Hype StackHypeStack

Admin app

The template ships an admin app at apps/admin, a third surface next to apps/frontend and apps/backend, built for operators (you and your team), not your end users. Out of the box it is a placeholder. A starter pack fills it: the two SaaS starters, WorkOS and Better Auth, ship the full admin below. The free auth starter ships the minimal version: login, admin management, and a dashboard that feature packs fill, without the users and organizations screens.

What's inside

The admin app has its own login and a set of private, role-gated screens:

ScreenRouteWho can open itStarter
Dashboard/Any adminAll
Users/users, /users/$userIdAny adminSaaS starters
Organizations/orgs, /orgs/$organizationIdAny adminSaaS starters
Settings/settingsSuper admin onlyAll
Login/loginPublicAll

An organization's detail page has Overview and Members tabs, plus a Flags tab for its feature flags. Feature packs add tabs next to those.

On the backend, the starter adds /admin API routes (dashboard stats, users, orgs) and /admins/* for super-admin CRUD of admin records. An admin Prisma model stores who has access beyond the bootstrap list.

How super-admin auth works

Admin access uses an AdminRole (super_admin or admin). Resolution order:

  1. SUPER_ADMIN_EMAIL - comma-separated emails. Matching sign-ins are always super_admin, even with no row in the admin table. This is how you get the first operator in.
  2. admin table - super admins add and manage these from the Settings screen. Middleware is withAdmin / withSuperAdmin on top of the same identity provider as the customer app.

Helpers live under apps/backend/src/features/admin/helpers/super-admin.ts and apps/backend/src/utils/auth/admin-hono.ts (getAdminApp()).

Set the bootstrap list in apps/backend/.env:

bash
SUPER_ADMIN_EMAIL=you@example.com,teammate@example.com

How feature packs extend the admin

Feature packs do not ship a second admin app. They plug into this one through pack manifests and codemods:

Extension pointManifest fieldWhat packs do
Nav slot adminnav with slot: "admin"Adds sidebar entries (for example Notifications, Newsletter, AI chat)
Dashboard rowsdashboardRowsInjects metric cards into the dashboard
Org detail rows / cardsorgDetailsRows, orgDetailsCardsComposes billing or usage cards onto an organization's page
Org detail tabsorgDetailsTabsAdds a whole tab next to Overview, Members, and Flags
Extra routes / featuresroutes, filesAdds API routes and admin UI modules under apps/admin and apps/backend

Examples:

  • Billing (any provider) adds a revenue row on the dashboard, org billing and revenue cards, and /admin/billing API routes.
  • Notifications adds a Notifications section with campaigns and an engagement widget.
  • Newsletter adds the email studio, releases, and audience pages.
  • AI Chat adds a usage dashboard and an AI usage tab on every organization.

Install any of these on top of a starter and the widgets and routes show up automatically after the CLI finishes.

Where to add your own admin screens

  1. Add a route under apps/admin/src/routes/(private)/...
  2. Add backend routes under apps/backend/src/routes/admin-... mounted with getAdminApp() (or withSuperAdmin when only super admins should call them)
  3. Gate UI with the same admin role checks the starter already uses
  4. Prefer composing into the dashboard or org detail pages when the feature is a metric or a card, not a whole section

Running it

bash
pnpm dev

Nx starts frontend, backend, and admin with hot reload. Sign in with a SUPER_ADMIN_EMAIL account.

Environment variables

VariablePurpose
SUPER_ADMIN_EMAILComma-separated bootstrap super admin emails. Optional but you need at least one to sign in the first time.