Browse the docs

Start

fuast docs

Start here. What a capsule is, the server and client contracts, auth and env, inspection, deploys, limits, and where to read next.

fuast is a small cloud for team software. An agent writes a little full-stack TypeScript app called a capsule, fuast runs it with a database, sign-in, storage, schedules, and email built in, and you share it with coworkers like a doc.

If you are an agent, treat the capsule directory as the whole app. Write the server contract, write the Preact client, run the fuast CLI, read the runtime state, and deploy without leaving the terminal. The agent start guide is the short version of this site.

An agent without a terminal can do the same through the MCP server at https://fuast.com/mcp: Claude, ChatGPT, Cursor, and VS Code connect to it and deploy from file contents.

Start here

bunx @revnu/fuast new my-app --template todo
cd my-app
bunx @revnu/fuast dev

fuast create is an alias for fuast new. To turn the current, empty directory into a capsule, run fuast init. Templates: todo, guestbook, signature, approvals, live-demo. See examples. The dashboard's New app button deploys the same templates without a terminal.

A capsule has this shape:

server/index.ts      default export capsule({...}): schema, queries, mutations, actions, endpoints, schedules
client/index.tsx     export function App(): the Preact UI
shared/              pure TypeScript both sides import
.env.fuast.server    optional server-only env (KEY=value lines)
favicon.svg          optional (.ico also works)
fuast.json           {"app": "<slug>"}, written by the first deploy. Commit it.
fuast-env.d.ts       type declarations for fuast/server, fuast/client, fuast/ui
tsconfig.json
AGENTS.md            instructions for coding agents (CLAUDE.md imports it)

Import rules:

  • server/ imports fuast/server and relative files.
  • client/ imports fuast/client, preact, preact/hooks, preact/jsx-runtime, and relative files (and, optionally, the fuast/ui component kit).
  • shared/ imports only relative files.
  • No npm packages and no Node built-ins anywhere.

Server contract

import { boolean, capsule, endpoint, json, mutation, query, string, table, userId } from "fuast/server";

export default capsule({
  name: "Notes",
  schema: {
    notes: table({
      body: string(),
      pinned: boolean().default(false),
      ownerId: userId()
    }).index("by_owner", ["ownerId"])
  },

  queries: {
    notes: query(async (ctx) => {
      const { userId } = ctx.auth.requireIdentity();
      return ctx.db.notes
        .withIndex("by_owner", (q) => q.eq("ownerId", userId))
        .order("desc")
        .collect();
    })
  },

  mutations: {
    addNote: mutation(async (ctx, body: string) => {
      const { userId } = ctx.auth.requireIdentity();
      const clean = body.trim().slice(0, 500);
      if (!clean) throw new Error("Write something first.");
      return ctx.db.notes.insert({ body: clean, ownerId: userId });
    })
  },

  endpoints: {
    health: endpoint({ method: "GET", path: "/api/health" }, () => json({ ok: true }))
  }
});

Handlers receive ctx:

  • ctx.auth: who is calling. requireIdentity() returns a guest or account, requireSignedIn() returns an account, both throw otherwise.
  • ctx.db: async table access through declared indexes. Read-only in queries, actions, and read-only endpoints.
  • ctx.env: server-only values from .env.fuast.server and the dashboard.
  • ctx.log: structured logs you read with fuast logs.
  • ctx.storage, ctx.email, ctx.team, ctx.workspace: files, email, workspace-shared tables, and workspace members.
  • Global fetch() for outbound HTTP.

Details: capsule API, database.

Client contract

import { canAccessApp, createClient, retryAuth, SignInButton, useAuth } from "fuast/client";
import { useState } from "preact/hooks";
import type app from "../server/index";

const client = createClient<typeof app>();

export function App() {
  const auth = useAuth();
  if (auth.isLoading) return null;
  if (!canAccessApp()) {
    return (
      <main className="p-6">
        {auth.error ? <p role="alert">{auth.error}</p> : <p>Sign in to use this app.</p>}
        {auth.error ? <button type="button" onClick={() => void retryAuth()}>Retry</button> : null}
        <SignInButton />
      </main>
    );
  }
  return <Notes />;
}

function Notes() {
  const notes = client.useQuery("notes");
  const addNote = client.useMutation("addNote");
  const [draft, setDraft] = useState("");
  return (
    <main className="p-6">
      <form onSubmit={(e) => { e.preventDefault(); void addNote(draft).then(() => setDraft("")); }}>
        <input value={draft} onInput={(e) => setDraft(e.currentTarget.value)} />
      </form>
      {notes === undefined ? null : notes.length === 0 ? (
        <p>No notes yet. Write one above.</p>
      ) : (
        <ul className="transition-opacity duration-200 starting:opacity-0">
          {notes.map((n) => <li key={n.id}>{n.body}</li>)}
        </ul>
      )}
    </main>
  );
}

client.useQuery returns undefined until the first result, then re-renders whenever a write changes the data it read. Mutations and actions return promises. See capsule API.

Auth and env

Every app belongs to a workspace (your company, by verified email domain). Sharing decides who can open it: private (you and people you add), workspace (your coworkers), or public (anyone with the link, including guests). Public apps give visitors a guest session until they sign in, and their userId() data follows them to their account. See auth and teams.

Server secrets go in .env.fuast.server:

OPENAI_API_KEY=sk-...
WEBHOOK_SECRET=whsec_...

Read them only in handlers with ctx.env.OPENAI_API_KEY. fuast dev loads the file. fuast deploy uploads it. Keep it out of git (the starter .gitignore does).

Inspect the runtime

While fuast dev runs:

fuast check
fuast run notes
fuast run addNote '"first note"'
fuast inspect --port 3000
fuast inspect --query notes
fuast db dump --port 3000
fuast logs --port 3000

fuast run calls a handler headlessly and prints its result. inspect --query shows how many rows one query read for what it returned. Locally, handler errors in fuast logs carry stacks mapped to your source. See test and debug.

For a deployed app, pass its slug (from fuast.json) or URL. Without one, these commands target fuast dev:

fuast inspect my-app
fuast run notes my-app
fuast db dump my-app
fuast logs my-app --follow

Dev and hosted apps serve the same /__fuast/* inspection routes with the same JSON. Use them before guessing. See reference.

Deploy

fuast check
fuast deploy

deploy needs no account. Without a login it puts the app online as a preview for 72 hours and prints a preview link and a claim link. The person the app is for opens the claim link, signs in, and the app is theirs: private, with the data it already holds. See deploy without an account.

fuast login
fuast deploy
fuast share --visibility workspace

fuast login opens a browser page where a person signs in and approves the CLI, once per machine. CI sets FUAST_TOKEN instead. Logged in, deploy goes straight to that account, and after a claim it keeps deploying the claimed app. deploy uploads source, type checks it (type errors block the deploy), builds it, and swaps it in with the data intact. Every deploy is an immutable record: fuast deploy list shows them and fuast deploy rollback <id> returns to one. See reference.

Current limits

  • One server entry (server/index.ts) and one client entry (client/index.tsx).
  • No npm packages, no Node built-ins, no CSS files. Tailwind classes compile automatically.
  • Per handler: 1000 rows returned, 5000 rows read, 4 MiB read, 1000 writes, 5 s of CPU, 10 s wall clock.
  • Per app: 100000 rows, 64 MiB of rows, 100000 requests and 20000 mutations per UTC day, 100 emails per day.
  • Files: 25 MiB each, 1 GiB per workspace.

Every limit, its error, and what to change: limits.

  • Agent start guide: the build, verify, deploy loop for coding agents.
  • Capsule API: server, client, handler capabilities, types.
  • Database: indexes, field types, pagination, schema changes, ingest.
  • Auth: accounts, guests, sign-in policy, endpoint credentials.
  • Teams: workspaces, sharing, invites, members, team tables.
  • Custom domains: serve an app at a domain you own, with DNS verification and HTTPS.
  • Storage: user uploads and server-side files.
  • Schedules: cron jobs.
  • Jobs: run a mutation or action later with ctx.scheduler, durably and transactionally.
  • Email: transactional email from handlers.
  • Agent tools: expose handlers to browser agents with WebMCP.
  • MCP server: connect Claude, ChatGPT, Cursor, VS Code, or Claude Code and build without a terminal.
  • Test and debug: fuast check, fuast run, inspect --query, logs, run-many.
  • Security: what fuast guarantees and what your capsule must check.
  • Limits: every limit and error.
  • Reference: CLI, inspection routes, HTTP API, env vars.
  • Examples: complete starter apps.
  • Migration to v2: upgrade a capsule written for the old fuast API.
  • Support: platforms, compatibility, persistence.
  • Isolation: how fuast keeps apps apart.
  • llms.txt: an index of every page for agents. /agents.md is the agent start guide, and /docs.json the index as JSON.