Skip to content

Development Workflow

Jayden Smith edited this page Sep 11, 2026 · 8 revisions

Development Workflow

These commands apply to 2.x development. Choose targeted commands for the layer you changed; native test and device commands require the generated Rust artifacts for their platform.

Install and inspect

npm install
npm --prefix example install
npm run typecheck
npm run typecheck:example

The example uses Expo Continuous Native Generation. Treat example/ios/ and example/android/ as disposable generated output; change example/app.config.ts or the package config plugin. Start or run it with:

npm run start:example
npm run run:example:ios
npm run run:example:android

The platform run commands regenerate the corresponding native project before building and launching. For JS-only iteration after a native build, use start:example. To regenerate both projects explicitly:

npm run prebuild:example

Build JavaScript and Rust artifacts

npm run build
npm run build:rust
npm run build:rust:ios
npm run build:rust:android

build:rust first regenerates UniFFI Swift/Kotlin bindings, then builds iOS and Android artifacts. The repository resolves Rust 1.95.0 through rust/toolchain.sh. The iOS build creates and copies ios/EditorCore.xcframework; Android builds arm64-v8a, armeabi-v7a, x86, and x86_64 shared libraries under rust/android.

The iOS flow needs the corresponding Rust iOS targets and Xcode command-line tools. The Android flow needs cargo-ndk, the corresponding Rust Android targets, and an Android NDK available to cargo-ndk. Native test wrappers stop early with a build:rust:ios or build:rust:android instruction when their required artifacts are missing.

Optional highlighting package

The core Rust build does not build the separately installed syntax-highlighting provider. From a source checkout, build its native assets and JavaScript separately:

npm --prefix packages/code-highlighting run build:native
npm --prefix packages/code-highlighting run build
npm --prefix packages/code-highlighting run test:rust

The native build regenerates the addon's bindings and iOS/Android artifacts. Packaged consumers receive these artifacts and do not need Cargo; contributors changing the provider need the corresponding native toolchains. See Code Syntax Highlighting.

Package preparation

npm run sync:version
npm run validate:security
npm run validate:package
npm run prepare:publish

prepare:publish runs version synchronization, source security validation, full Rust/binding build, TypeScript build, and packed-package/CocoaPods validation. Use it when preparing a release candidate; it is more than a JavaScript build.

TypeScript and static package checks

npm test
npm run test:rust
npm run validate:security
npm run validate:package

npm test runs Jest in-band with Watchman disabled. validate:security executes the security-contract validator. validate:package lints Swift and Kotlin sources, then checks the viewer cutover, release security behavior, generated bindings, XCFramework contents, packed package, and publish lifecycle.

Native source linting

npm run lint:ios
npm run lint:kotlin
npm run format:kotlin

lint:ios and lint:kotlin gate every release: CI runs them per pull request and the publish workflow runs them again before the package is published. Both download a pinned, checksum-verified linter into .tmp on first use, so local and CI results match. lint:ios requires macOS. format:kotlin auto-corrects most ktlint findings.

Rust benchmarks

npm run benchmark:rust
npm run benchmark:rust:quick
npm run benchmark:rust:yrs
npm run benchmark:rust:yrs:quick
npm run benchmark:rust:yrs:check
npm run benchmark:rust:yrs:editing
npm run benchmark:rust:yrs:editing:check

The quick variants pass the benchmark harness quick flag. The two check commands run the selected benchmark and compare it with the checked-in baseline.

Android commands

npm run build:android:library
npm run test:android
npm run test:android:api24
npm run test:android:performance
npm run build:android:example
npm run test:android:device
npm run test:android:device:ime
npm run test:android:device:performance

build:android:library compiles the library Kotlin target. test:android runs the library unit tests through the generated example Gradle project; test:android:performance selects NativePerformanceTest. test:android:api24 runs the connected API 24 smoke-test class and needs a suitable emulator/device. build:android:example builds the example debug APK. The device commands run connected instrumentation tests; set ANDROID_DEVICE_ID or ANDROID_SERIAL, or use example/.android-device-test.env. The IME and performance device variants select their corresponding test classes.

iOS commands

npm run test:ios
npm run test:ios:performance
npm run test:ios:device
npm run test:ios:device:performance

The iOS wrapper runs the CocoaPods workspace, not a raw Xcode project, so ExpoModulesCore stays in the build graph. It can select a booted simulator, a named simulator via IOS_SIMULATOR_NAME, an exact IOS_DESTINATION, or a physical IOS_DEVICE_ID. Physical runs also need IOS_DEVELOPMENT_TEAM; the device wrapper can load both values from ios-tests/.device-test.env. Pass a focused XCTest selector after --.

npm run test:ios -- -only-testing:NativeEditorTests/RenderBridgeTests

If ios-tests project inputs change, regenerate and install its workspace before running:

cd ios-tests
xcodegen generate
pod install

Change-to-command guide

Changed area Useful follow-up
packages/code-highlighting provider Its build:native, build, and test:rust scripts, then an app rebuild and focused platform checks.
src public API, types, component binding npm run typecheck; relevant Jest test.
rust/editor-core semantics or FFI npm run build:rust, then relevant native/package validation.
Generated bindings / native ABI npm run build:rust and npm run validate:package.
Android editor or viewer implementation npm run build:android:library, then unit/device coverage appropriate to the change.
iOS editor or viewer implementation npm run test:ios with a focused selector where possible.
Example configuration/native dependencies npm run prebuild:example, then run the required platform.

For public-API behavior see Document API Reference; for platform boundaries see Architecture.

Clone this wiki locally