This guide covers how to integrate GutenbergKit into your iOS or Android app. If you are instead interested in integrating GutenbergKit into the WordPress-iOS or WordPress-Android apps, see the WordPress App Integration guide.
- Platform: iOS 17+ / macOS 14+
- Dependencies (automatically resolved via Swift Package Manager):
- Platform: minSdk 24 (Android 7.0), targetSdk 34
- Dependencies (managed via Gradle):
androidx.webkit:webkit- Enhanced WebView featurescom.google.code.gson:gson- JSON serializationkotlinx-coroutines-android- Async operations
Add GutenbergKit as a Swift Package dependency in Xcode:
- Go to File → Add Package Dependencies...
- Enter the GutenbergKit repository URL
- Select the
GutenbergKitlibrary product
Note: The Package.swift is at the repository root, not in the ios/ directory.
Create an EditorViewController with a configuration:
import GutenbergKit
let configuration = EditorConfigurationBuilder(
postType: "post",
siteURL: URL(string: "https://example.com")!,
siteApiRoot: URL(string: "https://example.com/wp-json")!
)
.setTitle("My Post")
.setContent("<!-- wp:paragraph --><p>Hello world</p><!-- /wp:paragraph -->")
.setAuthHeader("Bearer your-token")
.build()
let editorViewController = EditorViewController(configuration: configuration)
editorViewController.delegate = selfThe EditorConfigurationBuilder provides many options for customizing the editor. See EditorConfiguration.swift for all available options.
Implement EditorViewControllerDelegate to handle editor events:
extension YourViewController: EditorViewControllerDelegate {
func editorDidLoad(_ viewController: EditorViewController) {
// Editor finished loading
}
func editor(_ viewController: EditorViewController, didUpdateContentWithState state: EditorState) {
// Content changed - state.isEmpty indicates if editor is empty
}
func editor(_ viewController: EditorViewController, didUpdateHistoryState state: EditorState) {
// Undo/redo state changed - use state.hasUndo and state.hasRedo
}
func editor(_ viewController: EditorViewController, didRequestMediaFromSiteMediaLibrary config: OpenMediaLibraryAction) {
// User requested media picker - present your media library UI
}
func editor(_ viewController: EditorViewController, didEncounterCriticalError error: Error) {
// Handle critical errors
}
}// Set content
editorViewController.setContent("<!-- wp:paragraph --><p>New content</p><!-- /wp:paragraph -->")
// Get content
let content = try await editorViewController.getContent()
// Get title and content together
let result = try await editorViewController.getTitleAndContent()
print("Title: \(result.title), Content: \(result.content)")Pre-warm the editor for faster first load:
// Call early in your app lifecycle
EditorViewController.warmup(configuration: configuration)For the fastest loading, pre-fetch dependencies:
let service = EditorService(configuration: configuration)
let dependencies = try await service.prepare { progress in
print("Loading: \(progress.fractionCompleted * 100)%")
}
// Pass dependencies for instant loading
let editorViewController = EditorViewController(
configuration: configuration,
dependencies: dependencies
)There are two ways to add GutenbergKit to your Android project:
Option 1: Maven dependency (recommended for production)
Add the Automattic Maven repository to your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://a8c-libs.s3.amazonaws.com/android")
}
}
}Then add the dependency to your build.gradle.kts:
dependencies {
implementation("org.wordpress.gutenbergkit:android:<version>")
}Option 2: Local module (for development)
Include the android/Gutenberg/ module directly in your project.
Create a GutenbergView and start the editor:
import org.wordpress.gutenberg.GutenbergView
import org.wordpress.gutenberg.EditorConfiguration
val gutenbergView = GutenbergView(context)
gutenbergView.initializeWebView()
val configuration = EditorConfiguration.builder()
.setTitle("My Post")
.setContent("<!-- wp:paragraph --><p>Hello world</p><!-- /wp:paragraph -->")
.setPostType("post")
.setSiteURL("https://example.com")
.setSiteApiRoot("https://example.com/wp-json")
.setAuthHeader("Bearer your-token")
.build()
gutenbergView.start(configuration)The EditorConfiguration.builder() provides many options for customizing the editor. See EditorConfiguration.kt for all available options.
Register listeners to handle editor events:
gutenbergView.setEditorDidBecomeAvailable { view ->
// Editor finished loading
}
gutenbergView.setContentChangeListener {
// Content changed
}
gutenbergView.setHistoryChangeListener { hasUndo, hasRedo ->
// Undo/redo state changed
}
gutenbergView.setOpenMediaLibraryListener { config ->
// User requested media picker
// config.allowedTypes, config.multiple, etc.
}
gutenbergView.setLogJsExceptionListener { exception ->
// Handle JavaScript exceptions
}// Set content
gutenbergView.setContent("<!-- wp:paragraph --><p>New content</p><!-- /wp:paragraph -->")
// Get title and content
gutenbergView.getTitleAndContent(
originalContent = "",
callback = object : TitleAndContentCallback {
override fun onResult(title: CharSequence, content: CharSequence) {
// Use title and content
}
},
completeComposition = true
)Pre-warm the editor for faster first load:
// Call early in your app lifecycle
GutenbergView.warmup(context, configuration)Enable asset caching for plugin and theme styles:
val configuration = EditorConfiguration.builder()
.setEnableAssetCaching(true)
.setCachedAssetHosts(setOf("example.com", "cdn.example.com"))
.build()Load custom blocks and editor assets from your site:
// iOS
let configuration = EditorConfigurationBuilder(...)
.setShouldUsePlugins(true)
.setEditorAssetsEndpoint(URL(string: "https://example.com/editor-assets")!)
.build()// Android
val configuration = EditorConfiguration.builder()
.setPlugins(true)
.setEditorAssetsEndpoint("https://example.com/editor-assets")
.build()Apply your site's theme styles to the editor. This requires valid editor settings (JSON) that provide theme style configuration (colors, typography, etc.) from your WordPress site's block editor settings endpoint (/wp-block-editor/v1/settings) or elsewhere.
// iOS
// Fetch editor settings JSON from your WordPress site
let editorSettingsJSON = try await fetchEditorSettings()
let configuration = EditorConfigurationBuilder(...)
.setShouldUseThemeStyles(true)
.setEditorSettings(editorSettingsJSON)
.build()// Android
// Fetch editor settings JSON from your WordPress site
val editorSettingsJSON = fetchEditorSettings()
val configuration = EditorConfiguration.builder()
.setThemeStyles(true)
.setEditorSettings(editorSettingsJSON)
.build()Some Gutenberg blocks and features use WordPress AJAX (admin-ajax.php) for functionality like form submissions. GutenbergKit supports AJAX requests when properly configured.
Requirements:
-
Production bundle required: AJAX requests fail with CORS errors when using the development server because the editor runs on
localhostwhile AJAX requests target your WordPress site. You must use a production bundle built withmake build. -
Configure
siteURL: ThesiteURLconfiguration option must be set to your WordPress site URL. This is used to construct the AJAX endpoint ({siteURL}/wp-admin/admin-ajax.php). On Android, the editor is served from the site's domain so that AJAX requests are same-origin. -
Set authentication header: The
authHeaderconfiguration must be set. GutenbergKit injects this header into all AJAX requests since the WebView lacks WordPress authentication cookies.
Configuration examples:
// iOS
let configuration = EditorConfigurationBuilder(
postType: "post",
siteURL: URL(string: "https://example.com")!,
siteApiRoot: URL(string: "https://example.com/wp-json")!
)
.setAuthHeader("Bearer your-token")
.build()// Android
val configuration = EditorConfiguration.builder(
siteURL = "https://example.com",
siteApiRoot = "https://example.com/wp-json"
)
.setPostType("post")
.setAuthHeader("Bearer your-token")
.build()