Getting started
Five minutes from clone to first item.
Prerequisites
- Bun ≥ 1.1 (
curl -fsSL https://bun.sh/install | bash) - Optional: Postgres 14+ for production. Dev defaults to Bun’s built-in SQLite.
Install + run
git clone https://github.com/your/workeros && cd workerosbun installcp apps/web/.dev.vars.example apps/web/.dev.vars
# Apply migrations to local SQLitebun run db:migrate:sqlite
# Start Vite + Cloudflare miniflare in one process on :5173# (admin SPA + Worker bundled — no separate API port, no proxy)bun run devOpen http://localhost:5173/sign-up and create the first user — they
auto-receive the admin role. Subsequent sign-ups get authenticated.
Your first collection
In the admin UI, go to Collections → New and define:
slug: postsfields: - title (text, required) - body (longtext) - published (boolean) - views (integer)ownerScoped: trueClick Create. The API runs CREATE TABLE c_posts (...) against the
live database — no redeploy.
Your first items
Click on posts in the list, then + New item. Type-aware inputs
render based on field type (textarea for longtext, checkbox for boolean,
number input for views). Save.
The owner-scoped flag auto-seeds permissions for the authenticated
role: each user only reads/writes their own items. Admin sees all.
Query
# RESTcurl http://localhost:5173/api/items/posts?limit=10 \ --cookie "$(cat /tmp/cookie.txt)"
# REST with filter (DSL — same as permissions)curl "http://localhost:5173/api/items/posts?filter=$(echo '{"published":{"_eq":true},"views":{"_gt":10}}' | jq -sRr @uri)&sort=-views"
# GraphQLcurl -X POST http://localhost:5173/api/graphql \ -H "content-type: application/json" \ -d '{"query":"{ posts(sort:\"-views\", limit:5) { id title views } }"}'Generate types for your client
bun run workeros gen-types http://localhost:5173 --out src/types.tsThe CLI fetches /api/collections and emits one TypeScript interface per
collection plus a Collections registry. Use with @workeros/client:
import { createClient } from "@workeros/client";import type { Posts } from "./types";
const wks = createClient({ url: "http://localhost:5173" });const r = await wks.from<Posts>("posts").list({ filter: { published: { _eq: true } }, sort: "-views", limit: 10,});What next
- Permissions DSL — granular role + condition rules
- Sandbox functions — JavaScript code that runs in a sandbox
- Deployment — push to Bun, Workers, Vercel, or Netlify