nativeblade / nativeblade
Build desktop and mobile apps with Laravel + Livewire
Requires
- php: 8.3.*|8.4.*|8.5.*
- bacon/bacon-qr-code: ^3.0
- laravel/framework: ^11.0|^12.0|^13.0
- phpdocumentor/reflection-docblock: ^6.0
Requires (Dev)
- livewire/livewire: ^3.0|^4.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- phpunit/phpunit: ^11.0|^12.0
- dev-main
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.9
- v1.7.8
- v1.7.7
- v1.7.6
- v1.7.5
- v1.7.4
- v1.7.3
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.5
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.14
- v1.5.13
- v1.5.12
- v1.5.11
- v1.5.10
- v1.5.9
- v1.5.8
- v1.5.7
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.9
- v1.4.8
- v1.4.7
- v1.4.6
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.1
- v1.3.0
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.1
- v1.1.0
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.0
- v0.9.22
- v0.9.20
- v0.9.12
- v0.9.10
- v0.9.9
- v0.9.8
- v0.9.7
- v0.9.6
- v0.9.5
- v0.9.4
- v0.9.3
- v0.9.2
- v0.9.1
- v0.9.0
- v0.5.5
- v0.5.4
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4.0
- v0.3.5
- v0.3.4
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.9
- v0.2.8
- v0.2.7
- v0.2.6
- v0.2.5
- v0.2.4
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.13
- v0.1.12
- v0.1.11
- v0.1.10
- v0.1.9
- v0.1.8
- v0.1.7
- v0.1.6
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-feature/portal
- dev-feature/tests
- dev-feature/blank
- dev-feature/shell
- dev-feature/pre-prod
- dev-feature/nativeblade-push
- dev-feature/switch-php
- dev-feature/database-4
- dev-feature/schedule-6
- dev-feature/filesystem-3
This package is auto-updated.
Last update: 2026-05-19 18:20:17 UTC
README
Build desktop & mobile apps with Laravel + Livewire. No Electron. No React Native. Just PHP.
Configuration • Components • Directives & Attributes • Navigate • Plugins • Push • Media • Animations • Lifecycle • Database • Filesystem • Build • Scheduler • Auto-Update • Publish • MCP (AI agents)
NativeBlade lets Laravel developers build desktop and mobile apps using only PHP and Blade. Your entire Laravel + Livewire application runs inside a PHP WebAssembly runtime, wrapped in a Tauri 2 shell. No JavaScript frameworks. No API layers. Just the Laravel you already know.
Features
- Pure Laravel — Routes, Livewire components, Blade templates, Eloquent (SQLite)
- Tiny Bundle — A full Laravel + Livewire app compresses to ~6 MB gzipped (see BUILD.md)
- Native Shell — Top bar, bottom navigation, drawer, modal, tray — all outside the WebView
- Native APIs — Dialogs, notifications, camera, geolocation, haptics, biometric, NFC, barcode
- Desktop — Windows, macOS, Linux with native menus and system tray
- Mobile — Android & iOS with status bar, safe area, orientation control
- Push Notifications — Server-pushed notifications via FCM (Android) and APNS (iOS) that wake the app even when closed
- Animations — 90+ Animate.css animations + custom NativeBlade animations via
nb-animationattribute - Offline-First — SQLite persisted to IndexedDB, works without a server
- Hot Reload — Vite HMR for instant feedback during development, plus
--buildmode to preview the production bundle locally - Icons — 3,024 Phosphor Icons (regular + fill) included
- Custom Fonts — Offline font loading via base64 embedding
- Page Transitions — Fade, slide, zoom, flip, bounce, blur — powered by Animate.css
- AI-Ready — Built-in MCP server so Claude Code, Cursor, and Windsurf can introspect your live project (declared plugins, facade methods, framework docs) instead of guessing
Requirements
- PHP 8.3, 8.4, or 8.5 (with GD extension)
- Laravel 11, 12, or 13
- Livewire 3
- Node.js 20+
- Rust — install here
Quick Start
# 1. Create a new Laravel project composer create-project laravel/laravel my-app cd my-app # 2. Install NativeBlade composer require nativeblade/nativeblade php artisan nativeblade:install # 3. Build the frontend npm run build # 4. Launch the desktop app php artisan nativeblade:dev
✓ src-tauri/ — Tauri project
✓ layouts/ — Blade layouts with shell support
✓ vite.wasm.config.js — Vite config for WASM bundling
✓ AppServiceProvider — NativeBlade config
✓ Demo app — Login, Trail, Lesson, Rank, Profile
The first run compiles the Rust binary, which takes a few minutes. Subsequent runs are fast.
Add Mobile
php artisan nativeblade:add android php artisan nativeblade:dev --platform=android --host=192.168.0.10 php artisan nativeblade:add ios php artisan nativeblade:dev --platform=ios --host=192.168.0.10
Mobile requires
--host=<your-local-ip>so the device/emulator can reach the Vite dev server running on your machine. Replace192.168.0.10with your computer's LAN IP (find it withipconfigon Windows orifconfig/ip addron macOS/Linux).localhostwon't work because the phone can't reach your machine through it.
NativeBlade Portal — test on real devices without building
A companion app for iOS and Android that loads any NativeBlade dev bundle by URL or QR scan. Install once, then point it at your nativeblade:dev server to preview your app on a real device with no Xcode / Android Studio build needed.
php artisan nativeblade:dev --platform=portal --host=192.168.0.10
Open the Portal app on your phone, scan the QR shown in your terminal (or paste the URL), and your Laravel + Livewire app loads in seconds. Switch between projects by changing the URL — no rebuild required.
Preview the Production Bundle
Test the exact bundle that will ship — without the Vite dev server and without running a full nativeblade:build:
php artisan nativeblade:dev --build php artisan nativeblade:dev --platform=android --build php artisan nativeblade:dev --platform=ios --build
Builds the frontend once, points Tauri at dist-wasm/, and launches the app. Ideal for validating the real production payload or iterating on Rust/native shell without HMR in the way. See BUILD.md.
UI Components
NativeBlade ships only the shell + runtime, not a styled component library. Pick a UI kit that fits the form factor:
| Form factor | Recommended kit | Install |
|---|---|---|
| Mobile (iOS + Android) | nativeblade/ui-mobile — Konsta-inspired Blade components with iOS and Material themes auto-detected per platform |
composer require nativeblade/ui-mobile |
| Desktop (Windows, macOS, Linux) | Flux UI — official Livewire UI kit by Caleb Porzio. Free core + paid Pro | composer require livewire/flux |
Any Livewire-compatible Blade UI library works (Filament, mary-ui, TallStackUI, Wireui, etc.). The shell, router, and bridges are component-agnostic.
How It Works
┌─────────────────────────────────────────────┐
│ Tauri Shell (native window) │
│ ┌──────────────────────────────┐ │
│ │ Top Bar / Header │ ← Shell │
│ ├──────────────────────────────┤ │
│ │ │ │
│ │ iframe (srcdoc) │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ Laravel + Livewire │ │ ← Your │
│ │ │ via PHP WebAssembly │ │ App │
│ │ └──────────────────────┘ │ │
│ │ │ │
│ ├──────────────────────────────┤ │
│ │ Bottom Navigation │ ← Shell │
│ └──────────────────────────────┘ │
└─────────────────────────────────────────────┘
- Boot — PHP WebAssembly loads your Laravel app (8.3, 8.4, or 8.5)
- Migrate — Pending migrations run automatically
- onBoot — Your startup code runs (license check, data sync, API calls) while splash is visible
- Route — Each navigation runs through Laravel's router inside WASM
- Render — Blade/Livewire HTML is rendered in an iframe
- Intercept — Fetch interceptor routes HTTP requests through WASM
- Bridge — Native actions flow through
postMessage - Schedule — Rust timers execute recurring tasks via Laravel Schedule
- Persist — SQLite syncs to IndexedDB automatically
Database
Migrations run automatically on boot — no php artisan migrate needed. Use standard Laravel migrations and Eloquent:
php artisan make:model Task -m
// Migration runs automatically when the app opens Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->string('title'); $table->boolean('done')->default(false); $table->timestamps(); });
// Eloquent works as usual Task::create(['title' => 'Buy milk']); $tasks = Task::where('done', false)->get(); $task->update(['done' => true]);
onBoot Hook
Run code before the app becomes visible. Splash stays up until complete:
NativeBladeConfig::onBoot(function () { $license = Http::get('https://api.myapp.com/license/check')->json(); NativeBlade::setState('license', $license); });
HTTP Bridge, Storage, Eloquent — everything works inside onBoot. See LIFECYCLE.md.
Scheduler
Laravel Schedule powered by Rust native timers. Define in routes/console.php:
use Illuminate\Support\Facades\Schedule; Schedule::call(fn () => SyncService::run())->everyFiveMinutes()->name('sync'); Schedule::call(fn () => CacheService::cleanup())->daily()->name('cleanup');
All Laravel frequency methods work. Overdue tasks execute on next app open. See LIFECYCLE.md.
State Management
use NativeBlade\Facades\NativeBlade; NativeBlade::setState('auth.user', ['name' => 'John']); $user = NativeBlade::getState('auth.user'); NativeBlade::forget('auth.user'); NativeBlade::flush();
Log
Write log entries from any PHP context (Livewire actions, schedules, routes, mount()) and see them in the Tauri devtools console in real time. Works even when PHP crashes mid-execution — the logs written before the crash are preserved.
use NativeBlade\Facades\NativeBlade; NativeBlade::log('App started'); NativeBlade::log('Retrying', ['attempt' => 3], 'warn'); NativeBlade::log('Payment failed', ['error' => $e->getMessage()], 'error'); NativeBlade::log('Query ran', ['ms' => 12], 'debug');
Each level maps to a console.* method and a color in the [NB:<level>] prefix:
| Level | Console method | Prefix color |
|---|---|---|
info (default) |
console.log |
blue |
warn |
console.warn |
orange |
error |
console.error |
red |
debug |
console.debug |
purple |
The context array is rendered as an expandable object in the browser devtools.
Platform Detection
NativeBlade::platform(); // 'windows', 'macos', 'linux', 'android', 'ios' NativeBlade::isDesktop(); NativeBlade::isMobile(); NativeBlade::isAndroid(); NativeBlade::isIos();
Navigation
NativeBlade::navigate('/dashboard')->toResponse(); NativeBlade::navigate('/', replace: true)->toResponse();
<button wire:nb-navigate="/users">Users</button> <button wire:nb-navigate.replace="/">Home</button>
Authentication
// Middleware $user = NativeBlade::getState('auth.user'); if (!$user) { return NativeBlade::navigate('/login')->toResponse(); } // Login NativeBlade::setState('auth.user', ['name' => 'Admin', 'email' => $email]); return NativeBlade::navigate('/', replace: true)->toResponse(); // Logout NativeBlade::forget('auth.user'); NativeBlade::navigate('/login', replace: true)->toResponse();
HTTP Bridge
Laravel's Http facade works transparently — WASM can't make network requests directly, so NativeBlade bridges them through JavaScript:
$response = Http::get('https://api.github.com/users'); // Parallel requests $responses = NativeBlade::pool(fn ($pool) => [ $pool->get('https://api.com/users'), $pool->get('https://api.com/posts'), ]);
Laravel Compatibility
NativeBlade is a client-side runtime, so anything inherently server-side (sending email, processing queues, running cron daemons) is intentionally not built in — your Laravel server handles those, and the client talks to it.
| Works natively | Via bridge | Via your Laravel server | Custom plugin / shell component |
|---|---|---|---|
| Routing, Blade, Livewire | Http facade (REST/GraphQL) |
Queues, jobs, dispatched tasks | WebSockets / Pusher / Reverb |
| Eloquent on SQLite (local) | MySQL / PostgreSQL / MariaDB (remote, via Rust) | Mail (SMTP, Mailgun, SES) | BLE, Bluetooth Classic |
| Middleware, Validation | Native Filesystem (Storage) | Redis, Memcached | Thermal printer (ESC/POS) |
| Collections, Carbon, Eloquent relations | Camera, Gallery, Video, Barcode, NFC | File Storage (S3, R2, GCS) | Payment terminals (TEF) |
| Service Container, Facades | Biometric, Push (FCM/APNS), Haptics | Heavy reports / aggregations | SAT / fiscal printers |
| Localization, Validation rules | Geolocation, Clipboard, Notifications | Auth providers (OAuth, SSO) | Anything else with tauriInvoke |
| Migrations (auto on boot) | Tauri/Rust commands, Upload streaming | ||
| Task Scheduling (Rust timers) | Custom plugins via tauriInvoke |
WebSockets specifically: Livewire's
wire:pollcovers most "real-time" needs in business apps with zero infrastructure. For genuine real-time (chat with typing indicators, collaborative editing), build a shell component that lives outside the iframe, connects to your WS server, and dispatches Livewire events. See PLUGINS.md → Composer plugin discovery.
Documentation
| Doc | Description |
|---|---|
| CONFIGURATION.md | Desktop, Android, iOS configs, permissions, privacy manifest, transitions |
| NAVIGATE.md | SPA routing — wire:nb-navigate directive, NativeBlade::navigate(), transition and replace modifiers |
| COMPONENTS.md | Shell components, icons, images, skeleton, fonts, safe area, custom components |
| DIRECTIVES.md | wire:nb-bridge, wire:nb-navigate, nb-feedback, native actions |
| PLUGINS.md | Built-in Tauri 2 plugin bridges (dialogs, notifications, clipboard, geolocation, haptics, biometric, barcode, NFC, opener, OS info) |
| PUSH.md | Server push notifications via FCM (Android) and APNS (iOS) |
| MEDIA.md | Native camera, gallery and video pickers with on-device resize |
| ANIMATIONS.md | nb-animation, Animate.css, custom animations, haptic feedback |
| DATABASE.md | SQLite local, native MySQL/PostgreSQL/MariaDB via Rust bridge |
| LIFECYCLE.md | Boot sequence, onBoot hook, clock sync, migrations |
| SCHEDULER.md | Task scheduling with Rust native timers |
| FILESYSTEM.md | Native filesystem, Storage driver, camera integration |
| BUILD.md | Build command, output, CLI commands, icon generation |
| UPDATES.md | Auto-update for desktop and mobile |
| PUBLISH.md | Publishing to stores |
| MCP.md | Built-in MCP server so Claude Code / Cursor / Windsurf can introspect your live project (declared plugins, facade methods, framework docs) |
How NativeBlade Differs
| NativeBlade | Electron | React Native | Flutter | |
|---|---|---|---|---|
| Language | PHP + Blade | JavaScript | JavaScript | Dart |
| Backend | Built-in (Laravel) | Separate | Separate | Separate |
| Binary Size | ~15 MB | ~150 MB | ~30 MB | ~20 MB |
| App Bundle | ~6 MB gzip (full Laravel) | — | — | — |
| Learning Curve | None (if you know Laravel) | Medium | High | High |
| Native UI | Shell + WebView | WebView only | Native | Custom rendering |
| Offline | Yes (WASM + IndexedDB) | Manual | Manual | Manual |
Testing
NativeBlade ships with a three-layer test suite that runs on every push to main via GitHub Actions.
PHP — PHPUnit against Laravel 11/12/13 on PHP 8.3/8.4/8.5 via Testbench:
composer test composer test:coverage # text summary (needs pcov or Xdebug) composer test:coverage-html # full HTML report in build/coverage/
JavaScript — node:test suite covering the runtime bridges (db/http/fs), action handlers and ctx helpers. No browser needed:
npm test
Rust — cargo test suite covering the Tauri command handlers (config, fileops, database row serialization, scheduler). sqlx integration tests use in-memory SQLite:
cd rust cargo test --lib
Run everything locally:
composer test && npm test && (cd rust && cargo test --lib)
Contributing
See CONTRIBUTING.md for guidelines.
License
MIT
Built with Laravel, Livewire, Tauri, and PHP WebAssembly.
Jefferson T.S

