Quickstart
Build an app with sign-in and stored data: one command, one install, about a dozen lines of code.
With your coding agent
Paste this one prompt into your coding agent (Claude Code, Cursor, Codex, or any agent that can read a URL). It reads the docs and builds against a local backend, free with no account or card.
Read https://docs.gemmein.com/llms.txt and take my app to its first paying customer.
The rest of this page is the same build by hand.
By hand
import { gemmein } from "@gemmein/sdk"
const g = gemmein("pk_test_...")
// Sign in with an emailed sign-in code, no passwords
await g.auth.sendEmailCode("user@example.com")
await g.auth.verifyEmailCode({ email: "user@example.com", code: "12345678" })
// Store data. The server enforces the collection's safety rule.
// Create the "tasks" collection first (see Collections below).
await g.collection("tasks").create({ title: "Buy milk", done: false })
const { records } = await g.collection("tasks").list()
Replace pk_test_... with your app key. On the local backend it is the
pk_local_... key the backend prints, passed with
{ apiUrl: "http://127.0.0.1:4545" } as the second argument to
gemmein(). In the cloud, every call needs an app key (pk_...),
shown on the Your app page.
This guide starts from an idea, with nothing built yet. If you already have an app, read the fit assessment at the top of llms.txt first. It compares what you have with what Gemmein refuses and gives a verdict before you install anything.
Run it locally
Building locally is free and needs no account. You run no server and write no security rules: you choose each collection's rule once, and Gemmein enforces it. Start the local backend in your project folder:
npx -y gemmein dev
This starts a local backend on http://127.0.0.1:4545, with no signup,
account or card. It prints sign-in codes in the terminal instead of emailing them and
simulates checkout, so nothing leaves your machine. Its boot card prints the local app
key.
Then install the SDK:
npm i @gemmein/sdk
The SDK is dependency-free pure ESM. With no bundler, copy
dist/index.js from the package next to your HTML and import it from a
<script type="module">. It works on any static host.
Move to the cloud
When the app works locally, run npx gemmein check to see what going live
still needs. Then run npx gemmein sync. It signs you in at
app.gemmein.com with a sign-in code, free and
with no card. A card is needed only when you go live.
Building with an AI tool: the Your app page gives you a ready-made prompt that covers the whole SDK. Paste it into your AI tool. The machine-readable package guide, which covers what your code calls, is also included in the package.
Collections
You create collections. The SDK never does, and a
new app has none. Locally, the first write to a collection that does not exist yet asks
you in the dev terminal which of the seven safety rules it follows, or you run
npx gemmein collection add <name> from a second terminal. In the
cloud, add it on the dashboard's Collections page (one click) or carry it there with
npx gemmein sync. There, a 404 unknown_collection means
the collection doesn't exist yet.
Names use lowercase letters, numbers and underscores only: saved_games
works and savedGames does not. A bad name throws the moment
collection() is called.
Record shape
Records come back wrapped, with your fields under .data:
const task = await tasks.create({ title: "Buy milk", done: false })
// { id, data: { title, done }, createdAt, updatedAt, ... }
task.data.title // ✓ "Buy milk"
task.title // ✗ undefined, and if your UI shows blanks this is why
Sessions
Sessions persist across page reloads. Each person has one session: verifying a new
code revokes that email's older sessions. A stale token throws auth_expired
once and the SDK clears it; a retry (or signing in again) recovers.
Where next
- Data: pick the right safety rule for each collection.
- Auth & sessions: the full sign-in API.
- Payments: charge for things without building a webhook.
- Test your safety rules in CI: check your app's safety rules with live calls.