npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nexfep

v0.1.5

Published

A desktop application framework based on @webviewjs/webview

Downloads

1,295

Readme

Nexfep

Language: English(now) | 简体中文

A desktop application framework based on @webviewjs/webview

Project Status

🚧 Early Stage

This project is currently in early development, with many core capabilities for desktop application development still missing. The framework is being continuously iterated.

Introduction

Nexfep is a desktop application framework built on @webviewjs/webview, written in TypeScript. It aims to provide developers with a concise and efficient toolchain for building cross-platform desktop applications.

The framework uses a window pool management mechanism, supporting multi-window application scenarios such as code editors, chat tools, dashboards, etc.

Features

  • Window Pool Management — Built-in window pool mechanism for automatic reuse and recycling of window resources, avoiding the overhead of frequent creation and destruction
  • IPC Communication — Supports bidirectional message communication between the main process and WebView, via injected functions
  • Window Control — Provides complete window operation APIs including maximize, minimize, close, title setting, and developer tools
  • Drag Regions — Built-in HTML attribute support for defining window drag regions (nexfep-area-drag, etc.)
  • TypeScript Support — Complete type definitions for excellent development experience

Installation

pnpm add nexfep

Quick Start

import { WindowPool } from 'nexfep';

const pool = new WindowPool();

const window = await pool.createWindow(true, false);

await window.loadHTML('<h1 nexfep-area-drag>Hello Nexfep!</h1>');

pool.mainloop();

Usage Guide

Window Pool

WindowPool is the core management class of the framework, responsible for window creation and recycling.

const pool = new WindowPool();

Constructor Parameters

  • WindowsWebview2UserDataFolder (optional) — WebView2 user data directory, defaults to %LOCALAPPDATA%\NexfepDevelopment.webview2-data

Window Creation

const win = await pool.createWindow(true, false);

Parameters

  • isShow (boolean, default true) — Whether to immediately show the window
  • isDecorated (boolean, default true) — Whether to use system window decorations. When set to false, the window has no border and requires a custom title bar

Window Operations

window.show();
window.hide();
window.maximize();
window.minimize();
window.close();
window.setTitle('New Title');
window.openDevTools();

Custom Messages

Send Messages

Send messages via window.postMessage in the page:

window.postMessage({ hello: 'world' });

Parameters

  • data — Any serializable data, will be serialized to JSON string before sending

Listen for Messages

Receive messages via onCustomMessage callback in the main process:

pool.onCustomMessage = (window, data) => {
  console.log(`Message from window ${window.id}:`, data);
};

Callback Parameters

  • window — The window object that sent the message
  • data — Message content, an object type (automatically converted from JSON string via JSON.parse)

Custom Events

Invoke Events

Invoke events via window.invoke in the page:

window.invoke('hello');
window.invoke('hello', 'world');

Parameters

  • event — Event name
  • data (optional) — Any serializable data, will be serialized to JSON string before sending

Listen for Events

Listen for events via pool.handle in the main process:

pool.handle('hello', (data) => {
  console.log('Received event hello:', data);
});

Parameters

  • event — Event name, must match the event name when invoking
  • callback — Event handler function, receives event data as data parameter. Can return any serializable data, which will be serialized to JSON string and sent back to the frontend as the return value of window.invoke (can also return nothing)

Remove Event Listener

Remove event listener via pool.unhandle in the main process:

pool.unhandle('hello', (data) => {
  console.log('Received event hello:', data);
});

Parameters

  • event — Event name, must match the event name when listening
  • callback — Event handler function, must match the callback function when listening

Global Variables

Set Variables

Set a global variable via window.setGlobal in the page:

window.setGlobal('hello', 'world');

Parameters

  • name — Global variable name
  • value — Global variable value, any serializable data, will be serialized to JSON string before sending

Get Variables

Get a global variable via window.getGlobal in the page:

const value = await window.getGlobal('hello');

Parameters

  • name — Global variable name

Global Variable Map

Get a Map<string, any> containing all global variables via WindowPool.global in the main process, which supports operations like set and get:

const globals = pool.global;
globals.set('hello', 'world');
const value = globals.get('hello');

Inter-Window Communication

The framework supports direct communication between windows via window.broadcast and window.tell, without going through the main process.

Broadcast

Send an event to all other open windows via window.broadcast:

window.broadcast('user-login', { userId: 123 });

Parameters

  • name — Event name
  • data (optional) — Any serializable data, will be serialized to JSON string before sending

Other windows listen for the broadcast event via window.addEventListener:

window.addEventListener('user-login', (event) => {
  console.log('User logged in:', event.detail);
});

Tell

Send a message to a specific window by its ID via window.tell:

window.tell(2, 'custom-message', { text: 'Hello Window 2' });

Parameters

  • to — Target window ID (number)
  • message — Event name
  • data (optional) — Any serializable data, will be serialized to JSON string before sending

The target window receives the message via window.addEventListener:

window.addEventListener('custom-message', (event) => {
  console.log('Received message:', event.detail);
});

Each window's ID can be accessed via window.id:

console.log('This window ID:', window.id);

Window Control Functions

The following injected functions can be directly called in the page for window control:

window.close();              // Close window
window.minimize();           // Minimize window
window.unminimize();         // Restore minimized window
window.maximize();           // Maximize window
window.unmaximize();         // Restore maximized window
window.setTitle('Title');    // Set window title
window.openDevTools();       // Open developer tools
window.closeDevTools();      // Close developer tools

The following properties are also available in the page:

console.log(window.id);                // Window unique identifier
console.log(window.isNexfepLoadDone);  // Whether the window has finished loading

Drag Regions

Define window drag regions via HTML attributes without writing additional JavaScript code. These attributes automatically apply -webkit-app-region and app-region CSS properties.

nexfep-area-drag

Makes the entire region and all its child elements draggable. Suitable for scenarios like custom title bars where the entire region needs to be draggable.

<div nexfep-area-drag>
  <h1>Title Bar</h1>
  <span>Subtitle</span>
</div>

nexfep-element-drag

Makes only the specified element itself draggable; child elements are not affected. Suitable for scenarios requiring precise control over the drag region.

<div>
  <div nexfep-element-drag>Drag Handle</div>
  <p>This part is not draggable</p>
</div>

nexfep-no-drag

Makes the specified region and all its child elements non-draggable. Highest priority, can override parent element's drag attributes. Suitable for interactive elements like buttons and input fields.

<div nexfep-area-drag>
  <h1>Title Bar</h1>
  <button nexfep-no-drag>Click Button</button>
</div>

nexfep-auto-drag

Automatically determines drag regions: the entire region is draggable, but common interactive elements (button, input, select, textarea, a) are automatically set to non-draggable. Suitable for complex regions containing multiple interactive elements.

<div nexfep-auto-drag>
  <h1>Title Bar</h1>
  <button>Automatically non-draggable</button>
  <input placeholder="Automatically non-draggable" />
  <a href="#">Automatically non-draggable</a>
</div>

Load Complete Event

The nexfep-load-done event is triggered after the WebView window finishes loading:

window.addEventListener('nexfep-load-done', () => {
  console.log('Nexfep window loaded');
});

It can also be checked via the window.isNexfepLoadDone property:

if (window.isNexfepLoadDone) {
  // Window is ready
}

API

WindowPool

| Method/Property | Parameters | Return Value | Description | | ------------------------------------- | -------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------ | | constructor(userDataFolder?) | userDataFolder: string (optional) | WindowPool | Creates a window pool, optionally specifying the WebView2 user data directory | | createWindow(isShow?, isDecorated?) | isShow: boolean (default true), isDecorated: boolean (default true) | Promise<Window> | Creates and returns a window | | handle(event, callback) | event: string, callback: (data: string) => void | None | Listens for the specified event, triggers callback when event is received | | unhandle(event, callback) | event: string, callback: (data: string) => void | None | Removes the specified callback from the event listener | | global | / | Map<string, any> | A global variable map of type: Map<string, any> | | closeWindow(window) | window: Window | Promise<void> | Closes the specified window and returns it to the pool | | closePool() | None | Promise<void> | Closes the window pool and exits the application | | mainloop() | None | void | Starts the application main loop, blocking until the application exits | | onCustomMessage | (window: Window, data: string) => void | None | Custom message callback, triggered when receiving custom messages from pages |

Window

| Method/Property | Parameters | Return Value | Description | | ------------------------------------- | ------------------------------------------- | ---------------- | ---------------------------------------- | | loadURL(url) | url: string — URL to load | Promise<void> | Loads the specified URL | | loadHTML(html) | html: string — HTML string | Promise<void> | Loads the specified HTML content | | show() | None | void | Shows the window | | hide() | None | void | Hides the window | | maximize() | None | void | Maximizes the window | | unMaximize() | None | void | Restores the window (cancels maximize) | | minimize() | None | void | Minimizes the window | | unMinimize() | None | void | Restores the window (cancels minimize) | | close() | None | void | Closes the window and returns to pool | | setTitle(title) | title: string — Window title | void | Sets the window title | | setDecorated(isDecorated) | isDecorated: boolean — Use system decorations | void | Sets whether the window has borders and title bar | | resizable(resizable) | resizable: boolean — Resizable | void | Sets whether the window is resizable | | openDevTools() | None | void | Opens developer tools | | closeDevTools() | None | void | Closes developer tools | | id | None | number | Unique window identifier, auto-incrementing |

Development

pnpm install
pnpm run compile

License

MIT License