Real accounts, without the password problem.

Sign-up and sign-in for the people who use your app. A code in their inbox, a passkey on their phone, a session, a sign-out button, and a login page. Two lines of config, on every plan, including free.

— what your AI actually does

You ask for accounts. It ships a login.

No identity dashboard, no client secrets, no callback URLs. Your agent adds a block to the project config and declares who each route is for. Deploying that mounts the sign-in endpoints, creates the account tables, and puts the browser client on every page.

you, to your AILet people sign up and keep their own reading list
hatchable.toml
# end users: people who sign up on your app
[auth]
enabled   = true
providers = ["email"]  # codes; passkeys ride along

# each person sees only their own rows
[db.tables.books]
read  = "own"
write = "own"
api/books.js
import { db } from 'hatchable';

export const access = 'user';
export const methods = ['POST'];

export default async function (req, res) {
  // req.user is guaranteed here. Anyone signed
  // out was turned away before this ran.
  await db.query(
    'INSERT INTO books (user_id, title) VALUES ($1, $2)',
    [req.user.id, req.body.title]
  );
  res.json({ ok: true });
}
the gate runs at the edge, not in your handler. there is no session to look up and no 401 to write.
— what you get

Everything sign-in needs, and nothing to run.

The accounts, the sessions, the ceremonies, and the abuse limits are the platform's job. What is left for your app is the part that is actually yours: what a signed-in person can see and do.

Email codes

A code in the inbox, never a password

Someone types their address and gets a six-digit code. It is good for ten minutes, five wrong guesses burn it, and it is stored hashed rather than in plain text. First sign-in creates the account; there is no separate sign-up form.

Nobody picks a weak password, because nobody picks a password.

Passkeys

Face ID and Touch ID, included

After the first sign-in your app can offer a passkey, and returning visitors are one prompt away from being back in. Saved passkeys show up in the email field's autofill, and if a person cancels or their device cannot do it, the code path is still there.

A regular comes back on Tuesday and never opens their inbox.

Google

Continue with Google, under your name

Add google to the providers list and the button appears once you finish a one-time console setup: a domain you have verified, plus your own Google client, so the consent screen shows your brand rather than ours. Email stays available alongside it.

Sign up by email in March, use Google in June, still one account.

Access levels

Your customers and your team are different people

Every route says who it is for in one line. user means someone who signed up on your app. member means a Hatchable collaborator on the project, which is you and whoever you invited to build it. admin narrows that to owners, and scheduler is for background jobs only.

The customer dashboard is user. The staff console is admin. They never overlap.

Sessions

Stay signed in, and sign out for real

Signing in sets a cookie that JavaScript cannot read, scoped to your app and kept separate from the Hatchable session you build with. It lasts thirty days, refreshes while a person keeps using the app, and expires for good after six months. Sign-out is one call.

No session store to run, no token rotation to think about.

Login page

A sign-in screen that looks like your app

There is always a working page at /login, drawn with your theme file and your logo, so sign-in can never dead-end. Put your own page at that path and yours wins automatically. Signed-out visitors are sent there and returned to whatever they were trying to reach.

Ask for a login screen in your own colors and you get one.

Signed out

Anonymous is a design decision, not an error

A public route can serve both audiences from one handler: read the signed-in person, get them or get nothing, and vary the page. Signed-out is the normal case for a visitor who just arrived, so it should look like a front door, not a rejection.

Anyone can read the recipes. Saving one is what asks you to sign in.

Invite only

Close the door when the audience is a list

Switch sign-up to invite and the rule becomes: an existing account, or an address you invited. Invites are rows your admin pages add and remove, never a list sitting in a config file, and an uninvited address is refused before any code is sent.

A client portal where the only people who can get in are the ones you added.

— the numbers

The spec sheet, in plain terms.

Turning it onAn [auth] block in hatchable.toml. Available on every plan, including free.
Sign-in methodsEmailed one-time code, always on. Passkeys on top of it. Google as an extra provider once you connect your own Google client on a verified domain.
CodesSix digits, valid for ten minutes, burnt after five wrong attempts, stored as a hash rather than in the clear.
SessionsAn HttpOnly, Secure cookie scoped to your app and separate from your Hatchable account session. Thirty days, refreshed on use, with a hard ceiling at 180 days.
Route accesspublic, user, member, admin, scheduler. Declared per file, enforced at the edge before your code runs, and required on every route.
In your handlerOn a user route, req.user is there: id, email, name, and profile image. On a public route you read it yourself and it may be empty.
User idsOpaque text, not numbers. Store them in text columns and key your own tables off them.
Per-row rulesMark a table private-per-person and Postgres scopes every query to the signed-in user. How row access works →
ReservedThe platform owns the sign-in endpoints and the account tables. A deploy that tries to take them over is rejected, and password libraries are rejected with it.
Abuse limitsCode requests are throttled per address and per network, so nobody can use your sign-in form to flood a stranger's inbox or probe which addresses exist.
Accounts per plan100 on free, 1,000 on Builder, 5,000 per project on the App plan. Full table →

Numbers current as of August 2026 and enforced by the same table the pricing page renders from.

— things people ask for

Say it like this.

You never have to name a library or a provider. These are ordinary sentences that turn into accounts, gates, and a login screen.

accounts"Let people sign up so they have their own saved list"
gating"Only signed-in people should be able to post a comment"
mixed"Anyone can browse, but saving something asks you to sign in"
passkeys"Offer Face ID for people coming back"
invites"Only the clients I invite should be able to create an account"
design"Make the sign-in page match the rest of the site"
— common questions

Asked and answered.

Do I need a separate auth service?

No. Sign-in is part of the platform, the way the database is. There is no identity provider to sign up for, no keys to paste, no callback URLs to configure, and no per-user bill on top of your plan. You turn it on in your project config and deploy.

Are there passwords anywhere?

No. There is no password field, no reset flow, and no password column in the database. People prove they own an email address with a one-time code, then add a passkey if they want a faster way back in. A whole category of support request stops existing.

What is the difference between a member and a user?

They are two different populations. A member is a Hatchable collaborator on your project, meaning you and anyone you invited to help build it. A user is someone who signed up on your deployed app. A route declared for members lets your team in and turns your customers away; a route declared for users does the opposite. Being a collaborator does not make you a user of your own app, so if you want to use it, sign up like everyone else.

Do I have to build the login page myself?

Only if you want it to look like your app, which you usually do. The platform serves a working sign-in page at /login, styled from your theme file and your logo, so sign-in can never dead-end. Ship your own page at that path and yours takes over automatically, with no flag to flip.

Can people sign in with Google?

Yes, as an addition to email, once you connect it. You add google to the providers list, then finish a one-time setup in the console: a verified custom domain, which is Google's requirement, and your own Google OAuth client, so the consent screen shows your name and logo rather than ours. Someone who signed up by email and later uses Google with the same address stays one account.

How many people can sign up, and can I limit who does?

The free plan includes 100 end-user accounts, Builder 1,000, and the App plan 5,000 per project. If your app is meant for a controlled audience instead, set signup to invite: only existing users and emails you have invited can create an account, and uninvited addresses are refused before any code is sent.

More detail lives in the [auth] reference and the SDK reference.

— free to start, no card

Stop wiring up a login flow.

Connect the AI you already use, say that people should be able to sign up, and the accounts are simply there: codes, passkeys, sessions, and a page to sign in on.