The full-stack app with an admin
Pages for the people who use it, and a generated CRUD surface for the person who has to fix a row at eleven at night.
The admin is derived from the same defineSchema the app already uses, so it cannot drift from the tables. Search fields, filters, bulk actions and read-only models are configuration, not a second application.
It mounts behind your auth. It is a full administrative surface over your database — treat an unprotected basePath as a public database.
What you are carrying
@atlas/serverRoutes and static serving.
@atlas/dbSchemas the admin reads its shape from.
@atlas/authWho gets in, and who gets into `/admin`.
@atlas/adminGenerated list, detail, create, filters, bulk actions.
@atlas/uiReact blocks for the half people see.
Start it
atlas init -n myapp --template admin
What it looks like
import { admin, model } from "@atlas/admin"
import { users, uploads } from "./schema"
const panel = admin({
db,
basePath: "/admin",
auth: { secret: config.secret }, // not optional in production
models: [
model({ schema: users, searchFields: ["email", "name"], filterFields: ["createdAt"] }),
model({ schema: uploads, searchFields: ["filename"], readOnly: true }),
],
})
serve({ port: 3000, routes: [...appRoutes, ...panel.mount([])] })