ewvjs
v1.0.21
Published
Embedded WebView for JavaScript - Edge WebView2 bindings for Node.js
Maintainers
Readme
ewvjs
Embedded WebView for JavaScript
ewvjs allows you to create modern desktop applications using Node.js and the Microsoft Edge WebView2 control. It provides a lightweight, native GUI experience with full access to Node.js APIs.
Features
- 🪟 Native Window Management: Create, control, and customize native Windows.
- 🌐 Modern Web Technologies: Build your UI with HTML, CSS, and JavaScript.
- ⚡ Node.js Integration: Call Node.js functions directly from your frontend code.
- 🖱️ Context Menus: Customizable native right-click context menus.
- 📦 Packaging: Built-in CLI tool to package your app into a standalone executable.
- 🔄 Auto Update: Download a hosted manifest and atomically swap in a packaged app update.
- 🔧 Native Bindings: High-performance C# bindings via
node-api-dotnet. - 🖼️ Customization: Support for frameless windows, transparency, vibrancy, and more.
Installation
npm install ewvjsQuick Start
Create a simple application:
const { create_window, start } = require('ewvjs');
// Create a new window
const win = create_window('My App', 'https://www.google.com', {
width: 1024,
height: 768,
});
// Run the window
win.run();
// Keep the application alive
start();Exposing Node.js Functions
You can expose Node.js functions to your frontend code easily:
Backend (Node.js):
const { create_window, expose, start } = require('ewvjs');
const os = require('os');
// Expose a function to specific window or globally
expose('getSystemInfo', () => {
return {
platform: os.platform(),
arch: os.arch(),
cpus: os.cpus().length
};
});
const win = create_window('System Info', 'index.html', { width: 400, height: 300 });
win.run();
start();Frontend (HTML/JS):
// Call the exposed function via window.ewvjs.api
async function showInfo() {
const info = await window.ewvjs.api.getSystemInfo();
console.log(info);
}API Reference
create_window(title, url, options)
Creates a new WebView window.
title(string): The window title.url(string): The URL to load (http/https) or path to a local HTML file or HTML string.options(object): Configuration options.
start()
Starts the application event loop. This keeps the Node.js process alive until all windows are closed.
expose(name, callback)
Exposes a Node.js function to the frontend.
name(string): The name of the function as it will appear inwindow.ewvjs.api.callback(function): The Node.js function to execute. Can be async.
autoUpdateFromManifest(manifestUrl)
Downloads an update manifest, fetches the packaged app ZIP, stages it, and performs an atomic directory swap from a detached PowerShell helper after the current process exits. The helper then relaunches the app.
Manifest format:
{
"version": "0.0.2",
"url": "https://example.com/updater_test/update_balbal.zip"
}Usage:
const result = await ewvjs.autoUpdateFromManifest('https://example.com/manifest.json');
if (result.updated) {
console.log('Updated to', result.version);
} else {
console.error('Update failed:', result.error);
}Notes:
- The archive is extracted with Windows
tar. - The running app cannot overwrite itself directly, so the helper process handles the swap.
- A backup copy is kept during the swap to reduce the chance of update failure leaving the install broken.
Window Options
{
width?: number; // Window width
height?: number; // Window height
min_width?: number; // Minimum window width
min_height?: number; // Minimum window height
x?: number; // X position
y?: number; // Y position
resizable?: boolean; // Allow resizing
fullscreen?: boolean; // Start in fullscreen
hidden?: boolean; // Start hidden
frameless?: boolean; // Remove window frame
focus?: boolean; // Focus window on creation
minimized?: boolean; // Start minimized
maximized?: boolean; // Start maximized
on_top?: boolean; // Keep window on top
confirm_close?: boolean; // Require confirmation before closing
transparent?: boolean; // Transparent background
background_color?: string; // Hex color (e.g. "#FFFFFF")
vibrancy?: boolean; // Enable window vibrancy/acrylic effect (default: true)
dark_mode?: boolean; // Enable dark mode
title_bar?: boolean; // Show/hide title bar (if not frameless)
icon?: string; // Path to .ico file
session?: {
persist?: boolean; // Persist cookies/localStorage
path?: string; // Custom user data path
envname?: string; // WebView2 Environment name
};
additional_args?: string; // Additional WebView2 arguments
debug?: boolean; // Enable debug tools/console
}Window Methods
Once a window is created, you can control it using the returned Window instance:
- Lifecycle:
run(),close(),destroy() - State:
maximize(),minimize(),restore(),hide(),focus(),show() - Size & Position:
getSize(),setSize(w, h),resize(w, h)getMinSize(),setMinSize(w, h)getPosition(),setPosition(x, y),move(x, y)
- Interaction:
setTitle(title)showTitlebar(),hideTitlebar()evaluate(script, [frame]): Execute JavaScript in the WebView or target a specific subframe/iframe context.setIcon(path)
- Cookies:
getCookies(),setCookie(name, value, domain, path),clearCookies()
Executing JavaScript inside IFrames (Cross-Origin Bypass)
The evaluate method supports executing and injecting JavaScript directly inside any subframe/iframe context, completely bypassing standard browser Same-Origin Policy (SOP) limitations. This enables the native Node.js layer to inspect and mutate the DOM of cross-origin or same-origin subframes natively.
async evaluate(script: string, frame?: string | number): Promise<any>Parameters:
script: The JavaScript code string to execute.frame(optional): The target subframe selector. This can be:- String: The iframe's
nameattribute value (case-insensitive) or a substring of the iframe's loadedsrcURL. - Number: The internal unique frame registry identifier.
- String: The iframe's
Example:
// Execute on top-level main document
const title = await win.evaluate("document.title");
// Execute inside a cross-origin iframe using its frame name
const iframeText = await win.evaluate(
"document.querySelector('h1').innerText",
"my-frame-name"
);
// Execute inside an iframe targeted by its loaded URL substring
await win.evaluate(
"document.body.style.background = '#8b5cf6'",
"example.com/payment"
);Custom Context Menus
Define native context menus using on_context_menu. It should return an array of ContextMenuItem objects.
ContextMenuItem Interface
interface ContextMenuItem {
label?: string;
type?: 'normal' | 'separator' | 'checkbox' | 'submenu';
checked?: boolean;
enabled?: boolean;
submenu?: ContextMenuItem[];
click?: () => void;
}Example:
win.on_context_menu = (params) => {
return [
{ label: 'Refresh', click: () => win.reload() },
{ type: 'separator' },
{ label: 'Exit', click: () => win.close() }
];
};CLI Reference
ewvjs-cli provides a command-line interface for creating and packaging applications.
Installation
The CLI is included with the ewvjs-cli package and can be run using npx:
npx ewvjs-cli <command> [options]Commands
init - Initialize a New Project
Create a new ewvjs project with a sample application structure.
Usage:
npx ewvjs-cli init [name] [options]Arguments:
name- Project name (default:my-ewvjs-app)
Options:
-t, --template <template>- Template to initialize (basic|react) (default:basic)-l, --list-templates- List all available templates
Example:
npx ewvjs-cli init my-awesome-app --template react
cd my-awesome-app
npm install
npm run devProject Templates
ewvjs-cli supports two official templates out of the box:
1. Basic Template (basic - default)
A simple, lightweight setup using plain static assets:
app.js: Main host controller containing standard Node.js exposure hooks.assets/: Pure HTML/CSS/JS frontend files loaded natively viafile://resolution.
2. React Template (react)
A premium, feature-rich React 19 + Vite 8 + TypeScript development environment:
- Vite Bundler: Ultra-fast build times and hot-reload configs.
- Premium Styling: Pre-configured global CSS resets, sleek glassmorphic themes, and linear gradients styled around the Outfit Google Font.
- HMR Developer Runner: Spawns a parallel Vite developer server and embeds it directly into the native ewvjs window, rendering real-time UI changes dynamically as you edit.
- Type-Safe Host API: Employs global typed window definitions for fully intelligent, warning-free React-to-Node API communications.
React Workflow Commands:
# Initialize a new React project
npx ewvjs-cli init my-react-app --template react
cd my-react-app
npm install
# Run the HMR interactive developer window
npm run dev
# Compile React static outputs and build a standalone packaged exe
npm run packagepackage - Package Application
Package your ewvjs application into a standalone executable.
Usage:
npx ewvjs-cli package <entry> [options]Arguments:
entry- Entry point JavaScript file (required, e.g.,app.js)
Options:
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| --output <name> | -o | Output executable name (without .exe) | app |
| --name <name> | -n | Application name | My App |
| --icon <file> | -i | Path to application icon (.ico file) | None |
| --assets <dir> | -a | Assets directory to include in package | ./assets |
| --target <target> | -t | Target platform | node18-win-x64 |
| --modules <modules> | -m | Additional node modules to bundle (comma-separated) | None |
Examples:
Basic packaging:
npx ewvjs-cli package app.jsFull customization:
npx ewvjs-cli package app.js \
--output myapp \
--name "My Application" \
--icon icon.ico \
--assets ./public \
--modules axios,lodash \Package with custom target:
npx ewvjs-cli package app.js -o myapp -t node20-win-x64Output:
The packaged application will be created in the dist/ directory with:
<output>.exe- Standalone executable- Native WebView2 dependencies (unless
--no-nativeis used) - Bundled assets from the specified directory
Notes:
- Icon file must be in
.icoformat - Additional modules should be listed without spaces:
axios,lodash,express - Default target
node18-win-x64works with Node.js 18+ on 64-bit Windows
Getting Help
Display available commands and options:
npx ewvjs-cli --help
npx ewvjs-cli package --help
npx ewvjs-cli init --helpDisplay version:
npx ewvjs-cli --versionLicense
MIT LICENSE
