Agent Quickstart ​

Copy-paste this page into your AI agent's chat to give it full context on teenybase.

Introduction ​

You are working with teenybase, a backend framework that deploys to the user's own Cloudflare account (Workers + D1 + R2). The entire backend is defined in a single teenybase.ts config file — no backend code.

Run the CLI ​

Run every command as npx teenybase <command>. After npm install -g teenybase, teeny <command> works too. Never use npx teeny: it downloads an unrelated npm package named teeny.

Early (v0.1): APIs may change before 1.0.

Setup ​

There are two paths depending on whether this is a new project or an existing one. Infer which from conversation context (e.g. the user already has a package.json, or says "add a backend to my app" → Option B). If unclear, ask: "Are we starting a new project or adding teenybase to an existing one?"

Option A: New project ​

bash
npx teenybase create my-app -t with-auth -y
cd my-app

Important: Always pass -t and -y when running non-interactively (scripts, CI, coding agents). Without them, a command that needs to ask a question fails with exit code 1 when stdin is not a TTY, and the error names the flag to pass.

FlagWhat it does
-t, --template <template>Set the project template. Values: with-auth (users table + auth + rules) or blank (empty project).
-y, --yesSkip all confirmation prompts and use defaults.

If neither flag is given, the CLI prompts interactively for template and deploy target.

This creates the directory, scaffolds all files, and runs npm install. You're ready to go.

Files created:

  • package.json — deps: teenybase, hono ^4, devDeps: wrangler ^4, typescript ^5, @cloudflare/workers-types ^4
  • teenybase.ts — backend config (tables, auth, rules)
  • src/index.ts — worker entry point (imports teenybase, wires up Database + extensions)
  • wrangler.jsonc — Cloudflare Workers config with D1 binding PRIMARY_DB
  • .dev.vars — local secrets: JWT_SECRET, JWT_SECRET_USERS, ADMIN_JWT_SECRET, ADMIN_SERVICE_TOKEN, POCKET_UI_VIEWER_PASSWORD, POCKET_UI_EDITOR_PASSWORD
  • worker-configuration.d.ts — TypeScript type for CloudflareBindings
  • tsconfig.json — includes path alias "virtual:teenybase": ["./teenybase"]
  • migrations/ — empty, auto-populated by generate / deploy
  • .gitignore — ignores node_modules, .local-persist, .dev.vars, .prod.vars, migrations

Apply the migrations and start the local dev server:

bash
npx teenybase deploy --local --yes
npx teenybase dev

API is at http://localhost:8787/api/v1.

Option B: Add to existing project ​

bash
npm install teenybase hono
npm install -D wrangler @cloudflare/workers-types typescript
npx teenybase init -y

init detects existing files and only creates what's missing. It will not overwrite your package.json — it only creates one if none exists. If you already have a tsconfig.json, it patches in the "virtual:teenybase": ["./teenybase"] path alias without replacing it.

Important: Since init does not modify an existing package.json, you must install the dependencies yourself (the npm install lines above).

After init, apply the migrations and start the local dev server:

bash
npx teenybase deploy --local --yes
npx teenybase dev

Key files ​

FilePurpose
teenybase.tsBackend config — tables, fields, auth, rules, actions. In most apps, this is the main file you edit.
src/index.tsWorker entry point. Usually unchanged unless you need custom routes or R2 storage.
wrangler.jsoncCloudflare Workers config, D1/R2 bindings
.dev.varsLocal secrets (6 keys: JWT_SECRET, JWT_SECRET_USERS, ADMIN_JWT_SECRET, ADMIN_SERVICE_TOKEN, POCKET_UI_VIEWER_PASSWORD, POCKET_UI_EDITOR_PASSWORD)
.prod.varsProduction secrets (same keys). Generated with random values on the first remote deploy. Gitignored.
migrations/Auto-generated SQL. Don't edit manually.

CLI commands ​

bash
npx teenybase create <name> [-t <tpl>] [-y]  # Scaffold new project (runs npm install)
npx teenybase init [-t <tpl>] [-y]           # Add teenybase to existing project
npx teenybase generate --local               # Generate migrations from config changes
npx teenybase deploy --local --yes           # Generate + apply migrations to the local database
npx teenybase dev                            # Start local dev server (port 8787)
npx wrangler login                           # One-time: authenticate with Cloudflare
npx teenybase deploy --remote --yes          # Deploy to the user's Cloudflare account
npx teenybase secrets --remote --upload      # Upload .prod.vars to production
npx teenybase logs                           # Stream logs from the deployed worker
npx teenybase --help                         # List commands and options

Config format ​

ts
import { DatabaseSettings } from 'teenybase'
import { baseFields, authFields, createdTrigger, updatedTrigger } from 'teenybase/scaffolds/fields'

export default {
  appUrl: 'http://localhost:8787',
  jwtSecret: '$JWT_SECRET',        // Resolved from .dev.vars / .prod.vars
  appName: 'My App',
  tables: [
    {
      name: 'users',
      autoSetUid: true,
      fields: [...baseFields, ...authFields],
      triggers: [createdTrigger, updatedTrigger],
      extensions: [
        { name: 'auth', jwtSecret: '$JWT_SECRET_USERS', jwtTokenDuration: 3600, maxTokenRefresh: 5 },
        { name: 'rules', createRule: 'true', viewRule: 'auth.uid == id', listRule: 'auth.uid == id', updateRule: 'auth.uid == id', deleteRule: 'auth.uid == id' },
      ],
    },
    {
      name: 'posts',
      autoSetUid: true,
      fields: [
        ...baseFields,
        { name: 'title', type: 'text', sqlType: 'text' },
        { name: 'body', type: 'text', sqlType: 'text' },
        { name: 'author', type: 'text', sqlType: 'text' },
        { name: 'published', type: 'bool', sqlType: 'boolean', default: '0' },
      ],
      triggers: [createdTrigger, updatedTrigger],
      extensions: [
        { name: 'rules', listRule: 'published == true', viewRule: 'published == true', createRule: 'auth.uid == author', updateRule: 'auth.uid == author', deleteRule: 'auth.uid == author' },
      ],
    },
  ],
} satisfies DatabaseSettings

If you keep the default scaffold from teeny create, it also includes authCookie: { name: 'teeny_auth' } and passwordConfirmSuffix: 'Confirm' on the users auth extension. authCookie enables cookie-based sessions for OAuth redirect callbacks and any SSR layer you add; sign-up and password-reset requests must include passwordConfirm.

In the posts example above, set author to the signed-in user's record.id on insert so the ownership rules line up with auth.uid == author.

API endpoints ​

Base URL: http://localhost:8787/api/v1 (local). For deployed apps, use the worker URL printed by npx teenybase deploy --remote (also saved in infra.jsonc) and append /api/v1.

CRUD:

POST /table/{table}/insert      { "values": {...}, "returning": "*" }
GET|POST /table/{table}/select  ?where=...&order=...&limit=...
GET|POST /table/{table}/list    Same as select but returns { items, total }
GET  /table/{table}/view/{id}
POST /table/{table}/update      { "where": "id == '...'", "setValues": {...} }
POST /table/{table}/edit/{id}   { "field": "value" }
POST /table/{table}/delete      { "where": "id == '...'" }

Auth:

POST /table/{table}/auth/sign-up              { "username", "email", "password", "passwordConfirm", "name" }
POST /table/{table}/auth/login-password       { "identity", "password" }
POST /table/{table}/auth/refresh-token        { "refresh_token" }
POST /table/{table}/auth/request-password-reset   { "email" }
POST /table/{table}/auth/confirm-password-reset   { "token", "password", "passwordConfirm" }
POST /table/{table}/auth/request-verification     Authorization: Bearer <token>
POST /table/{table}/auth/confirm-verification     { "token" }
POST /table/{table}/auth/logout                   Authorization: Bearer <token>
POST /auth/logout                                 Clears auth cookie only

Auth header: Authorization: Bearer <token>

Other:

GET  /health
GET  /doc/ui          # Swagger UI
GET  /doc             # OpenAPI 3.1.0 JSON

Workflow ​

  1. Edit teenybase.ts
  2. Run npx teenybase deploy --local --yes (generates and applies migrations)
  3. Keep npx teenybase dev running (it reloads after each local deploy)
  4. Test with curl or the frontend
  5. When ready: npx wrangler login (once), then npx teenybase deploy --remote --yes