- Getting Started
- Architecture
- The Basics
- Digging Deeper
-
EDGE Components
- Introduction
- Accordion
- Activity Indicator
- Badge
- Bottom Navigation
- Bottom Sheet
- Button
- Button Group
- Canvas
- Carousel
- Checkbox
- Chip
- Column
- Divider
- Floating Action Button
- Gesture Area
- Icon
- Image
- Lazy Grid
- Layout & Styling
- List
- Menus
- Modal
- Pressable
- Progress Bar
- Radio Group
- Refreshable
- Row
- Scroll View
- Select
- Shapes
- Side Navigation
- Slider
- Spacer
- Stack
- Tab Row
- Text
- Text Input
- Toggle
- Top Bar
- Virtual List
- Web View
- Plugins
- Testing
- Publishing Your App
Changelog
For changes prior to v4, see the v3 documentation.
4.2.0#
Released: August 14, 2026
What's Changed
- [Masterclass] Fix items-start/items-stretch inversion on iOS and max-w-* being dropped on both platforms by @shanerbaner82 in #313
- [Masterclass] Support per-corner and per-side border radius classes by @shanerbaner82 in #314
- [Masterclass] Dismiss the keyboard on tap for screens with native chrome by @shanerbaner82 in #315
- Use destructive theme color for native errors by @wojt-janowski in #295
- Fix glass elements ignoring their corner radius on iOS by @shanerbaner82 in #323
- Restore push notification badge clearing by @wojt-janowski in #294
- Ignore file URLs in DeepLinkRouter by @gwleuverink in #332
- Restore the video and audio MIME types the squash dropped by @gwleuverink in #328
- Restore the Android query string handling the SuperNative squash reverted by @gwleuverink in #327
- fix: forward flexDirection into layout — completes flex-row/flex-col by @shanerbaner82 in #270
Full Changelog: https://github.com/NativePHP/mobile-air/compare/4.1.0...4.2.0
4.1.0#
Released: August 7, 2026
What's Changed
- fix(ios): stop aliasing the plain "plus" icon to plus.circle.fill by @shanerbaner82 in #255
- fix: parse flex-row / flex-col direction utilities by @shanerbaner82 in #256
- feat: content-addressed callback ids by @shanerbaner82 in #257
- feat: TreeObservers — observe published trees, events, and navigation by @shanerbaner82 in #259
- feat: #[Locked] properties — bindings cannot write identity props by @shanerbaner82 in #260
- Remove deprecated flashlight method from System class by @simonhamp in #263
- fix: measure cross-axis size against the resolved main size by @simonhamp in #264
- fix(ios): recompute remaining space before placing justified children by @shanerbaner82 in #254
- feat: GatedBridge contract + FakeBridge capability deny-list by @shanerbaner82 in #258
- perf: cut hot reload latency and its variance by @simonhamp in #266
- feat(ios): implement UI.SetBackground for parity with Android by @shanerbaner82 in #277
- fix: hot reload permanently wedging when a trigger lands mid-reboot by @shanerbaner82 in #278
- feat: expose stored navigation configs on CallbackRegistry by @shanerbaner82 in #267
- feat: NativeRouteFallback — apps decide what a browser sees on native routes by @shanerbaner82 in #268
- feat: plugin-registered element attribute capture by @shanerbaner82 in #269
- Fix deep link delivery in native-ui (EDGE) apps on iOS by @shanerbaner82 in #282
- Restore the zip error detail lost by the SuperNative squash by @gwleuverink in #276
- fix(android): avoid resizing WebView for keyboard insets by @buseduran in #156
- feat(edge): dispatch screen lifecycle events from the navigation loop by @sylvesterdamgaard in #248
- Ship the real app name in CFBundleName (OAuth consent alert fix) by @shanerbaner82 in #285
- Fix top-bar background_color not rendering at the scroll edge (iOS) by @shanerbaner82 in #284
- Extend shows-indicators to refreshable and lazy-grid by @shanerbaner82 in #286
- Fix - Expose tree publication revisions on Android by @wojt-janowski in #280
- Port signed-zero inset anchoring from the dev core (parser + iOS + Android) by @shanerbaner82 in #288
- Port the background-layer core seams from the dev core (Android) by @shanerbaner82 in #287
- Honour
platforms, and stop copying SwiftPM manifests and test targets into the app target by @ICTtrying in #262 - Distinguish a locked device from a missing key in SecureStorage by @simonhamp in #283
- Make the Android plugin dependency block marker-delimited, so build.gradle.kts stops growing a comment per build by @ICTtrying in #271
- Add Tailwind aliases and unsupported class warnings by @wojt-janowski in #296
- fix(ios): stop mangling certificate passwords containing special characters by @shanerbaner82 in #210
- fix(plugins): copy Android plugin sources into a dedicated wiped source root by @simonhamp in #215
- Accept format v4 — event channel is a queue, and pin the binaries release by @simonhamp in #265
New Contributors
- @sylvesterdamgaard made their first contribution in #248
- @ICTtrying made their first contribution in #262
Full Changelog: https://github.com/NativePHP/mobile-air/compare/4.0.1...4.1.0
4.0.1#
Released: July 31, 2026
What's Changed
- Recreate the runtime directories Laravel needs in the bundle copy by @gwleuverink in #247
- Fold the runtime dir list onto BundleExclusions and guard it by name by @simonhamp in #249
- fix(ios): use persistent WKWebsiteDataStore so cookies survive cold launch by @sawan-webmavens in #140
- Fix: make iOS bundle extraction atomic and self-healing by @voicecode-bv in #153
- Substitute ${ENV_VAR} placeholders in Android plugin meta-data by @voicecode-bv in #167
New Contributors
- @sawan-webmavens made their first contribution in #140
Full Changelog: https://github.com/NativePHP/mobile-air/compare/4.0.0...4.0.1
4.0.0#
Released: July 30, 2026
What's Changed
- Fix: Remove stray tag by @martin-ro in #158
- SuperNative by @shanerbaner82 in #173
- fix(android): generate APP_KEY locally instead of booting PHP by @buseduran in #177
- Restore Android SDK versions config items by @unlocdavid in #171
- feat(testing): plugin-extensible test suite via FakeBridge macros by @shanerbaner82 in #182
- Handle target=_blank / window.open in the Android WebView by @shanerbaner82 in #180
- Fix fresh-install build failure with zero plugins by @shanerbaner82 in #179
- Fix navigation transition flicker and rebuild exit animations (two-layer swap) by @shanerbaner82 in #181
- fix: stale stack root shown during back transitions after leaving native chrome by @shanerbaner82 in #184
- feat(edge): @pressDown / @pressUp — touch-down and touch-up events by @shanerbaner82 in #185
- feat(edge): @pressDown/@pressUp events + fix Compose BOM 2025.12 compile break by @shanerbaner82 in #186
- Apply opacity before other modifiers so it fades the whole box by @shanerbaner82 in #192
- Bump Gradle wrapper to 8.14.5 in the Android template by @shanerbaner82 in #191
- Native-first boot: no WebView until a web route actually renders (Android + iOS) by @shanerbaner82 in #201
- Fix permanent re-extraction loop — bundle re-extracted on every cold boot by @shanerbaner82 in #195
- Fix persistent-boot corruption from concurrent extraction/artisan races by @shanerbaner82 in #196
- Fix crash when the app is backgrounded during deferred boot by @shanerbaner82 in #197
- Force R8 minification for profileable builds by @shanerbaner82 in #198
- Regenerate the Android baseline profile against the plugin-era dex layout by @shanerbaner82 in #199
- Fix silent install failure on version downgrade in native:run android by @shanerbaner82 in #200
- Move Firebase/google-services ownership from core template to plugins by @shanerbaner82 in #190
- Fix dropped plugin events on iOS native-direct boots (main) by @shanerbaner82 in #205
- LaravelBridge.localSend: dispatch-time local event channel by @shanerbaner82 in #206
- Android: Jump webview-forward session (port of iOS JumpWebViewSession) by @shanerbaner82 in #207
- feat(ios): dedicated PHP runtimes for embedded php-mode webviews by @simonhamp in #204
- Fix Pint 1.29 code style failures in CI by @simonhamp in #209
- fix(plugins): clean generated plugin copies before compiling by @simonhamp in #188
- feat(edge): raw-slot capture for <webview> + @navigated event wiring by @simonhamp in #189
- feat(edge): @tap alias family for @press events by @shanerbaner82 in #212
- Remove duplicate runtime blocks from nativephp config by @martin-ro in #208
- Fix release bundle cache handling by @WesWeCan in #194
- Add content transitions for in-place Text changes (numericText on iOS) by @simonhamp in #213
- fix: Windows and Linux compatibility across all CLI commands by @shanerbaner82 in #214
- fix: keep rapid tab re-taps from reverting to a stale slow render by @simonhamp in #216
- fix: iOS hot reload dropped in native-direct boots by @shanerbaner82 in #218
- docs: design-system guidance (theme tokens, font aliases, layouts) + parser regression tests by @shanerbaner82 in #219
- docs: teach the fonts 'default' alias as the app-wide font default by @shanerbaner82 in #220
- docs: fix self-referential @tap alias line in the migration table by @shanerbaner82 in #222
- chore: finish the @tap standardization across source, tests, and docs by @shanerbaner82 in #223
- IDE helper stub for the Route::native / nativeGroup / ->layout macros by @shanerbaner82 in #225
- Support negative margins and insets in the Tailwind parser by @shanerbaner82 in #230
- Feature/composable chrome and nested components by @shanerbaner82 in #227
- Add a v3 → v4 upgrade skill to the bundled Boost skills by @shanerbaner82 in #231
- Fix native chrome and flex layout bugs on iOS 26 and Android by @shanerbaner82 in #232
- feat(testing): make TestableComponent macroable for element test vocabulary by @shanerbaner82 in #233
- feat(edge): support <native:top-bar-title> in inline chrome by @shanerbaner82 in #234
- feat(ios): lock the interface style via nativephp.appearance by @shanerbaner82 in #235
- Readable labels for EDGE alignment (plus Concerns rename & comment cleanup) by @simonhamp in #224
- feat(edge): @selectionChange event delivers text-input caret/selection to PHP by @simonhamp in #221
- fix: suspend embedded webview PHP contexts across a runtime reboot by @simonhamp in #229
- Restore and consolidate the app bundle copy on BundleFileManager by @gwleuverink in #217
- Make native:watch interactive: sticky footer and a screen picker by @simonhamp in #240
- Simplify the install command's closing moment by @simonhamp in #242
- Restrict the testing suite's visible-text check to announced-text props by @shanerbaner82 in #244
- feat(plugins): offer a multiselect when native:plugin:uninstall gets no package by @shanerbaner82 in #211
New Contributors
- @martin-ro made their first contribution in #158
- @unlocdavid made their first contribution in #171
- @WesWeCan made their first contribution in #194
- @gwleuverink made their first contribution in #217
Full Changelog: https://github.com/NativePHP/mobile-air/compare/3.3.6...4.0.0
4.0.0-rc.1#
Released: July 15, 2026
What's Changed
- SuperNative — fully native UI powered by SwiftUI on iOS and Jetpack Compose on Android, and the new default for v4 apps
- Livewire-like native components — each screen is a PHP NativeComponent class holding its state and behavior, re-rendering the native UI as your properties change
- Shared memory between PHP and the native layer — no serialization overhead or web view bridge between your code and the UI
- Web view as a component — the classic web-view-first approach is now opt-out: render a single native route with a full-screen web view to keep building the v3 way
- Layouts — declare shared chrome (nav bars, tab bars) once in a NativeLayout class and attach it to a route or group of routes
- Native navigation stack — register screens with Route::native(), then push, pop, and replace them with native transitions
- Component testing suite — mount a NativeComponent, drive interactions, and assert on state and output entirely in-process, with no device or simulator
- Device, Dialog, File and System Plugins are now core built-ins —
nativephp/mobile-device,nativephp/mobile-dialog,nativephp/mobile-file, andnativephp/mobile-systemplugins have moved intonativephp/mobile. Remove the standalone plugins before upgrading (see the Upgrade Guide). The facades and events are unchanged, so no application code changes are needed. - The Vite dev server is now opt-in — native:run / native:watch no longer start Vite automatically. Pass --vite to enable JS/CSS HMR. The --no-vite flag still works but is now redundant. See Hot Reloading.
- Fix: Remove stray tag by @martin-ro in #158
New Contributors
- @martin-ro made their first contribution in #158
Full Changelog: https://github.com/NativePHP/mobile-air/compare/3.3.6...4.0.0-rc.1
NativePHP
Bring your
Laravel
skills to the
desktop.
Cloud Platform
Bifrost
Build your NativePHP apps
in the cloud.
Ship it!
Plans from $10/mo
Plugin Dev Kit
Build native plugins with
Claude Code
Learn More
NativePHP Ultra
All NativePHP plugins, teams & priority support from
$35/mo
Learn More
The Vibes
The unofficial Laracon US
Day 3
Grab Your Spot
Only 100 tickets!
The Masterclass
Go from zero to
published app
in no time
in no time
Learn More