pushinbr / pam-native
Build fast native Android and iOS applications with PHP and PAM.
Requires
- php: ^8.5
Requires (Dev)
None
Suggests
- pushinbr/pam-native-audio: Voice recorder (moved out of the core in 1.46: Pam\Native\Audio\AudioRecorder) and the headless audio player.
- pushinbr/pam-native-auth: Biometric authentication.
- pushinbr/pam-native-contacts: Device contacts and the SMS composer (moved out of the core in 1.46: Pam\Native\Contacts\Contacts, Sms).
- pushinbr/pam-native-drawer: Optional drawer navigation and native drawer host.
- pushinbr/pam-native-location: Device location (moved out of the core in 1.46: Pam\Native\Location\Location).
- pushinbr/pam-native-media: Media library, system capture and view capture.
- pushinbr/pam-native-notifications: Native notifications and push rendering.
- pushinbr/pam-native-sensors: Motion sensors (moved out of the core in 1.46: Pam\Native\Sensors\Sensors).
- pushinbr/pam-native-share-extension: Incoming shared content.
- pushinbr/pam-native-toast: Styled in-app toasts and variants.
- pushinbr/pam-native-webview: Hardened native embedded web pages.
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v1.46.34
- v1.46.33
- v1.46.32
- v1.46.31
- v1.46.30
- v1.46.29
- v1.46.28
- v1.46.27
- v1.46.26
- v1.46.25
- v1.46.24
- v1.46.23
- v1.46.22
- v1.46.21
- v1.46.20
- v1.46.19
- v1.46.18
- v1.46.17
- v1.46.16
- v1.46.15
- v1.46.14
- v1.46.13
- v1.46.12
- v1.46.11
- v1.46.10
- v1.46.9
- v1.46.8
- v1.46.7
- v1.46.6
- v1.46.5
- v1.46.4
- v1.46.3
- v1.46.2
- v1.46.1
- v1.46.0
- v1.45.1
- v1.45.0
- v1.44.0
- v1.43.1
- v1.43.0
- v1.42.1
- v1.42.0
- v1.41.0
- v1.40.0
- v1.39.4
- v1.39.3
- v1.39.2
- v1.39.1
- v1.39.0
- v1.38.1
- v1.38.0
- v1.37.1
- v1.37.0
- v1.36.0
- v1.35.0
- v1.34.1
- v1.34.0
- v1.33.1
- v1.33.0
- v1.32.1
- v1.32.0
- v1.31.0
- v1.30.1
- v1.30.0
- v1.29.2
- v1.29.1
- v1.29.0
- v1.28.0
- v1.27.1
- v1.27.0
- v1.26.0
- v1.25.4
- v1.25.3
- v1.25.2
- v1.25.1
- v1.25.0
- v1.24.0
- v1.23.1
- v1.23.0
- v1.22.7
- v1.22.6
- v1.22.5
- v1.22.4
- v1.22.3
- v1.22.2
- v1.22.1
- v1.22.0
- v1.21.0
- v1.20.2
- v1.20.1
- v1.20.0
- v1.19.1
- v1.19.0
- v1.18.0
- v1.17.0
- v1.16.1
- v1.16.0
- v1.15.0
- v1.14.2
- v1.14.1
- v1.14.0
- v1.13.3
- v1.13.2
- v1.13.1
- v1.13.0
- v1.12.2
- v1.12.1
- v1.12.0
- v1.11.1
- v1.11.0
- v1.10.0
- v1.9.1
- v1.9.0
- v1.8.0
- v1.7.0
- v1.6.1
- v1.6.0
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.37
- v1.0.36
- v1.0.35
- v1.0.34
- v1.0.33
- v1.0.32
- v1.0.31
- v1.0.30
- v1.0.29
- v1.0.28
- v1.0.27
- v1.0.26
- v1.0.25
- v1.0.24
- v1.0.23
- v1.0.22
- v1.0.21
- v1.0.20
- v1.0.19
- v1.0.18
- v1.0.17
- v1.0.16
- v1.0.15
- v1.0.14
- v1.0.13
- v1.0.12
- v1.0.11
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v0.10.0
- v0.9.2
- v0.9.1
- v0.8.9
- v0.8.8
- v0.8.5
- v0.8.4
- v0.8.2
- v0.8.1
- v0.8.0
- v0.7.0
- v0.6.78
- v0.6.77
- v0.6.73
- v0.6.70
- v0.6.69
- v0.6.68
- v0.6.67
- v0.6.65
- v0.6.64
- v0.6.63
- v0.6.62
- v0.6.61
- v0.6.60
- v0.6.59
- v0.6.58
- v0.6.57
- v0.6.56
- v0.6.55
- v0.6.53
- v0.6.52
- v0.6.51
- v0.6.50
- v0.6.49
- v0.6.48
- v0.6.47
- v0.6.46
- v0.6.45
- v0.6.44
- v0.6.43
- v0.6.42
- v0.6.41
- v0.6.40
- v0.6.39
- v0.6.38
- v0.6.37
- v0.6.36
- v0.6.35
- v0.6.34
- v0.6.33
- v0.6.32
- v0.6.31
- v0.6.30
- v0.6.29
- v0.6.28
- v0.6.27
- v0.6.26
- v0.6.25
- v0.6.24
- v0.6.23
- v0.6.22
- v0.6.21
- v0.6.20
- v0.6.19
- v0.6.18
- v0.6.17
- v0.6.16
- v0.6.15
- v0.6.14
- v0.6.13
- v0.6.12
- v0.6.11
- v0.6.10
- v0.6.9
- v0.6.8
- v0.6.7
- v0.6.6
- v0.6.5
- v0.6.4
- v0.6.3
- v0.6.2
- v0.6.1
- v0.6.0
- v0.5.94
- v0.5.93
- v0.5.92
- v0.5.91
- v0.5.90
- v0.5.89
- v0.5.88
- v0.5.87
- v0.5.86
- v0.5.85
- v0.5.84
- v0.5.83
- v0.5.82
- v0.5.81
- v0.5.80
- v0.5.79
- v0.5.78
- v0.5.77
- v0.5.76
- v0.5.75
- v0.5.74
- v0.5.73
- v0.5.72
- v0.5.71
- v0.5.70
- v0.5.69
- v0.5.68
- v0.5.67
- v0.5.66
- v0.5.65
- v0.5.64
- v0.5.63
- v0.5.62
- v0.5.61
- v0.5.60
- v0.5.59
- v0.5.58
- v0.5.57
- v0.5.56
- v0.5.55
- v0.5.54
- v0.5.53
- v0.5.52
- v0.5.51
- v0.5.50
- v0.5.49
- v0.5.48
- v0.5.47
- v0.5.46
- v0.5.45
- v0.5.44
- v0.5.43
- v0.5.42
- v0.5.41
- v0.5.40
- v0.5.38
- v0.5.37
- v0.5.36
- v0.5.35
- v0.5.34
- v0.5.33
- v0.5.32
- v0.5.31
- v0.5.30
- v0.5.29
- v0.5.28
- v0.5.26
- v0.5.25
- v0.5.24
- v0.5.23
- v0.5.22
- v0.5.21
- v0.5.20
- v0.5.19
- v0.5.18
- v0.5.17
- v0.5.16
- v0.5.15
- v0.5.14
- v0.5.13
- v0.5.12
- v0.5.11
- v0.5.10
- v0.5.9
- v0.5.8
- v0.5.7
- v0.5.6
- v0.5.5
- v0.5.4
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- v0.4.8
- v0.4.7
- v0.4.6
- v0.4.5
- v0.4.4
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4.0
- v0.3.0
- v0.2.1
- dev-feat/r34-platform-media
- dev-fix/r35-rows
- dev-fix/r34-ios
- dev-fix/r32-android
- dev-fix/r31-android
- dev-fix/r30-android
- dev-fix/r29-android
- dev-perf/r27-android
- dev-fix/ios-r26-audio
- dev-fix/ios-r25
- dev-perf/r24-android
- dev-fix/list-anchor-end
- dev-release/1.46.25
- dev-fix/ios-r21-parity
- dev-release/1.46.24
- dev-fix/ios-r17-parity
- dev-port4/r19-android-fw
- dev-port4/r18-android-fw
- dev-port4/r16-android-fw
- dev-fix/ios-r15-story-open
- dev-port4/r14-android-fw
- dev-fix/ios-r12-dynamic-type
- dev-fix/ios-r12-parity
- dev-port4/r11-android-fw
- dev-port4/r10-android-fw
- dev-port4/responsive-fw
- dev-release/1.46.17
- dev-fix/ios-r8-zoom-sheet
- dev-port4/r9-android-fw
- dev-fix/press-move-cancels-long-press
- dev-port4/r8-android-fw
- dev-fix/sheet-keyboard-lift
- dev-port4/r7-android-fw
- dev-fix/android-modal-navbar-focus
- dev-fix/android-glide-duration-reset
- dev-integrate/port3-20261027
- dev-feat/ios-r5-20261031
- dev-codex/p1-fw
- dev-ios-port-fix6
- dev-ios-port-fix5
- dev-ios-port-fix4
- dev-ios-port-fix3
- dev-ios-port-fix2
- dev-fix/android-paint-order
- dev-feat/ios-port-20261029
- dev-feat/ios-port-modal-20261029
- dev-debug/port4-ellipsis-probe2
- dev-feat/port4-text-precision-20261029
- dev-debug/port4-text-probe-20261029
- dev-feat/port4-pressable-nested-20261029
- dev-feat/port4-yoga-relative-rounding-20261029
- dev-feat/port4-text-height-ceil-20261029
- dev-feat/port4-stretch-max-width-20261029
- dev-feat/port4-input-font-ceil-20261029
- dev-feat/port4-single-line-ellipsis-20261029
- dev-feat/port4-indicator-color-20261029
- dev-fix/port4-render-diff-20261028
- dev-feat/port4-feed-scroll-20261028
- dev-feat/port4-modal-shared-20261028
- dev-feat/port4-shared-element-20261028
- dev-parity-bubbles/fw-20261028
- dev-fix/focus-after-mount
- dev-feat/port4-chat-wallpaper-20261027
- dev-feat/port4-chat-scroll-20261028
- dev-codex/inbox-resource-framework
- dev-codex/u3-i18n-plugin
- dev-feat/port4-core-slim-20261027
- dev-feat/arch-v2-routing-http-20261027
- dev-feat/arch-v2-core-20261027
- dev-feat/port4-perf-20261027
- dev-feat/port4-gaps-20261027
- dev-feat/port4-anim-20261027
- dev-feat/port4-ui-polish-20261027
- dev-feat/port4-layout-apis-20261027
- dev-feat/port4-reels-surface-20261027
- dev-feat/port4-protocolo-20261027
- dev-feat/port4-ios-sobras-20261027
- dev-feat/port4-fila-critica-20261027
- dev-feat/ios-app-build-20261026
- dev-feat/port3-jogos-core-20261027
- dev-feat/port3-criar-post-20261027
- dev-feat/port3-chat-20261027
- dev-feat/port3-reels-20261027
- dev-feat/port3-notificacoes-push-20261027
- dev-feat/port3-notificacoes-20261027
- dev-feat/port3-loop-editor-20261027
- dev-feat/ios-runtime-20261026
- dev-feat/ios-push-20261026
- dev-feat/ios-media-20261026
- dev-feat/ios-complete-20261024
- dev-release/1.44.0
- dev-fix/ui-polish
- dev-perf/x20-145
- dev-fix/critical-20261014
- dev-fix/sheet-safe-area
- dev-perf/x20-native-encoder
- dev-perf/x20-list-window
- dev-fix/storage-keys
- dev-fix/perf-idle-wakeups
- dev-release/1.43.1
- dev-fix/component-root-props
- dev-fix/zoom-viewer
- dev-release/1.43.0
- dev-fix/php-exit-crash
- dev-release/1.42.0
- dev-fix/covered-routes
- dev-release/1.41.0
- dev-release/1.40.0
- dev-release/1.39.4
- dev-release/1.39.3
- dev-fix/retired-ime-owner-20261013
- dev-fix/ios-sheet-viewport
- dev-fix/sheet-ime-viewport
- dev-fix/zindex-host-parity
- dev-release/1.39.2-parity
- dev-fix/hidden-input-ime-20261013
- dev-fix/activity-retained-events-20261013
- dev-wip/pam-native-local-2026-10-05
- dev-fix/debug-id-firebase-safety
- dev-release/1.0.37
- dev-perf/renderer-commit-work
- dev-release/1.0.36
- dev-feat/files-large-document-pick
- dev-release/1.0.35
- dev-feat/zechat-authoring-debug-id
- dev-release/v1.0.34-ios-reader
- dev-perf/ios-binary-reader-scalars
- dev-release/v1.0.33-20261004
- dev-feat/ios-incoming-share-20261004
- dev-feat/ios-files-parity-20261004
- dev-feat/ios-core-parity-20261004
- dev-audit/native-ui-candidate-20260914
- dev-fix/intrinsic-text-cross-width
- dev-fix/ci-immutable-checkout-ref
- dev-codex/premium-ui-native-gates
- dev-release/1.0.25
- dev-fix/macrobenchmark-kotlin-runtime
- dev-release/1.0.24
- dev-fix/android-install-session-recovery
- dev-release/1.0.21
- dev-feat/sensitive-clipboard
- dev-release/1.0.20
- dev-feat/files-sha256
- dev-feat/http-file-upload
- dev-fix/ios-http-redirects
- dev-fix/vscode-reproducible-package
- dev-release/1.0.19
- dev-fix/notification-permission-failure
- dev-release/1.0.18
- dev-fix/dynamic-font-metrics
- dev-release/1.0.17
- dev-fix/mobile-bundle-ignore
- dev-fix/vscode-php-components
- dev-fix/release-ref-name-1.0.16
- dev-feat/visual-dom-1.0
- dev-fix/release-workflow-dispatch
- dev-fix/mandatory-build-cleanup
- dev-perf/offensive-0.10
This package is auto-updated.
Last update: 2026-11-02 21:38:10 UTC
README
PAM Native
Build real Android and iOS applications with typed PHP.
A Rust reconciler, retained native renderer, signals, navigation, UI-thread motion, and modular platform capabilities—with no JavaScript runtime or WebView.
Documentation · Why this exists · What you can build · Quick start · Issues
Why this exists
A Rust reconciler, retained native renderer, signals, navigation, UI-thread motion, and modular platform capabilities—with no JavaScript runtime or WebView.
| Role | Native mobile product |
| Execution path | PHP 8.5 · Rust · Android Views · UIKit |
| This repository owns | Native project workflow, renderer, navigation, state, protocol, and plugin ABI |
| Boundary | Camera, video, maps, payments, and other capabilities remain focused packages |
What you can build
- Production phone and tablet applications
- TV, foldable, keyboard, pointer, and D-pad experiences
- Media, social, commerce, and offline-first products assembled from focused modules
Quick start
pam init my-app --template native
cd my-app
pam composer require pushinbr/pam-native
pam doctor --fix
pam dev
The PAM documentation covers prerequisites, production setup, and the complete workflow. PAM projects keep normal manifests and lockfiles; product features stay in the package that owns them.
Every build follows the mandatory build hygiene contract:
final APK/AAB/IPA/app deliverables are preserved in dist, while regenerable
Gradle, Cargo and Xcode intermediates are removed when the command exits.
Device bundles keep the PHP SDK and its resources; the SDK's native host sources
and documentation stay on the development machine.
PAM Native lets PHP developers ship native mobile applications without adding a JavaScript runtime or turning the app into a website inside a WebView.
Write familiar PHP components, state, actions, and Laravel-inspired named routes. PAM keeps your PHP application alive, reconciles its interface in Rust, and renders real UIKit and Android controls.
See it in action
<?php use App\Screens\HomeScreen; use App\Screens\ProductScreen; use Pam\Native\App; use Pam\Native\Routing\Route; App::run( Route::stack('main', initial: 'home', routes: function (): void { Route::screen('home', HomeScreen::class); Route::screen('product', ProductScreen::class); }), );
It feels familiar because it is
Use explicit PHP trees when you want complete control:
return Screen::make( SafeAreaView::make( Column::make( Text::make('Your cart')->style(new Style(fontSize: 28)), Text::make("{$this->items} items"), Button::make('Checkout')->onPress($this->checkout(...)), )->style(new Style(padding: 24, gap: 16)), ), );
Or use single-file components when template authoring is a better fit:
final class Counter extends Component { #[State] public int $count = 0; #[\Pam\Native\Attributes\Action] public function increment(): void { $this->count++; } } ?> <template language="2"> <Column class="card"> <Text class="title">Count: {{ $count }}</Text> <Button label="Increment" @press="increment" /> </Column> </template> <style scoped> .card { padding: 24px; gap: 16px; } .title { font-size: 28px; font-weight: 700; } </style>
Both styles compile to the same typed retained tree. Scoped styles become native properties; they are not browser CSS.
Language 2 adds typed tag/event/slot contracts, native interaction states,
compiled tokens and recipes, viewport/container queries, declarative flow and
async branches, stable virtual-list identity, compositor keyframes,
accessibility diagnostics, Composer-extensible tags and a full editor-neutral
LSP. Attributes such as #[Prop] and #[Action] remain the canonical PHP API.
Read the UI Language 2 guide.
Lists and scroll views take React Native's pull to refresh directly
(:refreshing, on:refresh, tintColor, refreshColors) with the platform
indicator on each side: see Pull to refresh.
Need precise imperative control without introducing a browser runtime? The Visual DOM adds indexed selectors, atomic tree mutations, events, native animation and asynchronous layout observation directly on the same retained PHP → Rust → Android/UIKit pipeline.
A complete app (architecture v2)
A small chat app shows the whole architecture: globals, routes, middleware,
composables and screens that use only setup(). The full reference is
Architecture v2.
index.php
routes.php
src/
Api/Api.php
Composables/useAuth.php
Middleware/Authenticate.php
Screens/LoginScreen.pam.php
Screens/ChatsScreen.pam.php
Screens/ChatScreen.pam.php
index.php boots the app. The globals are visible in every template and
component.
<?php use App\Middleware\Authenticate; use Pam\Native\App; use function App\Composables\useAuth; use function Pam\Native\{useColorScheme, useSafeAreaInsets, useNetwork}; require __DIR__.'/vendor/autoload.php'; App::globals([ 'scheme' => useColorScheme(), 'insets' => useSafeAreaInsets(), 'online' => useNetwork(), 'auth' => useAuth(), ]); App::middleware(['auth' => Authenticate::class]); App::run(require __DIR__.'/routes.php');
routes.php declares typed, Laravel-style routes. The {id} parameter
arrives in ChatScreen::setup(string $id).
<?php use App\Screens\{ChatScreen, ChatsScreen, LoginScreen}; use Pam\Native\Route; Route::screen('/login', LoginScreen::class)->name('login'); Route::middleware('auth')->group(function () { Route::screen('/chats', ChatsScreen::class)->name('chats'); Route::screen('/chat/{id}', ChatScreen::class)->name('chat'); });
src/Api/Api.php is the app's HTTP client, with the JWT and 401
interceptors.
<?php namespace App\Api; use Pam\Native\Http\{Http, HttpClient, HttpError, Request}; use function App\Composables\useAuth; final class Api { private static ?HttpClient $client = null; public static function client(): HttpClient { return self::$client ??= Http::create(baseUrl: 'https://api.example.com') ->onRequest(fn (Request $request) => ($token = useAuth()->token->value) !== null ? $request->withToken($token) : $request) ->onError(function (HttpError $error) { if ($error->status === 401) { useAuth()->logout(); } throw $error; }); } }
src/Composables/useAuth.php is an app composable: shared state, a token
kept in SecureStorage, and navigation on login and logout.
<?php namespace App\Composables; use App\Api\Api; use Pam\Native\Signals\Signal; use Pam\Native\Storage\SecureStorage; use function Pam\Native\{navigate, signal}; final class Auth { /** @param Signal<?string> $token @param Signal<?array> $user */ public function __construct(public readonly Signal $token, public readonly Signal $user) { SecureStorage::get('token', fn (?string $saved) => $this->token->value = $saved); } public function login(string $email, string $password): void { Api::client()->post('/login', ['email' => $email, 'password' => $password]) ->then(function ($response) { $this->token->value = $response->json()['token']; $this->user->value = $response->json()['user']; SecureStorage::set('token', $this->token->value); navigate('chats'); }); } public function logout(): void { $this->token->value = null; $this->user->value = null; SecureStorage::delete('token'); navigate('login'); } } function useAuth(): Auth { static $auth = null; return $auth ??= new Auth(signal(null), signal(null)); }
src/Middleware/Authenticate.php sends signed-out users to the login
screen.
<?php namespace App\Middleware; use Closure; use Pam\Native\{Middleware, Route}; use function App\Composables\useAuth; use function Pam\Native\redirect; final class Authenticate implements Middleware { public function handle(Route $to, Closure $next): mixed { return useAuth()->token->value !== null ? $next($to) : redirect('login'); } }
src/Screens/ChatsScreen.pam.php is a paginated, cached list that
refreshes when the screen is focused again. Theme, safe area and connectivity
come from the globals.
<?php namespace App\Screens; use App\Api\Api; use Pam\Native\Component; use Pam\Native\Composables\Resource; use function Pam\Native\{navigate, useResource}; final class ChatsScreen extends Component { public Resource $chats; public function setup(): void { $this->chats = useResource( fn (?string $cursor) => Api::client()->get('/chats', ['cursor' => $cursor])->json(), paginate: true, refreshOnFocus: true, cache: 'chats', ); } public function open(int $id): void { navigate('chat', ['id' => $id]); } public function refresh(): void { $this->chats->reload(); } public function more(): void { $this->chats->more(); } } ?> <template> <Column class="screen" :class="['dark' => $scheme.dark]" :paddingTop="$insets.top"> <Text p-if="!$online.value" class="offline">You are offline</Text> <VirtualizedList :refreshing="$chats.refreshing" on:refresh="refresh" on:endReached="more"> <Pressable p-for="$chat in $chats.data" :key="$chat['id']" @press="open($chat['id'])"> <Text class="title">{{ $chat['title'] }}</Text> </Pressable> </VirtualizedList> <View :height="$insets.bottom" /> </Column> </template>
src/Screens/ChatScreen.pam.php receives the route parameter, follows
the keyboard and sends messages optimistically.
<?php namespace App\Screens; use App\Api\Api; use Pam\Native\Component; use Pam\Native\Composables\{KeyboardState, Resource}; use function Pam\Native\{onBlur, useKeyboard, useResource}; final class ChatScreen extends Component { public string $id; public string $draft = ''; public Resource $messages; public KeyboardState $keyboard; public function setup(string $id): void { $this->id = $id; $this->keyboard = useKeyboard(); $this->messages = useResource( fn (?string $cursor) => Api::client()->get("/chats/{$id}/messages", ['cursor' => $cursor])->json(), paginate: true, cache: "chat:{$id}", ); onBlur(fn () => $this->keyboard->dismiss()); } public function send(): void { $tmp = ['id' => 'tmp-'.bin2hex(random_bytes(4)), 'text' => $this->draft]; $this->draft = ''; $this->messages->prepend($tmp); Api::client()->post("/chats/{$this->id}/messages", ['text' => $tmp['text']]) ->then(fn ($response) => $this->messages->replace($tmp['id'], $response->json())) ->catch(fn () => $this->messages->markFailed($tmp['id'])); } public function more(): void { $this->messages->more(); } } ?> <template> <Column class="screen" :paddingTop="$insets.top" :paddingBottom="$keyboard.visible ? $keyboard.height : $insets.bottom"> <VirtualizedList inverted on:endReached="more"> <Text p-for="$message in $messages.data" :key="$message['id']" :class="['failed' => $message['_failed'] ?? false]"> {{ $message['text'] }} </Text> </VirtualizedList> <Row> <Input p-model="$draft" /> <Button label="Send" @press="send" /> </Row> </Column> </template>
Code written before v2 keeps working: mount(), constructor route parameters,
Appearance::onChange() and the other earlier APIs are still supported. They
are marked @deprecated and each one points to its replacement.
Native where it matters
- Real Android Views and UIKit controls
- Native stack, tabs, drawers, sheets, headers, gestures, and transitions
- Recycled lists and grids for large datasets
- Keyboard-safe inputs, safe areas, accessibility, and reduced motion
- Camera, media library, audio, contacts, location, sensors, notifications, push, sharing, files, SQLite, and secure storage
- Background execution and offline-first state
- Native animation and gesture execution without per-frame PHP traffic
- Hot reload, profiling, time travel, diagnostics, and repeatable benchmarks
- A plugin SDK for application-specific native modules and views
PHP describes the experience. Rust performs reconciliation and layout. Kotlin and Swift apply bounded native mutations once per display frame.
Built for real products
PAM Native includes the parts that demos usually skip:
- process and navigation restoration;
- bounded payloads, queues, caches, and retained state;
- typed integer-backed protocol enums;
- exact-host WebView allowlists and canonical file access;
- offline media caching and retry-safe operations;
- API 26 and API 36 Android contracts;
- UIKit simulator tests;
- deterministic protocol fuzzing;
- performance budgets and baseline profiles.
The public showcase includes a marketplace, finance dashboard, chat composer, offline field workflow, component lab, hot reload, and a recycled list with 10,000 rows.
![]() |
![]() |
![]() |
![]() |
Explore the showcase source or follow the showcase guide to build it locally.
The PAM ecosystem
- 24 official ecosystem packages — Firebase, auth, payments, subscriptions, maps, media, background transfer, realtime, offline sync, extensions, device capabilities, observability, testing, and plugin tooling. Install only the capabilities your application uses.
- PAM Native Nitro — typed, offline-first models and native SQLite queries.
- PAM — the persistent PHP runtime, async I/O, CLI, and wider application platform.
- Plugin SDK — connect native SDKs, modules, views, resources, and PHP service providers.
Learn at your pace
Start with the short path, then open the internals only when you need them:
- Create your first app
- Build components and the v2 app architecture
- Declare named routes
- Manage local and global state
- Use native capabilities
- Understand performance and recovery
For protocol, renderer, and runtime details, use the technical documentation index.
Advanced: install only the SDK
Generated PAM projects already configure this dependency. Direct Composer
installation is intended for custom hosts and framework contributors; most
applications should start with pam init or pam add:
pam composer require pushinbr/pam-native:^1.0
Community
Bug reports, focused feature proposals, documentation fixes, components, and plugins are welcome. Start with the contribution guide or open a discussion describing the application you want to build.
PAM Native is open source under Apache-2.0. You may build and sell proprietary or open applications with it without a revenue limit or runtime royalty. See LICENSING.md for the plain-language grant and the full LICENSE for controlling terms.
Drawer e Toast opcionais (1.46)
Instale pushinbr/pam-native-drawer:0.1.0 para Drawer e
pushinbr/pam-native-toast:0.1.0 para Toast. Migre os imports para
Pam\Native\Drawer e Pam\Native\Toast. Os nomes antigos usam MovedToPlugin:
com o pacote instalado são aliases; sem ele, informam o comando Composer.
O núcleo conserva os IDs reservados e os ganchos genéricos de módulos/views;
não inclui o renderizador de Drawer nem a aparência ou variantes de Toast.
O real-world app depende somente do plugin Toast.



