Creating Native Windows with Menus, Icons, and Custom Actions in NativePHP



One of the most exciting parts of building desktop apps with NativePHP is the ability to go beyond just rendering web content. You can create fully native windows, add system-style menus, custom icons, and define custom actions — all using your existing Laravel knowledge.

In this article, we’ll show you how to level up your NativePHP app with true native behavior.


🚀 What You’ll Learn

  • How to create custom windows

  • How to add menus (File, Help, etc.)

  • How to assign tray icons

  • How to define custom menu actions

Let’s build something that feels like a real desktop app, not just a website in a window.


🪟 Creating a Custom Native Window

You can define windows in Laravel using classes provided by NativePHP.

Step 1: Create a Custom Window Class

php artisan native:window MainWindow

This creates a class in app/Native/Windows/MainWindow.php.

Step 2: Configure the Window

namespace App\Native\Windows;

use Native\Laravel\Facades\Window;
use Native\Laravel\Contracts\ProvidesWindows;

class MainWindow implements ProvidesWindows
{
    public function windows(): array
    {
        return [
            Window::new()
                ->title('Dashboard')
                ->url('/dashboard')
                ->width(1024)
                ->height(768)
                ->resizable(true)
                ->fullscreenable(true)
        ];
    }
}

You can register this in config/nativephp.php.


📋 Adding a Native Menu

Adding a native menu is straightforward with NativePHP.

Step 1: Create a Menu Class

php artisan native:menu AppMenu

Step 2: Configure the Menu

use Native\Laravel\Facades\Menu;
use Native\Laravel\Facades\MenuItem;

Menu::create()
    ->label('File')
    ->submenu([
        MenuItem::label('New Window')
            ->click(fn () => Window::open('/')),
        MenuItem::label('Quit')
            ->role('quit'),
    ]);

You can add this to your AppServiceProvider or a custom NativeServiceProvider.


🖼️ Adding a Tray Icon

You can also add a tray icon that lives in the system menu bar.

use Native\Laravel\Facades\Tray;

Tray::create()
    ->icon(public_path('icons/tray.png'))
    ->menu([
        MenuItem::label('Open App')
            ->click(fn () => Window::open('/')),
        MenuItem::label('Quit')
            ->role('quit'),
    ]);

This makes your app feel much more native and accessible.


⚡ Defining Custom Actions

You can respond to user interaction from menus, trays, or buttons by binding actions.

Example: Open Settings Window from Menu

Menu::create()
    ->label('Settings')
    ->submenu([
        MenuItem::label('Open Settings')
            ->click(fn () => Window::open('/settings')),
    ]);

You can use Livewire or JavaScript to trigger more complex interactions.


🎯 Bonus: Keyboard Shortcuts

You can also assign keyboard shortcuts to menu items:

MenuItem::label('Reload')
    ->accelerator('CmdOrCtrl+R')
    ->click(fn () => Window::reload()),

🧰 Best Practices

Feature Best Practice
Menus Group logically (File, Edit, Help)
Tray Icon Use PNG or SVG in correct sizes (16px–32px)
Windows Avoid clutter; name and size them properly
Actions Keep them fast and responsive
Shortcuts Match OS standards (e.g. Cmd+Q to Quit)

✅ Summary

With NativePHP, you're not just wrapping a Laravel app in Electron — you're building first-class desktop software. Menus, icons, and native actions bridge the gap between web and native.

NativePHP makes it feel like home for Laravel developers.