Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Even at one user, you need authentication (so others don't get free credits) and a user model (so you can attribute usage, memory, billing). Don't roll your own auth — use a provider (Clerk, Supabase Auth, Auth0, Magic.link). Get it right early; auth migrations later are painful.
Day-1 auth: email + magic link or Google OAuth. Sessions via JWT cookies. Per-request middleware that injects user_id. Your DB has a users table; every other table foreign-keys to it. Tier in the user row (free / pro / enterprise) so feature gating is one SELECT. Don't store passwords. Don't bake your own JWT signing. Provider has done this for you.
# FastAPI + Clerk (or any provider with a Python SDK)
from fastapi import FastAPI, Depends, HTTPException, Request
from clerk_backend_api import Clerk
app = FastAPI()
clerk = Clerk(bearer_auth=os.environ["CLERK_SECRET"])
async def get_current_user(request: Request) -> dict:
token = request.headers.get("Authorization", "").replace("Bearer ", "")
try:
session = clerk.sessions.verify_session(token=token)
user = clerk.users.get_user(user_id=session.user_id)
return {"id": user.id, "email": user.email_addresses[0].email_address, "tier": user.public_metadata.get("tier", "free")}
except Exception:
raise HTTPException(401)
@app.post("/api/chat")
async def chat(request: Request, user = Depends(get_current_user)):
# tier-gated features
if user["tier"] == "free" and not allow(user["id"], 50, 86400):
raise HTTPException(429, "free tier daily limit")
# ...
# Database
CREATE TABLE users (
id text PRIMARY KEY, -- match provider's user_id
email text UNIQUE NOT NULL,
tier text NOT NULL DEFAULT 'free',
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE traces (
id bigserial PRIMARY KEY,
user_id text NOT NULL REFERENCES users(id),
...
);
CREATE INDEX traces_user ON traces(user_id);
-- enable RLS for defense in depth
ALTER TABLE traces ENABLE ROW LEVEL SECURITY;
CREATE POLICY traces_owner ON traces FOR ALL USING (user_id = current_setting('app.uid'));python3 main.py