Skip to main content
This walkthrough gets a Pylon server running with a schema, one policy, and one server function. You’ll then hit the API with curl to see it work end-to-end. Once you want a realtime UI on top, point the React SDK, Swift SDK, or React Native SDK at the running server, or clone one of the example apps.
Just want a working app? One command, no separate install:
npm create @pylonsync/pylon@latest my-app -- --template todo
cd my-app && npm run dev
That scaffolds a single full-stack Pylon app — SSR React 19 frontend + API served from one port, no Next.js, no monorepo. The Pylon CLI ships as a dependency, so npm run dev runs it — you don’t need to install anything globally. Templates: default (SaaS), todo, chat, shop, consumer, waitlist, ai-chat, and more — run npm create @pylonsync/pylon@latest with no args to pick one. Every app ships with a test harness (pylon test) wired up.Ready to ship? npm run deploy (or pylon deploy — see Deploy).
The rest of this page builds a minimal backend by hand so you can see each piece. It uses a global pylon binary; if you’d rather start from the scaffold above, skip to Concepts.

1. Install the CLI

curl -fsSL https://www.pylonsync.com/install.sh | bash
Downloads a prebuilt pylon binary to ~/.local/bin. Linux and macOS, x86_64 and arm64. No Rust toolchain required. (The npm create scaffold above doesn’t need this — it bundles the CLI. Install globally when you want pylon on your PATH for the from-scratch flow below.) Bun ≥ 1.0 is needed at runtime to execute server functions and render SSR — Pylon runs your TypeScript on it. Verify:
pylon --version
Other ways to install:
# Cargo (compiles from source)
cargo install pylon-cli

# Docker
docker pull ghcr.io/pylonsync/pylon:latest

2. Scaffold a new app

pylon init notes
cd notes
This scaffolds a Bun workspace with the API at apps/api/:
notes/
  apps/
    api/
      app.ts             # schema + manifest entry point
      sdk.ts             # local re-export of @pylonsync/sdk
      tsconfig.json
      package.json
  package.json           # workspace root
  .gitignore
  README.md
pylon init scaffolds the backend only — no frontend framework, because Pylon renders React on the server natively. To also generate a separate frontend, pass --frontend react (Vite), --frontend tanstack, or --frontend nextjs, or pick interactively when stdin is a TTY. For a full-stack app with SSR pages, use npm create @pylonsync/pylon (above) instead. You’ll add a functions/ directory under apps/api/ by hand in step 4.

3. Define the schema

Replace apps/api/app.ts with:
import { entity, field, policy, buildManifest } from "@pylonsync/sdk";

const Note = entity(
  "Note",
  {
    title: field.string(),
    body: field.string(),
    authorId: field.string(),
    updatedAt: field.datetime(),
  },
  {
    indexes: [{ name: "by_author", fields: ["authorId"], unique: false }],
  },
);

const notePolicy = policy({
  name: "note_public",
  entity: "Note",
  allowRead: "true",
  allowInsert: "auth.userId == data.authorId",
  allowUpdate: "auth.userId == data.authorId",
  allowDelete: "auth.userId == data.authorId",
});

const manifest = buildManifest({
  name: "notes",
  version: "0.1.0",
  entities: [Note],
  policies: [notePolicy],
  queries: [],
  actions: [],
  routes: [],
});

console.log(JSON.stringify(manifest, null, 2));
The trailing console.log is required — pylon dev captures stdout as the manifest.

4. Add a server function

Create apps/api/functions/createNote.ts:
import { mutation, v } from "@pylonsync/functions";

export default mutation({
  // `auth: "guest"` lets the guest session from step 6 call this. The
  // default is `auth: "user"`, which rejects guest sessions — switch to it
  // once you have real accounts. Either way `ctx.auth.userId` is a stable
  // string, so it's safe to use as the author id.
  auth: "guest",
  args: {
    title: v.string(),
    body: v.string(),
  },
  async handler(ctx, args) {
    const id = await ctx.db.insert("Note", {
      title: args.title,
      body: args.body,
      authorId: ctx.auth.userId,
      updatedAt: new Date().toISOString(),
    });
    return { id };
  },
});
The filename becomes the RPC name — this will be callable at POST /api/fn/createNote. pylon init already adds @pylonsync/sdk + @pylonsync/functions to apps/api/package.json. If you skipped init or stripped the deps, install them manually:
cd apps/api && bun add @pylonsync/sdk @pylonsync/functions

5. Run the server

cd apps/api
pylon dev
pylon dev auto-discovers app.ts (and schema.ts for legacy projects), watches app.ts and functions/*.ts, auto-migrates the database (SQLite at .pylon/dev.db by default, Postgres if DATABASE_URL is set), and serves the API on http://localhost:4321. Expected output:
✓ notes v0.1.0 — 1 entities, 0 queries, 0 actions, 1 policies, 0 routes
  Server:   http://localhost:4321
  Database: .pylon/dev.db

6. Hit the API

Create a guest session:
curl -X POST http://localhost:4321/api/auth/guest
# → { "token": "eyJ…", "user_id": "usr_01H…" }
Call the mutation (replace TOKEN with the value from above):
curl -X POST http://localhost:4321/api/fn/createNote \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"First note","body":"hello from Pylon"}'
# → { "id": "not_01H…" }
List the rows:
curl http://localhost:4321/api/entities/Note
# → [{ "id": "not_01H…", "title": "First note", ... }]
You now have a working Pylon backend with a typed schema, row-level policy, RPC function, and HTTP API.

Next steps

Entities

All the field types and index options.

Policies

How row-level access rules work.

Functions

Queries, mutations, actions, validators.

Live queries

How db.useQuery stays in sync.

Testing

pylon test — pure logic, components, functions over HTTP.
Want a full UI on top? For all three, the same Pylon server backs the UI — wire format is identical across platforms.

Hand the rest to a coding agent

Once your backend is running, the rest is shell. Pylon Cloud has a one-paste handoff flow that signs your coding agent (Claude Code, Codex, OpenCode, Cursor, Aider, grok build) into your account, installs the Pylon skill, and asks what to build — no token in chat history. From there the agent can use the full CLI surface: pylon secrets, pylon logs tail, pylon deploy, pylon domains add, pylon db backup, pylon data list <Entity>, etc.