API Reference
Complete API documentation for NANO runtime
WinterTC APIs
NANO implements the WinterTC standard for edge runtimes. Unlike Node.js, WinterTC uses web-standard APIs like fetch, Request, and Response.
| API | Status | Description |
|---|---|---|
| fetch() | Full | HTTP client with streaming |
| Request | Full | HTTP request constructor with body |
| Response | Full | HTTP response constructor |
| Headers | Full | Case-insensitive header map |
| URL | Full | URL parsing with all properties |
| URLSearchParams | Full | Query string manipulation |
| TextEncoder | Full | UTF-8 encoding to Uint8Array |
| TextDecoder | Full | UTF-8 decoding from Uint8Array |
| ReadableStream | Full | Streaming data interface |
| WritableStream | Full | Output streaming with backpressure |
| console | Full | log, error, warn, info, debug |
| setTimeout/setInterval | Full | Timer functions with clearing |
WebAssembly
V8 built-in WASM engine for executing binary modules in isolates.
const wasmBytes = await fetch('/module.wasm').then(r => r.arrayBuffer());
const wasmModule = await WebAssembly.compile(wasmBytes);
const memory = new WebAssembly.Memory({ initial: 1 });
const instance = await WebAssembly.instantiate(wasmModule, {
env: { memory }
});
const result = instance.exports.add(1, 2);
WebAssembly API
| Method | Description |
|---|---|
| WebAssembly.compile() | Compile bytes into a module |
| WebAssembly.instantiate() | Create an instance with imports |
| WebAssembly.Module | Compiled module class |
| WebAssembly.Instance | Runtime instance class |
| WebAssembly.Memory | Linear memory management |
| WebAssembly.Table | Function reference table |
WebCrypto
Full crypto.subtle implementation via Rust crypto crates.
const data = new TextEncoder().encode('hello');
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
const key = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
true,
['encrypt', 'decrypt']
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
data
);
Supported Algorithms
| Algorithm | Operations |
|---|---|
| SHA-256, SHA-384, SHA-512 | digest |
| AES-GCM, AES-CTR, AES-CBC | encrypt, decrypt, generateKey |
| HMAC | sign, verify, generateKey |
| PBKDF2 | deriveKey, deriveBits |
| HKDF | deriveKey, deriveBits |
| RSA-OAEP, RSA-PSS, RSASSA-PKCS1-v1_5 | encrypt, decrypt, sign, verify |
| ECDSA (P-256, P-384) | sign, verify, importKey |
| ECDH (P-256, P-384) | deriveKey, deriveBits |
WebSocket v2.3.0
WebSocket support follows the Cloudflare Workers API. See the WebSocket guide for full details.
export default {
async fetch(request) {
if (request.headers.get('Upgrade') !== 'websocket') {
return new Response('Expected WebSocket', { status: 426 });
}
const [client, server] = new WebSocketPair();
server.addEventListener('message', (event) => {
server.send(`Echo: ${event.data}`);
});
server.addEventListener('close', (event) => {
console.log('Closed:', event.code, event.reason);
});
server.accept();
return new Response(null, { status: 101, webSocket: client });
}
};
WebSocket API
| Member | Description |
|---|---|
| new WebSocketPair() | Returns [client, server] linked pair |
| server.accept() | Accept the connection (required before send) |
| server.send(data) | Send text string or ArrayBuffer |
| server.close(code?, reason?) | Send Close frame |
| server.addEventListener(type, fn) | Register message / close / error handler |
| server.readyState | 0=CONNECTING 1=OPEN 2=CLOSING 3=CLOSED |
Nano.fs (VFS)
Virtual File System API for per-isolate filesystem access.
// Read file
const data = await Nano.fs.readFile('/data/config.json', 'utf-8');
const config = JSON.parse(data);
// Write file
await Nano.fs.writeFile('/data/output.txt', 'Hello, World!');
// Check existence
const exists = await Nano.fs.exists('/data/config.json');
VFS Methods
| Method | Description |
|---|---|
| Nano.fs.readFile() | Read file contents |
| Nano.fs.writeFile() | Write file contents |
| Nano.fs.exists() | Check if path exists |
| Nano.fs.readdir() | List directory contents |
| Nano.fs.mkdir() | Create directory |
| Nano.fs.unlink() | Delete file |
nano:kv v2.2.2+
EdgeStore-backed persistent key-value storage. Hostname-namespaced — each app has its own isolated slice. Zero configuration: the engine initialises on first import.
import { kv } from 'nano:kv';
// Bytes API
await kv.set('hits', new TextEncoder().encode('42'));
const raw = await kv.get('hits'); // Uint8Array | null
new TextDecoder().decode(raw); // "42"
await kv.delete('hits');
// JSON helpers
await kv.setJSON('config', { version: 3 });
const cfg = await kv.getJSON('config'); // { version: 3 }
// Prefix scan
const entries = await kv.list('user:'); // [[key, Uint8Array], ...]
import { openKV } from 'nano:kv';
const cache = openKV('cache');
const sessions = openKV('sessions');
// Namespaces are isolated — same key in different stores never collides
await cache.setJSON('user:1', { name: 'Alice' });
await sessions.setJSON('tok:abc', { uid: 1, exp: Date.now() + 3600_000 });
KV Store API
| Method | Signature | Description |
|---|---|---|
| kv.get(key) | → Uint8Array | null | Read raw bytes |
| kv.set(key, value) | Uint8Array | string | Write raw bytes or string |
| kv.delete(key) | → void | Remove a key |
| kv.list(prefix) | → [string, Uint8Array][] | Scan keys by prefix |
| kv.getJSON(key) | → any | null | Deserialise JSON value |
| kv.setJSON(key, val) | any | Serialise and store JSON |
| openKV(name) | → KVStore | Open a named namespace — same API as kv |
localStorage shim v2.2.2+
A synchronous, browser-compatible localStorage API backed by nano:kv. Copy examples/localStorage-shim.js into your app and import it once — front-end code and Cloudflare Workers patterns that use localStorage.* run unchanged.
// Import once at the top of your app:
import './localStorage-shim.js';
// Then use the standard browser API anywhere:
await localStorage.setItem('theme', 'dark');
const theme = await localStorage.getItem('theme'); // "dark"
await localStorage.removeItem('theme');
localStorage.length; // number of stored keys
localStorage.key(0); // key name at index 0
await localStorage.clear(); // wipe all keys
localStorage API
| Method / Property | Returns | Description |
|---|---|---|
| setItem(key, val) | → Promise<void> | Store a string value |
| getItem(key) | → Promise<string | null> | Read a value; null if missing |
| removeItem(key) | → Promise<void> | Delete a key |
| clear() | → Promise<void> | Remove all keys in this namespace |
| key(n) | → string | null | Return the nth key name |
| length | number | Number of stored entries |
setItem/getItem/removeItem/clear return Promises — unlike the synchronous browser DOM API — because nano:kv operations cross into Rust. Await them or chain with .then().
Node.js Polyfills v2.2.2+
Common Node.js built-ins available via require(). No bundler shim needed — they are injected directly into the V8 context.
const path = require('path');
path.join('/var', 'app', 'config.json'); // /var/app/config.json
path.dirname('/var/app/config.json'); // /var/app
path.basename('/var/app/config.json'); // config.json
path.extname('/var/app/config.json'); // .json
path.isAbsolute('/absolute'); // true
path.normalize('/var//app/../app/f'); // /var/app/f
const { from, alloc, isBuffer, concat } = require('buffer');
const a = from('hello '); // Uint8Array
const b = from('world');
new TextDecoder().decode(concat([a, b])); // "hello world"
isBuffer(a); // true
alloc(16); // zero-filled Uint8Array(16)
// Set vars in app config:
// { "apps": [{ "env_vars": { "NODE_ENV": "production" } }] }
process.env.NODE_ENV; // "production"
process.version; // "v18.0.0"
process.platform; // "linux"
Security note: process.env exposes only the per-app env_vars configured by the operator — never the host process environment. Prevents accidental secret leakage between tenants.