### 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.

Routes:

/api/users — list all users

/api/time — current time

`); }); // 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.

{count}

); } `); vfs.writeFileSync('/app/about/page.tsx', `export default function About() { return (

About

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. ```