### Install and Run Convex Todo Demo
Source: https://github.com/macaly/almostnode/blob/main/examples/convex-todo/README.md
Installs dependencies and starts the development server for the Convex Todo browser runtime demo. This command should be run from the examples/convex-todo directory.
```bash
npm install
npm run dev
```
--------------------------------
### Project Setup
Source: https://github.com/macaly/almostnode/blob/main/README.md
Clone the repository, navigate to the project directory, and install dependencies using npm.
```bash
git clone https://github.com/macaly/almostnode.git
cd almostnode
npm install
```
--------------------------------
### Install and Use Lodash Package
Source: https://github.com/macaly/almostnode/blob/main/docs/core-concepts.html
This example demonstrates installing the 'lodash' package and then using its utility functions within a JavaScript file executed in the virtual file system.
```javascript
import { createContainer } from 'almostnode';
const { vfs, npm, runtime } = createContainer();
// Install lodash from npm
await npm.install('lodash');
// Use it in your code
vfs.writeFileSync('/app.js', `
const _ = require('lodash');
const data = [1, [2, [3, [4]]]];
console.log(_.flattenDeep(data)); // [1, 2, 3, 4]
console.log(_.chunk([1,2,3,4,5,6], 2)); // [[1,2],[3,4],[5,6]]
`);
runtime.runFile('/app.js');
```
--------------------------------
### Initialize almostnode Container
Source: https://github.com/macaly/almostnode/blob/main/docs/index.html
Use `createContainer()` to set up a virtual filesystem, runtime, and package manager. This is the fastest way to get started.
```javascript
import { createContainer } from 'almostnode';
const { vfs, runtime, npm } = createContainer();
// Write a file to the virtual filesystem
vfs.writeFileSync('/hello.js', `
console.log('Hello from almostnode!');
`);
// Execute it
runtime.runFile('/hello.js');
```
--------------------------------
### Run HTTP or Express Server
Source: https://github.com/macaly/almostnode/blob/main/index.html
Initializes the playground environment, installs Express if needed, resets the server bridge, and starts the server. Handles console logs from the server and sets up the preview.
```typescript
async function runSimple(tabId) {
terminal.innerHTML = '';
iframe.src = 'about:blank';
placeholder.classList.remove('hidden');
previewUrl.classList.remove('visible');
setRunning(true);
setTabState(tabId, 'running');
setStatus('Starting...');
try {
const container = createContainer();
container.runtime.onConsole = (method, args) => {
const msg = args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ');
log(msg, method === 'error' ? 'err' : 'log');
};
if (tabId === 'express') {
log('Installing express from npm...', 'info');
setStatus('Installing npm packages...');
await container.npm.install('express', {
onProgress: (msg) => log(msg, 'info'),
});
log('Express installed', 'ok');
}
resetServerBridge();
const bridge = getServerBridge({
baseUrl: window.location.origin,
onServerReady: (port) => {
currentBridge = bridge;
currentPort = port;
log('Server listening on port ' + port, 'ok');
setStatus('Running');
setTabState(tabId, 'running');
loadPreview(bridge, port, '/');
},
});
const code = editors[tabId].value;
log('Executing code...', 'info');
setStatus('Executing...');
containe
```
--------------------------------
### Start Dev Server with Env Vars
Source: https://github.com/macaly/almostnode/blob/main/docs/CONVEX_TUTORIAL.md
Initializes and starts a development server with Convex URL set as an environment variable. It first deploys to Convex to get the URL, then configures and registers the server.
```typescript
import { getServerBridge } from 'almostnode/server-bridge';
// Deploy and get the URL
const convexUrl = await deployToConvex('dev:my-project|token...');
// Create server with env vars
const server = new NextDevServer(vfs, {
port: 3000,
preferAppRouter: true,
env: {
NEXT_PUBLIC_CONVEX_URL: convexUrl,
},
});
// Register and start
const bridge = getServerBridge();
await bridge.initServiceWorker();
bridge.registerServer(server, 3000);
server.start();
console.log(`App running at: ${bridge.getServerUrl(3000)}`);
```
--------------------------------
### Express Server Setup and Routes
Source: https://github.com/macaly/almostnode/blob/main/examples/express-demo.html
Sets up an Express server with middleware for JSON parsing, defines routes for the home page, user API, time API, and a random number API. Includes a 404 handler and starts the server on port 3000. This is the main server logic.
```javascript
const express = require('express');
const app = express();
// Middleware to parse JSON
app.use(express.json());
// Home route
app.get('/', (req, res) => {
console.log('GET /');
res.send(`
Express Agent Runtime
This Express server is running inside an isolated browser runtime.
`);
});
// API routes
app.get('/api/users', (req, res) => {
console.log('GET /api/users');
res.json([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
{ id: 3, name: 'Charlie', email: 'charlie@example.com' }
]);
});
app.get('/api/time', (req, res) => {
console.log('GET /api/time');
res.json({ timestamp: Date.now(), iso: new Date().toISOString(), readable: new Date().toLocaleString() });
});
app.get('/api/random', (req, res) => {
console.log('GET /api/random');
res.json({ number: Math.random(), dice: Math.floor(Math.random() * 6) + 1 });
});
// 404 handler
app.use((req, res) => {
res.status(404).json({ error: 'Not Found', path: req.path });
});
// Start server
app.listen(3000, () => {
console.log('Express server running on port 3000');
});
```
--------------------------------
### Install a Package with PackageManager
Source: https://github.com/macaly/almostnode/blob/main/docs/api-reference.html
Demonstrates installing a specific npm package using the `install` method of the PackageManager. Options for saving to package.json are available.
```javascript
`install`
`(packageSpec: string, options?: InstallOptions): Promise`
```
--------------------------------
### Register and Start Development Server
Source: https://github.com/macaly/almostnode/blob/main/docs/tutorial-editor.html
Register the development server on a specific port and then start it to enable file watching for HMR.
```javascript
bridge.registerServer(devServer, 3000);
devServer.start();
```
--------------------------------
### Install Packages from package.json
Source: https://github.com/macaly/almostnode/blob/main/docs/api-reference.html
Shows how to install all dependencies listed in a package.json file using the `installFromPackageJson` method of the PackageManager.
```javascript
`installFromPackageJson`
`(options?: InstallOptions): Promise`
```
--------------------------------
### List Installed Packages
Source: https://github.com/macaly/almostnode/blob/main/docs/api-reference.html
Demonstrates retrieving a record of installed packages and their versions using the `list` method of the PackageManager.
```javascript
`list`
`(): Record`
```
--------------------------------
### Execute the Default Start Script
Source: https://github.com/macaly/almostnode/blob/main/examples/npm-scripts-demo.html
Executes the 'start' script defined in package.json, typically used to launch a development server or application.
```bash
npm start
```
--------------------------------
### Install and run CLI tools
Source: https://github.com/macaly/almostnode/blob/main/README.md
Install npm packages that include CLI tools, such as Vitest, and run them directly. The tools are automatically available in the PATH after installation.
```typescript
// Install a package that includes a CLI tool
await container.npm.install('vitest');
// Run it directly — bin stubs are created in /node_modules/.bin/
const result = await container.run('vitest run');
console.log(result.stdout); // Test results
```
--------------------------------
### Install Package Function
Source: https://github.com/macaly/almostnode/blob/main/examples/next-demo.html
Handles the installation of a specified package using the package manager, updates the UI, creates a demo page, and loads the file. Includes error handling and progress logging.
```javascript
async function installPackage(packageSpec) { if (!vfs || !packageManager) { log('VFS or PackageManager not initialized', 'error'); return; } const packageName = packageSpec.split('@')[0]; installBtn.disabled = true; installBtn.textContent = 'Installing...'; try { log(`Installing ${packageSpec}...`); const result = await packageManager.install(packageSpec, { onProgress: (message) => log(message), }); for (const name of result.added) installedPackages.add(name); updateInstalledList(); const { pagePath, routePath } = createPackageDemoPage(packageName); log(`Created demo: ${pagePath}`, 'hmr'); const tabs = useAppRouter ? appRouterTabs : pagesRouterTabs; if (!tabs.find(t => t.file === pagePath)) { tabs.push({ file: pagePath, label: `${packageName}-demo.jsx` }); updateFileTabs(); } loadFile(pagePath); log(`Installed ${packageSpec}`, 'hmr'); log(`Navigate to ${routePath} to see the demo.`); } catch (error) { log(`Failed: ${error.message}`, 'error'); console.error(error); } finally { installBtn.disabled = false; installBtn.textContent = 'Install'; } }
```
--------------------------------
### Run Development Server
Source: https://github.com/macaly/almostnode/blob/main/docs/AI_CHATBOT_TUTORIAL.md
Starts the development server for the Next.js application. Open your browser to the specified local address to view the demo.
```bash
npm run dev
```
--------------------------------
### Install Dependencies from package.json
Source: https://github.com/macaly/almostnode/blob/main/docs/core-concepts.html
Use `container.npm.installFromPackageJson()` to install all dependencies listed in an existing `package.json` file.
```javascript
container.npm.installFromPackageJson()
```
--------------------------------
### Initial Sandbox Messages
Source: https://github.com/macaly/almostnode/blob/main/examples/sandbox-next-demo.html
Logs initial informational messages to the console when the sandbox demo is loaded, guiding the user on how to start.
```javascript
logToConsole('Sandbox demo loaded', 'info');
logToConsole('Click Connect to Sandbox to start', 'info');
```
--------------------------------
### Install Package
Source: https://github.com/macaly/almostnode/blob/main/examples/next-demo.html
Installs a specified package using the package manager. This function is triggered by user input and updates the UI to reflect the installation.
```javascript
function installPackage(pkg) {
log(`Installing ${pkg}...`);
packageManager.install([pkg]).then(() => {
installedPackages.add(pkg);
updateInstalledList();
log(`Installed ${pkg}`);
}).catch(e => {
log(`Failed to install ${pkg}: ${e.message}`, 'error');
console.error(e);
});
}
```
--------------------------------
### Setting up a Vite Development Server with VirtualFS
Source: https://github.com/macaly/almostnode/blob/main/README.md
Initialize a VirtualFS and configure a ViteDevServer for a frontend application. This example creates a basic React app structure.
```typescript
import { VirtualFS, ViteDevServer, getServerBridge } from 'almostnode';
const vfs = new VirtualFS();
// Create a React app
vfs.writeFileSync('/index.html', "
<\/div>
```
--------------------------------
### PackageManager for npm Installs
Source: https://github.com/macaly/almostnode/blob/main/docs/CONVEX_TUTORIAL.md
Shows how to use the PackageManager to install npm packages into the virtual filesystem, including single packages and multiple packages.
```typescript
import { PackageManager } from 'almostnode';
const npm = new PackageManager(vfs, { cwd: '/project' });
// Install a package
await npm.install('convex', {
onProgress: (msg) => console.log(msg),
});
// Install multiple packages
await npm.install(['react', 'react-dom']);
```
--------------------------------
### Initialize PackageManager
Source: https://github.com/macaly/almostnode/blob/main/docs/api-reference.html
Shows the instantiation of the PackageManager to install npm packages into a virtual filesystem. It fetches from the npm registry and resolves dependencies.
```javascript
new PackageManager(vfs: VirtualFS, options?: { cwd?: string })
```
--------------------------------
### Run Next.js Dev Server
Source: https://github.com/macaly/almostnode/blob/main/README.md
Set up a virtual file system with Next.js pages and start the Next.js development server. The server can be accessed via a virtual URL.
```typescript
import { VirtualFS, NextDevServer, getServerBridge } from 'almostnode';
const vfs = new VirtualFS();
// Create a Next.js page
vfs.mkdirSync('/pages', { recursive: true });
vfs.writeFileSync('/pages/index.jsx', "
import { useState } from 'react';
export default function Home() {
const [count, setCount] = useState(0);
return (
Count: {count}
);
}
");
// Start the dev server
const server = new NextDevServer(vfs, { port: 3000 });
const bridge = getServerBridge();
await bridge.initServiceWorker();
bridge.registerServer(server, 3000);
// Access at: /__virtual__/3000/
```
--------------------------------
### Install npm Package Programmatically
Source: https://github.com/macaly/almostnode/blob/main/docs/core-concepts.html
Install a single npm package using `container.npm.install()`. This method provides typed results and supports progress callbacks and options like `save` or `saveDev`.
```javascript
container.npm.install('pkg')
```
--------------------------------
### Load File and Render Tabs
Source: https://github.com/macaly/almostnode/blob/main/examples/editor-tutorial.html
This snippet includes event listeners for file tab clicks to load files and initial setup functions to render tabs and load the default file. It also logs a message indicating the initial state.
```javascript
fileTabs.addEventListener('click', (e) => {
if (e.target.classList.contains('file-tab')) {
loadFile(e.target.dataset.path);
}
});
startBtn.addEventListener('click', startPreview);
saveBtn.addEventListener('click', saveFile);
setupFiles();
renderTabs();
loadFile(currentFile);
log('Files loaded. Click "Start Preview" to launch.');
```
--------------------------------
### HTML Scaffolding for Editor and Preview
Source: https://github.com/macaly/almostnode/blob/main/docs/tutorial-editor.html
Sets up the basic two-column layout for the editor and preview panels. Includes elements for file tabs, a textarea for editing, and buttons for starting the preview and saving. This structure serves as the foundation for the interactive editor.
```html
```
--------------------------------
### Generate Sandbox Files for Deployment
Source: https://github.com/macaly/almostnode/blob/main/docs/security.html
Use this utility to quickly create the necessary files for deploying the cross-origin sandbox, for example, to Vercel. It generates an HTML page, Vercel configuration, and a service worker.
```javascript
import { generateSandboxFiles } from 'almostnode';
import fs from 'fs';
const files = generateSandboxFiles();
fs.mkdirSync('sandbox', { recursive: true });
for (const [filename, content] of Object.entries(files)) {
fs.writeFileSync(`sandbox/${filename}`, content);
}
// Deploy: cd sandbox && vercel --prod
```
--------------------------------
### Manual Service Worker Setup
Source: https://github.com/macaly/almostnode/blob/main/README.md
Copies the service worker file to the public directory, either via bash command or programmatically using Node.js fs module.
```bash
cp node_modules/almostnode/dist/__sw__.js ./public/
```
```typescript
import { getServiceWorkerPath } from 'almostnode/next';
import fs from 'fs';
fs.copyFileSync(getServiceWorkerPath(), './public/__sw__.js');
```
--------------------------------
### Minimal Next.js App with almostnode
Source: https://github.com/macaly/almostnode/blob/main/docs/CONVEX_TUTORIAL.md
Sets up a virtual filesystem, writes project files, and starts a Next.js development server. It then registers the server with a bridge and logs the application URL.
```typescript
import { VirtualFS, Runtime, NextDevServer, PackageManager } from 'almostnode';
import { getServerBridge } from 'almostnode/server-bridge';
// 1. Create virtual filesystem
const vfs = new VirtualFS();
// 2. Write project files
vfs.writeFileSync('/package.json', JSON.stringify({ name: 'my-app' }));
vfs.mkdirSync('/app', { recursive: true });
vfs.writeFileSync('/app/page.tsx', "
export default function Home() {
return
Hello from almostnode!
;
}
");
// 3. Create and start the dev server
const server = new NextDevServer(vfs, {
port: 3000,
preferAppRouter: true,
});
// 4. Register with the server bridge (enables Service Worker routing)
const bridge = getServerBridge();
await bridge.initServiceWorker();
bridge.registerServer(server, 3000);
server.start();
// 5. Navigate to the app
const url = bridge.getServerUrl(3000);
console.log(`App running at: ${url}`);
```
--------------------------------
### Initialize VirtualFS and Project Files
Source: https://github.com/macaly/almostnode/blob/main/examples/editor-tutorial.html
Sets up the VirtualFS with a basic Next.js project structure and files. This includes package.json, layout.tsx, page.tsx, about/page.tsx, and globals.css.
```typescript
import { VirtualFS } from '../src/index.ts';
import { NextDevServer } from '../src/frameworks/next-dev-server.ts';
import { getServerBridge } from '../src/server-bridge.ts';
// ── State ──
let vfs, devServer, devServerUrl;
let currentFile = '/app/page.tsx';
// ── DOM refs ──
const editor = document.getElementById('editor');
const fileTabs = document.getElementById('file-tabs');
const startBtn = document.getElementById('start-btn');
const saveBtn = document.getElementById('save-btn');
const refreshBtn = document.getElementById('refresh-btn');
const statusDot = document.getElementById('status-dot');
const statusText = document.getElementById('status-text');
const previewFrame = document.getElementById('preview-frame');
const placeholder = document.getElementById('preview-placeholder');
const hmrToast = document.getElementById('hmr-toast');
const consoleEl = document.getElementById('console');
// ── Files we can edit ──
const files = [
{ path: '/app/page.tsx', label: 'page.tsx' },
{ path: '/app/layout.tsx', label: 'layout.tsx' },
{ path: '/app/about/page.tsx', label: 'about/page.tsx' },
{ path: '/app/globals.css', label: 'globals.css' },
];
// ── Logging ──
function log(msg, cls = '') {
const line = document.createElement('div');
line.textContent = `[${new Date().toLocaleTimeString()}] ${msg}`;
if (cls) line.className = cls;
consoleEl.appendChild(line);
consoleEl.scrollTop = consoleEl.scrollHeight;
}
function showHmrToast() {
hmrToast.classList.add('show');
setTimeout(() => hmrToast.classList.remove('show'), 2000);
}
// ── Step 1: Create VFS with project files ──
function setupFiles() {
vfs = new VirtualFS();
vfs.writeFileSync('/package.json', JSON.stringify({
name: 'editor-tutorial',
version: '1.0.0',
dependencies: {
next: '^14.0.0',
react: '^18.2.0',
'react-dom': '^18.2.0'
},
}, null, 2));
vfs.mkdirSync('/app', { recursive: true });
vfs.mkdirSync('/app/about', { recursive: true });
vfs.writeFileSync('/app/layout.tsx', `export default function RootLayout({ children }) {
return (
{children}
);
}
`);
vfs.writeFileSync('/app/page.tsx', `'use client';
import { useState } from 'react';
export default function Home() {
const [count, setCount] = useState(0);
return (
Welcome!
This is a Next.js app running entirely in the browser. Edit this file and press Ctrl/Cmd+S to see HMR in action.
This demo shows how to build a file editor with a live Next.js preview using almostnode. The preview runs in an iframe and updates via HMR when you save a file.
Tip: For production use, run the preview iframe on a different origin (e.g., a subdomain) to isolate untrusted code from your app's cookies, localStorage, and DOM.
);
}
`);
vfs.writeFileSync('/app/globals.css', `* { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, -apple-system, sans-serif; background: #fafafa; color: #222; }
a { color: #22c55e; }
a:hover { text-decoration: underline; }
`);
}
// ── Step 2: Render file tabs ──
function renderTabs() {
fileTabs.innerHTML = files.map(f => `` ).join('');
}
function loadFile(path) {
try {
editor.value = vfs.readFileSync(path, 'utf8');
currentFile = path;
renderTabs();
} catch (e) {
log('Error loading ' +
```
--------------------------------
### Create Runtime with Same-Origin Main Thread
Source: https://github.com/macaly/almostnode/blob/main/docs/security.html
Runs code directly on the main thread. This is the simplest setup but provides no isolation, so it should only be used with fully trusted code.
```javascript
const runtime = await createRuntime(vfs, {
dangerouslyAllowSameOrigin: true,
});
```
--------------------------------
### Generic Package Demo Component
Source: https://github.com/macaly/almostnode/blob/main/examples/next-demo.html
Generates a placeholder React component for any other package, indicating it has been installed and showing how to import it via esm.sh. This is a fallback for unhandled packages.
```javascript
'use client'; import React from 'react'; // import ${jsName} from 'https://esm.sh/${packageName}?dev'; export default function ${jsName.charAt(0).toUpperCase() + jsName.slice(1)}Demo() { return (
${packageName} Demo
The ${packageName} package has been installed.
Import via esm.sh:
import ${jsName} from 'https://esm.sh/${packageName}?dev';
); }
```
--------------------------------
### Navigate to Path in Preview
Source: https://github.com/macaly/almostnode/blob/main/examples/next-demo.html
Navigates the preview frame to a specified path. It ensures the path starts with a '/' and constructs the full URL for the preview frame's source.
```javascript
function navigateToPath(path) {
if (!previewActive || !devServerUrl) {
log('Preview not running.', 'error');
return;
}
if (!path.startsWith('/')) path = '/' + path;
const fullUrl = devServerUrl + path.substring(1);
previewFrame.onload = () => {
if (devServer && previewFrame.contentWindow)
devServer.setHMRTarget(previewFrame.contentWindow);
};
log(`Navigating to: ${path}`);
previewFrame.src = fullUrl;
urlInput.value = path;
}
```
--------------------------------
### Running Development Servers
Source: https://github.com/macaly/almostnode/blob/main/README.md
Instructions for running the main application and the sandbox on different ports for local development.
```bash
# Terminal 1: Main app on port 5173
npm run dev
# Terminal 2: Sandbox on port 3002
npm run sandbox
```
--------------------------------
### App Router Route Handler
Source: https://github.com/macaly/almostnode/blob/main/docs/nextjs-guide.html
Define an API endpoint using the App Router's route handler. This example sets up a GET request handler.
```typescript
export async function GET(request) {
return Response.json({ message: 'Hello!' });
}
```
--------------------------------
### Install Scoped Packages
Source: https://github.com/macaly/almostnode/blob/main/docs/core-concepts.html
Scoped packages, identified by the '@' prefix, can also be installed using the `npm.install` method.
```javascript
await npm.install('@hono/node-server');
```
--------------------------------
### Install almostnode Package
Source: https://github.com/macaly/almostnode/blob/main/README.md
Install the almostnode package using npm. This is the first step to using almostnode in your project.
```bash
npm install almostnode
```
--------------------------------
### Container Initialization Options
Source: https://github.com/macaly/almostnode/blob/main/README.md
Shows how to create a new container with custom options for working directory, environment variables, and console logging.
```typescript
interface ContainerOptions {
cwd?: string; // Working directory (default: '/')
env?: Record; // Environment variables
onConsole?: (method: string, args: any[]) => void; // Console hook
}
const container = createContainer({
cwd: '/app',
env: { NODE_ENV: 'development' },
onConsole: (method, args) => console.log(`[${method}]`, ...args),
});
```
--------------------------------
### Install Convex Package with npm
Source: https://github.com/macaly/almostnode/blob/main/docs/CONVEX_TUTORIAL.md
Installs the Convex package using npm within the project directory. Includes progress logging.
```typescript
const npm = new PackageManager(vfs, { cwd: '/project' });
await npm.install('convex', {
onProgress: (msg) => console.log(`[npm] ${msg}`),
});
```
--------------------------------
### PackageManager
Source: https://github.com/macaly/almostnode/blob/main/docs/CONVEX_TUTORIAL.md
Installs npm packages into the virtual filesystem. It supports installing single packages or multiple packages and provides progress updates.
```APIDOC
## Class: PackageManager
### Description
Install npm packages into the virtual filesystem.
### Methods
- `install(packages: string | string[], options?: object)`: Installs one or more npm packages. The `onProgress` option can be used to track installation progress.
- `onProgress(msg: string)`: Callback function to receive installation progress messages.
```