Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions config/docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,34 @@
'mobile' => [
4 => [
'the-basics/native-components' => 'the-basics/native-ui',
'the-basics/dialog' => 'the-basics/dialogs',
'getting-started/deployment' => 'publishing/introduction',
'plugins/vibe' => 'digging-deeper/websockets',

// Concepts section renamed to Digging Deeper
'concepts/authentication' => 'digging-deeper/authentication',
'concepts/databases' => 'digging-deeper/databases',
'concepts/deep-links' => 'digging-deeper/deep-links',
'concepts/push-notifications' => 'digging-deeper/push-notifications',
'concepts/queues' => 'digging-deeper/queues',
'concepts/security' => 'digging-deeper/security',

// SuperNative overview page now lives in the Architecture section
'super-native/introduction' => 'architecture/super-native',

// Some SuperNative pages moved into The Basics
'super-native/navigation' => 'the-basics/routing',
'super-native/layouts' => 'the-basics/layouts',
'super-native/events' => 'the-basics/events',

// Remaining SuperNative pages flattened into the Digging Deeper section
'super-native/lifecycle-hooks' => 'digging-deeper/lifecycle-hooks',
'super-native/data-binding' => 'digging-deeper/data-binding',
'super-native/reactivity' => 'digging-deeper/reactivity',
'super-native/theming' => 'digging-deeper/theming',
'super-native/gestures' => 'digging-deeper/gestures',
'super-native/search' => 'digging-deeper/search',
'super-native/accessibility' => 'digging-deeper/accessibility',
],
],
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ the stores. You should consult the [App Store Connect Help](https://developer.ap
[Play Console Help](https://support.google.com/googleplay/android-developer/?hl=en-GB#topic=3450769) documentation for
detailed and up-to-date guidance on how to prepare your app submissions and listings.

If you want more hands-on support, we happily work with our [Partners](/partners) to support them releasing their apps.
If you want more [hands-on support](/consulting), we happily work with our [Partners](/partners) to support them releasing their apps.

</aside>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ the stores. You should consult the [App Store Connect Help](https://developer.ap
[Play Console Help](https://support.google.com/googleplay/android-developer/?hl=en-GB#topic=3450769) documentation for
detailed and up-to-date guidance on how to prepare your app submissions and listings.

If you want more hands-on support, we happily work with our [Partners](/partners) to support them releasing their apps.
If you want more [hands-on support](/consulting), we happily work with our [Partners](/partners) to support them releasing their apps.

</aside>

Expand Down
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/architecture/_index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
title: Architecture
order: 80
order: 10
---
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ title: About the New Architecture
order: 10
---

Since v1, NativePHP for Mobile has run your Laravel app on the device itself — no server, no network round-trip. In
v3 and earlier, your app's UI rendered as HTML inside a web view. That model is productive and familiar, and it's
[still fully supported](../super-native/introduction#is-the-web-view-still-an-option). But it puts a browser between
NativePHP for Mobile runs your Laravel app on the device itself — no server, no network round-trip. Traditionally,
your app's UI rendered as HTML inside a web view. That model is productive and familiar, and it's
[still fully supported](../architecture/super-native#is-the-web-view-still-an-option). But it puts a browser between
your app and the platform, and some things can only feel truly native when they *are* native.

The new architecture — [SuperNative](../super-native/introduction) — removes that layer entirely. Your screens are
The new architecture — [SuperNative](../architecture/super-native) — removes that layer entirely. Your screens are
real SwiftUI and Jetpack Compose views, created and updated directly by your PHP code. Here's why we built it, and
what it changes.

Expand Down Expand Up @@ -68,8 +68,8 @@ app faster. If your app is happy in the web view, it will keep working exactly a

## Should you use it today?

SuperNative is **the default** in v4: new apps render native screens from the very first route. It's in beta, so
expect rapid iteration — and if you'd rather wait, [opting out](../super-native/introduction#is-the-web-view-still-an-option)
SuperNative is **the default**: new apps render native screens from the very first route. It's in beta, so
expect rapid iteration — and if you'd rather wait, [opting out](../architecture/super-native#is-the-web-view-still-an-option)
is one route and one component.

Ready to go deeper? Start with [The Renderer](renderer).
2 changes: 1 addition & 1 deletion resources/views/docs/mobile/4/architecture/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Definitions for the terms used throughout the Architecture section.

## SuperNative

The engine behind native rendering in NativePHP for Mobile v4. It spans everything described in this section:
The engine behind native rendering in NativePHP for Mobile. It spans everything described in this section:
components, the render pipeline, the shared-memory boundary and the platform renderers.
[About the New Architecture](about-the-new-architecture) is the best starting point.

Expand Down
44 changes: 0 additions & 44 deletions resources/views/docs/mobile/4/architecture/overview.md

This file was deleted.

130 changes: 130 additions & 0 deletions resources/views/docs/mobile/4/architecture/super-native.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
title: SuperNative Introduction
order: 5
---

## What is SuperNative?

SuperNative is our name for a combination of technologies that enable PHP to produce platform-native UI at
blistering speeds.

While SuperNative uses HTML-like syntax, **there is no need for a web view**. Your apps built with Blade
can fully leverage the native components and performance of each platform's UI tools, directly from PHP — SwiftUI
on iOS and Jetpack Compose on Android.

Your app's screens are not web views rendering HTML. They are real, platform-native views, built and
updated by your PHP code. Same Laravel app, same Blade templates, two genuine native UIs.

You don't need to think about the right syntax for Android vs iOS, just use EDGE.

SuperNative is **the default**. New apps render native screens from the very first route — no configuration
required.

<aside>

Prefer to keep building with the web view? [Opting out](#is-the-web-view-still-an-option) of native UIs couldn't
be simpler.

</aside>

## What SuperNative is not

SuperNative is not a fully custom renderer, like Skia or Impeller. It does not attempt to create pixel-perfect
cross-platform user interfaces. Instead it *embraces* the differences and simply smooths over them with a single
consistent syntax.

It's not another virtual machine on top of or adjacent to PHP trying to convert *all* instructions to/from native
equivalents. It's explicitly focused on turning PHP objects that conform to a known interface into a fixed-length
byte array that can be processed by an explicit native-side interpreter.

It is also not a transpiler or HTML-to-native converter. We've built our own Blade engine that converts Blade components
into a simplified binary format instead of HTML ([The Renderer](renderer)) and passes the

## Try it now

The fastest way to see SuperNative is to run the demo app,
[`nativephp/super-native`](https://github.com/nativephp/super-native), on a simulator or device.

You'll need a working NativePHP for Mobile [development environment](../getting-started/environment-setup) first
(Xcode for iOS, Android Studio for Android). Then clone the demo, install it, and run it:

```shell
git clone https://github.com/nativephp/super-native
cd super-native
composer install
php artisan native:install
php artisan native:run
```

`native:run` builds the app and launches it on your connected device or simulator. Explore the source to see how
the screens are built, then start swapping in your own.

## How it works

SuperNative builds on three ideas working together:

- **Shared memory with PHP** — the native layer and your PHP application share memory directly, so there's no
network round-trip, no serialization overhead, and no waiting on a web view bridge. State changes flow between
PHP and the native UI almost instantly.
- **Livewire-like components** — each screen is driven by a PHP component class that holds its state and behavior,
just like a Livewire component. User interactions call your methods, your properties update, and the UI
re-renders to match.
- **Blade components for DX** — you define your UI with the same [EDGE component](../edge-components/introduction)
syntax you already know. Familiar, expressive Blade templates compile down to native SwiftUI and Compose views.

If you've built anything with Livewire, you already know how to build with SuperNative.

For a look under the hood — how Blade becomes SwiftUI and Compose, how state flows across the shared-memory
boundary, and the threading model behind it — see the rest of the [Architecture](about-the-new-architecture) section.

<aside>

You **don't** need to read any of this to build apps with NativePHP. If you're here to ship an app, start with the
[Quick Start](../getting-started/quick-start) and [The Basics](../the-basics/overview) instead. This section is for
the curious — and for plugin authors and contributors who want to understand the machinery they're building on.

</aside>

## Why SuperNative?

Two reasons above all:

- **Performance** — native views render and animate at full platform speed. No web view startup cost, no DOM, no
JavaScript bridge. Scrolling, transitions and gestures feel exactly the way users expect because they're powered
by the same UI frameworks every other native app uses.
- **Accessibility** — SwiftUI and Jetpack Compose come with the platform's accessibility support built in.
Screen readers, dynamic type, contrast settings and assistive controls work with your app out of the box,
rather than being approximated through a browser.

There's more detail [in this blog article](/blog/supernative).

## Is the web view still an option?

Yes, but instead of being the default, it's now a component that you add to a native view. To make your app behave
the same way that NativePHP for Mobile versions before v4 did, you can do something like this:

```php
// routes/mobile.php
Route::native('/home', WebViewScreen::class);

// webviewscreen.blade.php
<webview url="/" fullscreen />

// routes/web.php
Route::view('/', 'welcome');
```

Then just set `NATIVEPHP_START_URL=/home` in your `.env`.

This way your existing web view-based app can keep on working and you can start adopt SuperNative one screen at a time
whenever you're ready — or not at all.

## For Plugin Developers

SuperNative contains **no breaking changes** to our plugin architecture.

It actually expands what your plugins are capable of by giving you a standardized target for UI elements. That means your
plugins can ship fully native EDGE components that you know will work consistently for developers using your plugin.

No need to make your plugins UI-less abstractions or support multiple flavors of front-end tooling; simply create and ship
EDGE components and every consumer of your plugin will see the UI you intended.
4 changes: 0 additions & 4 deletions resources/views/docs/mobile/4/concepts/_index.md

This file was deleted.

4 changes: 4 additions & 0 deletions resources/views/docs/mobile/4/digging-deeper/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: Digging Deeper
order: 40
---
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ When writing migrations, you need to consider any special recommendations for wo
For example, prior to Laravel 11, SQLite foreign key constraints are turned off by default. If your application relies
upon foreign key constraints, [you need to enable SQLite support for them](https://laravel.com/docs/database#configuration) before running your migrations.

**It's important to test your migrations on [prod builds](/docs/mobile/1/getting-started/development#releasing)
**It's important to test your migrations on [prod builds](../publishing/introduction#releasing)
before releasing updates!** You don't want to accidentally delete your user's data when they update your app.

## Seeding data with migrations
Expand Down Expand Up @@ -117,7 +117,7 @@ If anything, you should provide a client key that **only** allows client apps to
authenticated your user, you can pass an access token back to your mobile app and use this for communicating with your
API.

Store these tokens on your users' devices securely with the [`SecureStorage`](/docs/mobile/1/apis/secure-storage) API.
Store these tokens on your users' devices securely with the [`SecureStorage`](../plugins/core/secure-storage) API.

It's a good practice to ensure these tokens have high entropy so that they are very hard to guess and a short lifespan.
Generating tokens is cheap; leaking personal customer data can get _very_ expensive!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,6 @@ the native side plays it locally on touch.

Three tools, three jobs: **`animate-*` props** for state-driven motion (a value changed — ease to it), **press
feedback** for instant touch response, and **shared values** for finger-tracking or refresh-rate animation. For
motion *between screens*, see [Navigation](navigation#custom-transitions).
motion *between screens*, see [Navigation](../the-basics/routing#custom-transitions).

</aside>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on top, **resumes** when those screens pop away, and is **unmounted** when it fi
## mount()

Runs **once**, right after the screen is pushed onto the stack. This is where you load the screen's initial data
and read any [route params or navigation data](../super-native/navigation#reading-params-and-data).
and read any [route params or navigation data](../the-basics/routing#reading-params-and-data).

```php
class ProductScreen extends NativeComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ NativePHP manages the worker lifecycle natively on both platforms.

## Things to Note

- The queue worker requires [ZTS (Thread-Safe) PHP](/docs/mobile/3/getting-started/changelog), which is included by default in v3.1+.
- The queue worker requires ZTS (Thread-Safe) PHP, which NativePHP includes by default.
- Only the `database` queue connection is supported. This uses the same SQLite database as your app.
- Jobs are persisted to the database, so they survive app restarts.
- If a job fails, Laravel's standard retry and failure handling applies.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ Accepted forms: `native:poll` (default 2s), `native:poll="500ms"` / `native:poll
<aside>

Polling drives a full re-render, so keep intervals as long as the UX allows. For push-style updates that arrive
when something actually happens rather than on a timer, listen for an [event](events) instead.
when something actually happens rather than on a timer, listen for an [event](../the-basics/events) instead.

</aside>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A screen can present a native search bar in its navigation chrome and feed it fr
a **static** corpus the platform filters for you, and a **dynamic** handler you implement for server- or
database-backed results.

The search bar itself is shown by the [layout](layouts) chrome — via `NavBar::searchBar()` on a stack, or
The search bar itself is shown by the [layout](../the-basics/layouts) chrome — via `NavBar::searchBar()` on a stack, or
`Tab::search()` on a tab. This page covers the component side: producing the results.

## Static search
Expand Down Expand Up @@ -59,7 +59,7 @@ Or as a dedicated search tab:
Tab::search('Search', icon: 'magnifyingglass', placeholder: 'Find anything');
```

See [Layouts](layouts) for where these builders live and how a layout wraps a screen.
See [Layouts](../the-basics/layouts) for where these builders live and how a layout wraps a screen.

<aside>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
---
title: Vibe (Websockets)
order: 250
title: WebSockets
order: 350
---

<aside>

WebSockets functionality is provided by the (free) [Vibe plugin](../plugins/core/vibe). To use this feature, you must
install the `nativephp/mobile-vibe` Composer package.

</aside>

## Overview

Vibe brings live server events into your NativePHP Mobile app over the **Pusher protocol** — so it works with
Expand Down Expand Up @@ -149,7 +156,7 @@ Vibe::withToken($freshToken);

<aside>

Store tokens with the [SecureStorage](./core/secure-storage) plugin so they live in the device keychain/keystore rather
Store tokens with the [SecureStorage](../plugins/core/secure-storage) plugin so they live in the device keychain/keystore rather
than in plain application state.

</aside>
Expand Down Expand Up @@ -364,7 +371,7 @@ Presence only. Runs when a member leaves.

- **Foreground-only:** Websockets are foreground-only on mobile. The OS suspends the socket when your app goes to the
background. For delivery while the app is closed, use push notifications via the
[Firebase plugin](./core/firebase).
[Firebase plugin](../plugins/core/firebase).
- **Liveness, not source of truth:** Treat websocket events as a *liveness* signal, not authoritative state. On
reconnect, refetch the canonical data from your backend.
- **Auto-teardown:** Subscriptions are removed automatically when the component unmounts. Leaving a screen leaves its
Expand Down
Loading
Loading