Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Laravel Package

nativephp/laravel

NativePHP for Laravel lets you build native desktop apps with the PHP and Laravel skills you already have, bundling your code into a standalone application for Windows, macOS, and Linux without learning a new language or framework.

View on GitHub
Deep Wiki
Context7

Getting Started

NativePHP lets you ship an existing Laravel app as a native desktop application: Electron hosts a window, a bundled PHP binary serves your Laravel routes, and the package exposes facades for OS integration (windows, menus, notifications, dialogs, clipboard, tray, updater).

Minimal path:

composer require nativephp/laravel
composer require nativephp/electron   # desktop provider (use nativephp/mobile for mobile)
php artisan native:install            # publishes config, installs provider deps/binaries
php artisan native:dev                # serve + hot reload

Then open a window. The generated app/Providers/NativeAppServiceProvider.php only boots inside the native runtime — that's the correct place for window/menu setup:

public function boot(): void
{
    Window::open()
        ->route('dashboard')
        ->title(config('app.name'))
        ->width(1280)
        ->height(800)
        ->minWidth(900)
        ->rememberState();
}

Where to look first: config/nativephp.php (app id, version, window defaults, queue workers, updater), the generated NativeAppServiceProvider, and the Native\Laravel\Facades\* classes you'll actually call day to day (Window, MenuBar, Notification, Dialog, Shell, System, Settings, Updater).

First real use case: wrap an internal admin/dashboard in a window and delete a class of "open Chrome, log in, find the bookmark" friction — notifications and a tray/menu bar entry point usually justify the build on their own.

Implementation Patterns

Keep the browser experience and the native shell the same app. Every window loads your normal Laravel routes over an internal loopback server, so middleware, auth, Blade/Inertia/Livewire all behave as usual. Build features in the web app; add native only where the OS matters.

Bootstrapping lives in one provider. Menus, shortcuts, window definitions, and event listeners belong in NativeAppServiceProvider::boot(). Treat it as the app's "main" function — don't scatter Window::open() into controllers.

Menus as navigation. MenuBar::create()->label('File')->link('Dashboard', '/dashboard') (or ->route()), ->separator(), ->quit(). Use Menu::create() for the in-window menu and ContextMenu for right-click actions instead of building custom JS menus.

OS integration calls are thin facades — Notification::title()->show(), Dialog::open()/save()/message(), Shell::openExternal(), Shell::showInFolder(), Clipboard::text(), System::theme(), Settings::set()/get(). The JS side mirrors these through the Native global (Native.notification.show(...)), so lightweight interactions don't need a round trip to PHP.

React to events, not polling. Listen for Native\Laravel\Events\WindowShown, WindowClosed, NotificationClicked, MenuItemClicked, SettingChanged, etc. in EventServiceProvider or inline with Event::listen() in the native provider. These are the hooks for "user clicked the tray → show a new window".

Background work needs queue workers. Set config('nativephp.queue_workers') to a non-zero value; the Electron process spawns that many queue:work children. Anything long-running (imports, syncs, PDF generation) should be a job, not a synchronous request — otherwise the window's web process blocks.

Database is a separate SQLite file inside the app data directory, not your repo's database/database.sqlite. Use native:migrate during install/build and native:seed to populate onboarding/admin/demo data into the shipped database. Commands in the native: namespace run against the native app's environment, which is why plain php artisan migrate doesn't move the needle.

Distribution and updates: bump version in config/nativephp.php, configure updater in the same file, and wire Updater::checkForUpdates()/->download() into a "Check for updates" menu item. Ship through your own feed or GitHub Releases; code signing is a separate, non-optional problem (see below).

Gotchas and Tips

  • native:seed was broken in 1.3.0 and is fixed in 1.3.1 (PR #680). If you're on 1.3.0, seeding the native database for demo data, initial admin users, or factory-generated fixtures silently fails or throws. Upgrade, then re-run php artisan native:seed and verify with a native:run query or a settings read. This matters because the native DB is invisible from your dev workflow — you'll otherwise only discover the empty tables after building a distributable.
  • .env is not what you think it is at runtime. Only NATIVEPHP_-prefixed variables are baked at build time; don't assume the rest of your dev environment ships. Resolve config at build, and treat secrets as "not present in the app" unless you deliberately handle them.
  • Writes to base_path() fail after signing, particularly on macOS where the app bundle is effectively read-only. Use storage_path() (mapped into the app data directory) or the package's File facade; never write next to your source files.
  • native:install overwrites published assets; use --force deliberately, and re-publish after changing the Electron side. Hot reload only exists under native:dev — PHP class changes sometimes need a restart of the command.
  • Debugging: during native:serve/native:dev, Log::info() lands in the terminal. For a shipped build, logs and the SQLite DB are in the app data folder — native:open (or ~/Library/Application Support/{app_id} / %APPDATA% on Windows) is the first thing to check when "it works locally but not in the build."
  • Code signing and notarization are table stakes. Unsigned macOS builds are blocked by Gatekeeper; the Windows auto-updater requires a signed installer. Budget for certificates, notarization credentials, and a CI matrix before the first public release.
  • First build downloads Electron and PHP binaries — painfully slow if not cached. Use nativephp/actions in GitHub Actions and cache the dependency directories between jobs.
  • Window state and paths are per-user. rememberState() writes to the app data dir, so "it opens at the wrong size" is a local state problem, not a code problem. Same for Settings.
  • Extension points: the platform provider package (nativephp/electron) is publishable — customize the Electron main process and JS entry there; use the NativeAppServiceProvider for app-level wiring; use config('nativephp.provider') to swap providers if you support both desktop and mobile from one codebase.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager