GETTING STARTED

Installation

Futon ships as a single zero-dependency package. You'll also want a runtime adapter from @rasenganjs/runtime to actually bind a port — Futon itself only turns a Request into a Response.

Requirements

  • Node.js 18+ (for the Web Request/Response/Headers globals), or Bun / Deno / Cloudflare Workers.
  • An ESM project — Futon is published as "type": "module".

Installation

Automatic Installation

The fastest way to start a new Futon project is with the create-rasengan CLI, which scaffolds a working project for you. Futon scaffolding shipped in a newer release than what create-rasengan@latest currently points to — use the beta dist-tag to get it.

[01]Create a new project
Run the following command to create a new project.
Terminal
npx create-rasengan@beta --kind futon
[02]Follow the prompts
If you didn't pass --kind, you'll be asked which kind of project to create — select "futon". You'll also be asked to name your project.
Terminal
- What would you like to name your project? - What kind of project would you like to create?
[03]Install dependencies
create-rasengan copies the template files but doesn't install dependencies for you. Move into the new folder and install them.
Terminal
cd my-app npm install
[04]Run the application
Run the following command to start the development server.
Terminal
npm run dev

The scaffolded project is a minimal Futon app wired to NodeDevAdapter — a / route, a /health route, and an onError handler, ready to extend.

Manual Installation

npm
pnpm
yarn
bun
npm install @rasenganjs/futon @rasenganjs/runtime

Package Layout

Futon's main entry (@rasenganjs/futon) exports everything except one thing:

What lives where
import { fileUpload, MemoryStorage } from '@rasenganjs/futon'; // diskStorage is NOT in the main entry — // it imports node:fs, which must stay out of WinterCG/workerd bundles. import { diskStorage } from '@rasenganjs/futon/upload/disk';

See Storage Engines for why diskStorage lives behind its own subpath.

Verifying the Install

Create a minimal handler and run it in-process, without a server, using Futon.fetch() directly:

smoke-test.ts
import { Futon, json } from '@rasenganjs/futon'; const app = new Futon(); app.get('/', async () => json({ ok: true })); const response = await app.fetch(new Request('http://localhost/')); console.log(await response.json()); // { ok: true }

This is exactly how Futon's own test suite works — no HTTP server required to exercise the pipeline.

Introduction
Quick Start