saucer-nodejs
v0.1.1
Published
Node.js bindings for saucer - a modern C++ webview library with non-blocking event loop
Downloads
218
Maintainers
Readme
saucer-nodejs is a modern, lightweight alternative to Electron for building cross-platform desktop applications with web technologies. Built on the saucer C++ webview library, it provides native webview integration with a non-blocking event loop that works seamlessly with Node.js async patterns.
Why saucer-nodejs?
| Feature | saucer-nodejs | Electron | Tauri | |---------|--------------|----------|-------| | Bundle Size | ~5 MB | ~150 MB | ~3 MB | | Memory Usage | Low | High | Low | | Startup Time | Fast | Slow | Fast | | Node.js Integration | Native | Native | Bridge | | Non-blocking Event Loop | ✅ | ❌ | ❌ | | System Tray | ✅ | ✅ | ✅ | | Notifications | ✅ | ✅ | ✅ | | Clipboard | ✅ | ✅ | ✅ |
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Project Structure
- API Reference
- CLI
- Debug Mode
- Platform Support
- Examples
- Building from Source
- Contributing
- License
Features
Core Features
- 🚀 Non-blocking Event Loop - Native Node.js async/await integration
- 🪟 Native Webview - Uses system webview (WebKit on macOS, WebView2 on Windows, WebKitGTK on Linux)
- 📦 Small Bundle Size - ~5MB vs Electron's ~150MB
- ⚡ Fast Startup - Native performance without runtime overhead
- 🔄 Bidirectional RPC - Call Node.js functions from JavaScript and vice versa
Window Management
- 📐 Window Controls - Size, position, title, resizable, decorations
- 🖥️ Fullscreen Mode - Toggle fullscreen with single property
- 🔍 Zoom Control - Adjustable webview zoom level
- 📍 Window Position - Get/set window position programmatically
- 🎨 Customization - Background color, transparency, always-on-top
System Integration
- 📋 Clipboard API - Read/write text and images
- 🔔 System Notifications - Native OS notifications
- 🖱️ System Tray - Menu bar (macOS) / system tray (Windows/Linux)
- 📁 File Dialogs - Open/save file pickers
Developer Experience
- 🛠️ CLI Tool - Build, diagnose, and scaffold projects
- 🐛 Debug Logging - Category-based debug output
- 📝 TypeScript Support - Full type definitions included
- 🧪 Comprehensive Tests - 200+ automated test assertions
Requirements
- Node.js >= 20.0.0
- Operating System: macOS 11+, Windows 10+, or Linux (with GTK3 and WebKitGTK)
Platform-Specific Requirements
| Platform | Webview Engine | Additional Requirements |
|----------|---------------|------------------------|
| macOS | WebKit (system) | None |
| Windows | WebView2 | WebView2 Runtime (included in Windows 11) |
| Linux | WebKitGTK | webkit2gtk-4.0, gtk+-3.0 |
Installation
npm install saucer-nodejsThe package automatically downloads prebuilt binaries for your platform. If no prebuilt binary is available, it will attempt to build from source (requires CMake).
Verify Installation
npx saucer doctorThis runs platform diagnostics to ensure everything is set up correctly.
Quick Start
Basic Example
import { Application, Webview } from 'saucer-nodejs';
// Create application
const app = new Application({ id: 'com.example.myapp' });
// Create webview window
const webview = new Webview(app);
webview.title = 'My App';
webview.size = { width: 1024, height: 768 };
// Load HTML directly
webview.loadHtml(`
<!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>
<h1>Hello from saucer-nodejs!</h1>
<button onclick="greet()">Click me</button>
<script>
async function greet() {
const result = await window.saucer.exposed.sayHello('World');
alert(result);
}
</script>
</body>
</html>
`);
// Expose Node.js function to JavaScript
webview.expose('sayHello', (name) => {
return `Hello, ${name}!`;
});
// Show window
webview.show();
// Handle close
webview.on('closed', () => app.quit());Using the CLI
# Create a new project
npx saucer init my-app
cd my-app
npm install
npm start
# Run diagnostics
npx saucer doctor
# Build standalone executable
npx saucer build index.js my-appProject Structure
saucer-nodejs/
├── index.js # Main module entry point
├── index.d.ts # TypeScript definitions
├── cli/
│ └── saucer.js # CLI tool
├── lib/
│ ├── native-loader.js # Native module loader
│ └── debug.js # Debug logging utilities
├── examples/
│ ├── basic.js # Simple demo
│ └── application-features.js # Comprehensive test suite
├── src/ # C++ source files
├── vendor/ # saucer C++ library
└── scripts/ # Build and install scriptsAPI Reference
Application
The main application class that manages the event loop and application lifecycle.
import { Application } from 'saucer-nodejs';
const app = new Application({
id: 'com.example.myapp', // Bundle identifier
threads: 4 // Thread pool size (default: CPU cores)
});Methods
| Method | Description |
|--------|-------------|
| quit() | Terminate the application |
| isThreadSafe() | Check if called from main thread |
| nativeHandle() | Get native application handle |
| post(callback) | Execute callback on main thread |
| dispatch(callback) | Execute and wait for result |
Webview
The webview window class with full browser capabilities.
import { Webview } from 'saucer-nodejs';
const webview = new Webview(app, {
hardwareAcceleration: true,
persistentCookies: false,
userAgent: 'MyApp/1.0',
preload: 'window.myAPI = { version: "1.0" };'
});Properties
| Property | Type | Description |
|----------|------|-------------|
| title | string | Window title |
| size | { width, height } | Window dimensions |
| position | { x, y } | Window position |
| visible | boolean | Window visibility |
| resizable | boolean | Allow resizing |
| decorations | boolean | Show window decorations |
| alwaysOnTop | boolean | Keep window on top |
| fullscreen | boolean | Fullscreen mode |
| zoom | number | Zoom level (1.0 = 100%) |
| url | string | Current URL |
| devTools | boolean | Show developer tools |
| contextMenu | boolean | Enable context menu |
Methods
| Method | Description |
|--------|-------------|
| show() | Show the window |
| hide() | Hide the window |
| close() | Close the window |
| focus() | Focus the window |
| navigate(url) | Navigate to URL |
| loadHtml(html) | Load HTML directly |
| reload() | Reload current page |
| back() | Navigate back |
| forward() | Navigate forward |
| expose(name, fn) | Expose function to JavaScript |
| evaluate(script) | Execute JavaScript |
| inject(options) | Inject script |
| embed(files) | Embed files |
| serve(filename) | Serve embedded file |
Events
webview.on('closed', () => console.log('Window closed'));
webview.on('resize', (width, height) => console.log(`Resized: ${width}x${height}`));
webview.on('focus', (focused) => console.log(`Focus: ${focused}`));
webview.on('navigated', (url) => console.log(`Navigated to: ${url}`));
webview.on('load', (state) => console.log(`Load state: ${state}`));
webview.on('dom-ready', () => console.log('DOM ready'));
webview.on('title', (title) => console.log(`Title: ${title}`));Clipboard
System clipboard access.
import { clipboard } from 'saucer-nodejs';
// Write text
clipboard.writeText('Hello, World!');
// Read text
const text = clipboard.readText();
// Check availability
const hasText = clipboard.hasText();
const hasImage = clipboard.hasImage();
// Clear clipboard
clipboard.clear();Notification
System notifications.
import { Notification } from 'saucer-nodejs';
// Check support
if (Notification.isSupported()) {
// Request permission
const permission = await Notification.requestPermission();
if (permission === 'granted') {
// Show notification
const notification = new Notification({
title: 'Hello!',
body: 'This is a notification'
});
notification.show();
}
}SystemTray
System tray / menu bar integration.
import { SystemTray } from 'saucer-nodejs';
const tray = new SystemTray();
// Set tooltip
tray.setTooltip('My App');
// Set menu
tray.setMenu([
{ label: 'Show Window', click: () => webview.show() },
{ type: 'separator' },
{ label: 'Quit', click: () => app.quit() }
]);
// Show tray icon
tray.show();
// Cleanup
tray.destroy();CLI
The saucer CLI provides developer tools for building and debugging applications.
# Show help
npx saucer help
# Create new project
npx saucer init my-app
# Run in development mode with watch
npx saucer dev index.js
# Build standalone executable (SEA)
npx saucer build index.js my-app
# Run platform diagnostics
npx saucer doctor
# Show system information
npx saucer infoDebug Mode
Enable debug logging with environment variables:
# Enable all debug output
SAUCER_DEBUG=1 node app.js
# Enable specific categories
SAUCER_DEBUG=rpc,window node app.jsDebug Categories
| Category | Description |
|----------|-------------|
| rpc | RPC/expose function calls |
| window | Window operations |
| webview | Webview operations |
| native | Native module calls |
| app | Application lifecycle |
| event | Event handling |
| perf | Performance timing |
Programmatic Debug
import { createDebugger, measure } from 'saucer-nodejs/debug';
const debug = createDebugger('myapp');
debug('Something happened', { data: 123 });
// Measure async operations
const result = await measure('loadData', async () => {
// ... operation
return data;
});Platform Support
| Feature | macOS | Windows | Linux | |---------|-------|---------|-------| | Webview | ✅ WebKit | ✅ WebView2 | ✅ WebKitGTK | | Clipboard | ✅ | ✅ | ✅ | | Notifications | ✅ | ✅ | ✅ | | System Tray | ✅ | ⚠️ Stub | ⚠️ Stub | | Window Position | ✅ | ⚠️ Stub | ⚠️ Stub | | Fullscreen | ✅ | ⚠️ Stub | ⚠️ Stub | | Zoom | ✅ | ⚠️ Stub | ⚠️ Stub |
Note: Features marked as "Stub" have the API implemented but return placeholder values. Full implementations coming soon.
Examples
Load URL
webview.navigate('https://example.com');Embed Files
webview.embed({
'index.html': { content: '<h1>Hello</h1>', mime: 'text/html' },
'style.css': { content: 'body { color: blue; }', mime: 'text/css' }
});
webview.serve('index.html');Custom URL Scheme
Webview.registerScheme('myapp');
webview.handleScheme('myapp', (request) => {
if (request.url === 'myapp://api/data') {
return {
data: JSON.stringify({ hello: 'world' }),
mime: 'application/json',
status: 200
};
}
});Script Injection
webview.inject({
code: 'console.log("Injected!");',
time: 'ready', // 'creation' or 'ready'
permanent: true // Persist across navigations
});Building from Source
Prerequisites
- Node.js >= 20
- CMake >= 3.15
- C++20 compatible compiler
- macOS: Xcode Command Line Tools
- Windows: Visual Studio 2019+
- Linux: GCC 10+ or Clang 12+
Build Steps
# Clone repository
git clone https://github.com/aspect-build/saucer-nodejs.git
cd saucer-nodejs
# Install dependencies
npm install
# Build native module
npm run rebuild
# Run tests
node examples/application-features.jsContributing
Contributions are welcome! Please read our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE for details.
