Write standard Symfony controllers, services, and events.
Ship a .exe, .dmg, or .AppImage — powered by Electron or Tauri.
Architecture
A three-layer bridge between your PHP backend and the native OS runtime.
native:serve starts PHP on 127.0.0.1:8765
Spawns Electron or Tauri with a BrowserWindow at that URL
PHP and runtime talk over WebSocket IPC or named pipe
PHP calls driver->call('window.open', …) — native handles it
Native events pushed back as real Symfony events. No polling.
Services
All services are autowirable. Just type-hint in your constructor.
Open, close, and control native windows from your controllers. Set dimensions, titles, and behavior programmatically.
Create system tray icons with dynamic context menus. Supports separators, roles, and click events.
Send native OS notifications in one line. React to clicks with NotificationClickedEvent.
File pickers, confirm dialogs, save dialogs — native OS dialogs with full filter support.
Persistent key-value store across sessions. Includes a remember() memoization helper.
Get app paths, open external URLs, reveal files in Finder / Explorer, check for updates, quit.
Read and write text or images to the system clipboard. Check presence with hasText() / hasImage().
Register custom URL schemes (myapp://) for deep-linking. Receive DeepLinkReceivedEvent with parsed URL parts.
Drivers
Both implement the same NativeDriverInterface. One config line to swap.
# Switch with one line symfony_native_bridge: driver: tauri # was: electron app: name: "My App" version: "1.0.0" identifier: "com.example.my-app" window: width: 1280 height: 800 build: output_dir: dist targets: [windows, macos, linux]
Usage
Write code you already know. The bridge handles the rest.
# 1. Install the package composer require toxicity/symfony-native-bridge # 2. Register the bundle in config/bundles.php SymfonyNativeBridge\SymfonyNativeBridgeBundle::class => ['all' => true], # 3. Install the native runtime php bin/console native:install # Electron (default) php bin/console native:install --driver=tauri # Tauri # 4. Start developing php bin/console native:serve # 5. Build for distribution php bin/console native:build --target=windows --target=macos --target=linux
Events
The runtime pushes events back to PHP. Real Symfony dispatching — no polling, no hacks.
| Event class | Constant | Triggered when |
|---|---|---|
| AppReadyEvent | native.app.ready | Runtime is up and first window is open |
| AppBeforeQuitEvent | native.app.before_quit | User tries to quit — call $event->prevent() to cancel |
| AppActivatedEvent | native.app.activated | macOS: app clicked in Dock |
| WindowFocusedEvent | native.window.focused | A window gains focus |
| WindowBlurredEvent | native.window.blurred | A window loses focus |
| WindowClosedEvent | native.window.closed | A window is closed |
| TrayClickedEvent | native.tray.clicked | Tray icon clicked (left / right / double) |
| TrayMenuItemClickedEvent | native.tray.menu_item_clicked | A tray menu item is clicked |
| WindowResizedEvent | native.window.resized | A window is resized — carries new width & height |
| WindowMovedEvent | native.window.moved | A window is moved — carries new x & y position |
| DeepLinkReceivedEvent | native.protocol.deep_link | Custom URL scheme opened — exposes scheme, host, path, query |
| UpdateAvailableEvent | native.updater.update_available | A new version is found |
| NotificationClickedEvent | native.notification.clicked | User clicks a notification |
Roadmap
Your Symfony skills transfer 100%. No new framework to learn.