Real platform surfaces. Real Grok Build / *.grok.me platform. This page is an independent map of it — not the official help center. How to read this →
For builders who ship
Wire it — copy-paste recipes
Actual Grok Build wiring paths: auth mount, per-user SQL, UI gates, xAI server calls, env rules. Paste into your own Grok project — same template skills this platform ships.
Yes — this is the needful path. These snippets match the real pre-wired src/lib/auth + getSql() stack. Do not invent Clerk or rewrite server.ts. Verify broker providers in Live Lab if you extend social login.
Mount auth + login page
When you need: Google / X sign-in on a new Grok Build app
Files: src/routes/api/auth/$.ts · src/routes/login.tsx · src/lib/auth/* (pre-wired — do not rewrite server.ts)
Create the catch-all API route so Better Auth handles /api/auth/*
Add a login page that maps GROK_PROVIDERS → signIn()
Never create src/routes/auth/popup.tsx (preview popup is already in the Vite plugin)
Do not invent GitHub/ChatGPT providers — broker only accepts google + twitter
Providers live in src/lib/auth/providers.ts (Google + X only). Email/password: set emailAndPasswordEnabled = true in src/lib/auth/email-password.ts only.
When you need: Todos / saves / rows that belong to a signed-in user
Files: migrations/0002_*.sql · server functions using createServerFn
Add tables with user_id text not null (TEXT ids, not UUID)
Scope every query with authMiddleware → context.userId
Call server fns from client effects/handlers (same-origin)
Preview uses PGLite (ephemeral). Publish injects DATABASE_URL (Neon). Never trust a client-supplied user id.
migrations/0002_todos.sql
create table if not exists todos (
id serial primary key,
user_id text not null,
title text not null,
done boolean not null default false,
created_at timestamptz not null default now()
);
create index if not exists todos_user_id_idx on todos (user_id);
src/lib/todos.ts
import { createServerFn } from "@tanstack/react-start";
import { getSql } from "@/lib/db";
import { authMiddleware } from "@/lib/auth/middleware";
export const listTodos = createServerFn({ method: "GET" })
.middleware([authMiddleware])
.handler(async ({ context }) => {
const sql = await getSql();
return sql<{ id: number; title: string; done: boolean }>`select id, title, done from todos where user_id = ${context.userId} order by id desc`;
});
export const addTodo = createServerFn({ method: "POST" })
.validator((title: string) => title.trim())
.middleware([authMiddleware])
.handler(async ({ context, data: title }) => {
if (!title) return;
const sql = await getSql();
await sql`insert into todos (user_id, title) values (${context.userId}, ${title})`;
});
Gate UI on signed-in user
When you need: Show different chrome for guest vs signed-in
Files: any component
Use useCurrentUserState for guards (wait for isPending)