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.

Module Compilation
const wasmBytes = await fetch('/module.wasm').then(r => r.arrayBuffer());
const wasmModule = await WebAssembly.compile(wasmBytes);
Instantiation with Memory
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.ModuleCompiled module class
WebAssembly.InstanceRuntime instance class
WebAssembly.MemoryLinear memory management
WebAssembly.TableFunction reference table

WebCrypto

Full crypto.subtle implementation via Rust crypto crates.

Hashing
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('');
AES-GCM Encryption
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-512digest
AES-GCM, AES-CTR, AES-CBCencrypt, decrypt, generateKey
HMACsign, verify, generateKey
PBKDF2deriveKey, deriveBits
HKDFderiveKey, deriveBits
RSA-OAEP, RSA-PSS, RSASSA-PKCS1-v1_5encrypt, 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.

Echo Server Example
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.readyState0=CONNECTING 1=OPEN 2=CLOSING 3=CLOSED

Nano.fs (VFS)

Virtual File System API for per-isolate filesystem access.

Reading and Writing
// 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.

Default namespace (hostname-scoped)
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], ...]
Named namespaces with openKV()
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 });
Want the browser localStorage API? See the localStorage shim section below — it's built on nano:kv.

KV Store API

Method Signature Description
kv.get(key)→ Uint8Array | nullRead raw bytes
kv.set(key, value)Uint8Array | stringWrite raw bytes or string
kv.delete(key)→ voidRemove a key
kv.list(prefix)→ [string, Uint8Array][]Scan keys by prefix
kv.getJSON(key)→ any | nullDeserialise JSON value
kv.setJSON(key, val)anySerialise and store JSON
openKV(name)→ KVStoreOpen 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.

localStorage-shim.js — usage
// 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 | nullReturn the nth key name
lengthnumberNumber of stored entries
Note: The shim's 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.

require('path')
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
require('buffer')
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)
process.env + process.version
// 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.