NativePHP v4: Build Real Native iOS and Android UI with Blade and SuperNative
Laravel #NativePHP #Laravel #Mobile #SwiftUI #Jetpack Compose #Blade

NativePHP v4: Build Real Native iOS and Android UI with Blade and SuperNative

4 min read Mohamed Said Mohamed Said

NativePHP v4 ships a feature called SuperNative that compiles Blade components into real SwiftUI views on iOS and Jetpack Compose views on Android. There is no web view involved, no HTML-to-native converter, and no virtual machine sitting alongside PHP. Simon Hamp and Shane Rosenthal unveiled it at The Vibes, a 100-person event in Boston on 30 July 2026, the day after Laracon US.

What SuperNative Actually Is

NativePHP built its own Blade engine that converts Blade components into a fixed-length binary byte array instead of HTML. An interpreter on the native side reads that representation and constructs the SwiftUI or Compose view tree directly. Because PHP and the native layer share memory, there is no network round-trip and no bridge serialisation on every interaction.

The component set is called EDGE (Element Definition and Generation Engine). Elements like <column> and <pressable> map to platform-native layout primitives, and Tailwind utility classes drive the layout rather than CSS.

Writing a SuperNative Screen

A screen is now a PHP class extending NativeComponent, not a web route returning HTML. Public properties hold state, public methods are actions, and attributes handle reactive behaviour:

class DeliveryTracker extends NativeComponent
{
    #[Locked]
    public int $deliveryId;

    public string $status = 'awaiting_pickup';

    #[Poll(5000)]
    public function syncFromDatabase(): void
    {
        $delivery = Delivery::findOrFail($this->deliveryId);
        $this->status = $delivery->status;
    }

    public function render(): View
    {
        return view('native.delivery-tracker');
    }
}

Routes live in routes/mobile.php and use a Route::native macro:

Route::native('/deliveries/{deliveryId}', DeliveryTracker::class)
    ->layout(DeliveryLayout::class)
    ->name('deliveries.show');

The Blade view uses native primitives styled with Tailwind:

<column class="flex-1 p-6 gap-4 bg-theme-background safe-area">
    <text class="text-2xl font-bold">{{ str($status)->headline() }}</text>
    <pressable @tap="confirmReceipt" class="px-6 py-4 rounded bg-theme-primary">
        <text class="text-theme-on-primary font-semibold">Confirm receipt</text>
    </pressable>
</column>

v4 also adds @pressDown and @pressUp for press-and-hold interactions.

Testing Without a Device

Because a screen publishes a tree rather than rendering pixels, you can test it in CI with Pest:

it('confirms receipt of a delivery', function () {
    $delivery = Delivery::factory()->create(['status' => 'out_for_delivery']);

    Native::visit("/deliveries/{$delivery->id}")
        ->assertSee('Out For Delivery')
        ->tap('Confirm receipt')
        ->assertSet('status', 'received');
});

php artisan native:make-test DeliveryTracker scaffolds the file. No simulator required.

Keeping Existing Web Views

You do not have to rewrite a v3 app. A web view is now a component inside a native screen:

<webview php url="/" fullscreen />

Each embedded web view gets its own PHP runtime and is not booted until a web route actually renders.

What Changed in v4.1

  • #[Locked] prevents two-way bindings from overwriting protected properties.
  • TreeObservers expose element trees for debugging and session recording tools.
  • TreeSpy testing utility lets tests assert on intermediate render frames.
  • NativeRouteFallback controls what a browser sees on a native-only route.
  • The Tailwind parser now warns about unsupported classes instead of silently ignoring them.

Upgrading from v3

The one breaking change is dependency-related. Device, Dialog, File, and System are now bundled in nativephp/mobile, so the four standalone plugin packages must be removed:

php artisan native:plugin:uninstall --core-v4
composer update
php artisan native:install --force

Facades and events are unchanged, so existing Dialog::alert() calls continue to work.

Key Takeaways

  • SuperNative compiles Blade to SwiftUI and Jetpack Compose—no web view, no bridge overhead.
  • Screens are PHP classes; templates are Blade; tests are Pest and run in CI without a simulator.
  • Web views still work and can be mixed with native screens one route at a time.
  • The only breaking change in v4 is removing four now-bundled plugin packages.
  • php artisan native:jump and the free Jump companion app let you preview on real hardware over Wi-Fi without Xcode or Android Studio.

Source: NativePHP v4: Build Native iOS and Android UI in Blade — Laravel News

Found this useful?

Frequently Asked Questions

3 questions
Q01 Does NativePHP v4 still support web views, or do I have to rewrite my app?
Web views are still fully supported in v4. A web view is now a `<webview>` component you embed inside a native screen rather than the entire app, so you can migrate one screen at a time while leaving the rest as-is.
Q02 What is the breaking change when upgrading from NativePHP v3 to v4?
The only breaking change is that the Device, Dialog, File, and System plugins are now bundled in `nativephp/mobile`. Composer will refuse to resolve until the four standalone packages are removed. Run `php artisan native:plugin:uninstall --core-v4`, then `composer update` and `php artisan native:install --force`.
Q03 Can I test SuperNative screens without a physical device or simulator?
Yes. Because a screen publishes an element tree rather than rendering pixels, the Pest test suite mounts components in-process using `Native::test()` or `Native::visit()`. Tests run in CI without a simulator or connected device.

Continue reading

More Articles

View all