Skip to content

Latest commit

 

History

49 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

image

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 ewvjs

Quick 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 in window.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()

Window Events

Window lifecycle and state events are assigned directly on the Window instance.

win.on_close = () => {
    console.log('window closed');
};

win.on_resize = (size) => {
    console.log('resized to', size.width, size.height, size.state);
};

Available callbacks:

  • on_close() - Fired when the window closes.
  • on_show() - Fired when the window becomes visible.
  • on_hide() - Fired when the window is hidden.
  • on_resize(size) - Fired when the window is resized. size includes width, height, and state.
  • on_move(pos) - Fired when the window moves. pos includes x and y.
  • on_focus() - Fired when the window gains focus.
  • on_blur() - Fired when the window loses focus.
  • on_maximize() - Fired when the window is maximized.
  • on_minimize() - Fired when the window is minimized.
  • on_restore() - Fired when the window returns to the normal state.

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 name attribute value (case-insensitive) or a substring of the iframe's loaded src URL.
    • Number: The internal unique frame registry identifier.

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 dev

Project 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 via file:// 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 package

package - 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.js

Full 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-x64

Output:

The packaged application will be created in the dist/ directory with:

  • <output>.exe - Standalone executable
  • Native WebView2 dependencies (unless --no-native is used)
  • Bundled assets from the specified directory

Notes:

  • Icon file must be in .ico format
  • Additional modules should be listed without spaces: axios,lodash,express
  • Default target node18-win-x64 works 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 --help

Display version:

npx ewvjs-cli --version

License

MIT LICENSE

About

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.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Contributors

Languages