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

Electron Laravel Package

nativephp/electron

NativePHP for Electron lets Laravel developers build and ship native desktop applications from a single PHP codebase. It bundles a PHP runtime with Electron to create cross-platform Windows, macOS, and Linux apps using familiar Laravel tools—no separate desktop stack required.

View on GitHub
Deep Wiki
Context7

Getting Started

NativePHP/Electron is the desktop shell that lets an existing Laravel app ship as a native Electron application. The day-to-day workflow is: keep writing Laravel, and reach for the Native\Laravel facades only where the desktop layer needs to exist (windows, tray, menus, notifications, auto-updater).

Install and boot

composer require nativephp/electron
php artisan native:install      # publishes config + scaffolds electron app
php artisan native:serve        # or native:dev for watching

Where to look first

  1. config/nativephp.php — the source of truth for windows, updater, and app metadata.
  2. app/Providers/NativeAppServiceProvider.php — the lifecycle hook (boot) where you register windows, menus, and tray icons.
  3. Native\Laravel\Facades\Window — the entry point for almost every first use case.

First use case: open a single window pointed at a named route, so the desktop app is just your existing UI:

// NativeAppServiceProvider::boot()
Window::open()
    ->route('dashboard')
    ->width(1280)
    ->height(800);

If that renders, you already have a shippable app. Everything below is incremental polish on top of that baseline.

Implementation Patterns

Windows as first-class citizens. Treat window definitions as configuration, not code scattered through controllers. Define the main window in the service provider, and open secondary windows explicitly by ID so you can focus/close them later rather than spawning duplicates.

Suppressing sub-windows (1.3.0). target="_blank" links and window.open() calls previously always produced a second Electron window — usually a blank one with no Laravel session. The new option lets you suppress that opening and handle the intent yourself (redirect the main window, open a modal, or hand off to the OS browser via shell.openExternal). This is the correct pattern for external links and for OAuth/SSO popups you'd rather run in the system browser.

Navigation guards (1.3.0). You can now prevent the renderer from navigating away from the current domain or page. Use it as a cheap security boundary: pin the app to your own origin so an injected link or a stray window.location assignment can't turn your desktop app into a browser pointed at arbitrary content. Mirror the same intent in the system browser for genuinely external destinations.

Zoom factor on Windows (1.3.0). High-DPI Windows machines and accessibility users benefit from setting an explicit zoom factor per window instead of relying on the default. Note this is a Windows-side capability — don't build UI that assumes it works identically on macOS, and prefer setting it at window creation over mutating it later.

Locale information (1.3.0). New Electron API endpoints expose the OS/app locale. Wire this into App::setLocale() early in the boot path (or on a settings change) so dates, number formatting, and translations match what the user's machine reports, rather than hardcoding a locale in config. Keep Laravel's app.locale as the fallback when the API returns something you don't ship translations for.

Auto-updater discipline. The 1.3.0 change to only read publisher config when the updater is enabled means you can leave publisher keys in config without them affecting builds that don't use the updater. Still, treat updater config as environment-specific: separate builds for internal/beta/stable channels, and never ship a build with the updater pointed at a repo you don't control.

Scheduler and long-running work. Stray scheduler processes being cleaned up is a reminder that the Electron app hosts child PHP processes. For anything recurring, prefer Laravel's scheduler invoked from within the app lifecycle over ad-hoc Process calls, and make your job handlers idempotent — a process killed mid-run should not corrupt state on restart.

Multiple apps on one machine. Running two NativePHP apps side by side no longer fights over the same port on Windows. If you maintain several internal tools, this is what makes "install all of them" viable — but you still want each app to have a distinct app_id, updater feed, and window title so users can tell them apart in the taskbar.

Integration tips. Push anything sensitive (tokens, licensing, sync) through normal Laravel HTTP controllers rather than doing it in the renderer; the renderer is your Blade/Inertia/Livewire UI, and the backend is just Laravel. Use native:build in CI on a matrix per OS, and version the desktop app in lockstep with the web app's API contract.

Gotchas and Tips

  • Electron-builder was downgraded in 1.3.0. If you pinned a builder version or rely on a feature only present in the newer builder, pin explicitly in your own package.json and re-test native:build for every target OS before releasing. This is the most likely source of a "worked yesterday" build break.
  • Navigation guards can lock you out during development. If you block navigation away from the current page, hot-reload or redirect-to-login flows may trip the guard. Scope the guard narrowly (external origins only) rather than blocking all navigation.
  • Sub-window suppression breaks flows that genuinely need a popup. Third-party payment and OAuth providers sometimes require a real popup window with a postMessage callback. Test those flows after enabling suppression, and fall back to the system browser where needed.
  • Zoom factor is platform-scoped. Guard it behind a platform check or accept that it's a no-op elsewhere; don't expose a settings toggle that silently does nothing on macOS.
  • Locale from Electron is the OS locale, not the user's preference. Cache the resolved value, let the user override it in-app, and persist the override so it survives restarts.
  • Port cleanup and stray processes. After a crash, verify no orphaned PHP processes are holding ports before concluding the app is broken. native:serve failing to bind is nearly always a leftover process, not a config error.
  • Updater config surprises. With the 1.3.0 change, publisher settings are inert when the updater is disabled. If your updater "isn't running," check the enable flag first — the config being present no longer implies it's active.
  • Extension points: the NativeAppServiceProvider boot hook and the Native\Laravel facades are the sanctioned surface. Reaching into the generated Electron JS directly works but will be overwritten by native:install/upgrades — wrap any custom JS in the documented hooks instead.
  • Debugging: window and renderer errors surface in the Electron devtools, not the Laravel log; PHP-side failures surface in storage/logs/laravel.log and the terminal running native:serve. When something is "blank," check devtools first — it's usually a renderer error or an unreachable dev server, not a Laravel exception.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
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