Admin dashboard

The administrator-only /dashboard. Use the admin role to access the existing dashboard and extend its pages for your product, without building another admin framework.

The Saavo template includes a complete admin console for common operational tasks involving users, payments, roles, entitlements, tickets, notifications, affiliates, analytics, and logs.

When developing your own product, you usually do not need to rebuild the dashboard. Add an administrator email address to configuration, then register and verify an account with that address to access the existing management features at /dashboard. Add new admin pages, routes, and APIs only when the existing dashboard does not meet your business needs.

Available features

After template initialization, the following management features are available out of the box:

ModuleDefault entry pointDescription
Overview/dashboardOperational statistics
Users/dashboard/usersUser management
Subscriptions/dashboard/payments/subscriptionsSubscription snapshots
One-time purchases/dashboard/payments/purchasesOne-time purchase snapshots
Roles/dashboard/rolesView and manually adjust roles
Entitlements/dashboard/entitlement/listView and manually grant entitlements
Quota events/dashboard/entitlement/eventsGrant and consumption auditing
Reaction/dashboard/reaction/events, /dashboard/reaction/commandsBackground events and command execution
OAuth clients/dashboard/oauth-serverAuthorization server clients
Tickets/dashboard/ticketsHandle user tickets
Notifications/dashboard/notificationsPublish in-app notifications to users
Affiliate users/dashboard/affiliates/usersReferred users
Affiliate monthly settlements/dashboard/affiliates/payoutsCommission settlement review
Analytics/dashboard/analytics/*First-party analytics, controlled by analytics.enabled
Logs/dashboard/logs/system, /alert, /auditSystem, alert, and audit logs

All pages are accessed through /dashboard. Related APIs are grouped under /api/dashboard/* and share an administrator guard for permission checks.

Admin dashboard overview

Try the admin dashboard first

Before changing the dashboard, you should explore its existing modules with an administrator account.

  1. Change adminEmails in config/base.ts to an address where you can receive verification emails, or first register locally with the default admin@saavo.dev.
  2. Administrator accounts also require email verification. They do not skip this authentication step before becoming administrators.
  3. Open /dashboard and confirm that modules such as users, payments, and tickets are visible.
  4. Open the same URL with an ordinary account. You should be redirected to the homepage.

The default administrator account creation flow is:

Add the email address to adminEmails
↓
The account signs up and verifies its email address
↓
The system grants the admin role
↓
Access /dashboard

Non-administrators who visit dashboard pages are redirected to the homepage or sign-in page.

Tip

Developers usually do not need to reimplement these admin pages. Confirm that administrator access works, then add the few management features your product needs.

Configure the admin dashboard

The default dashboard supports operations for the template's existing modules. Before launch, at least confirm who the administrators are.

Add administrators

Saavo configures administrators through adminEmails in config/base.ts:

adminEmails: ['admin@your-domain.com'],

Register with that email address and complete email verification to receive the admin role. The address must match exactly. admin+test@example.com is not treated as admin@example.com.

adminEmails does not create a superuser account that bypasses authentication. Administrators start as ordinary users and receive administrator status only when their verified email address matches one in the configuration.

You should create your own administrator account soon after product initialization and confirm that it can access the dashboard.

Hide management modules you do not need

The analytics.enabled setting in config/deploy.ts controls analytics. Disabling first-party analytics removes the analytics entry from the dashboard.

Other management modules currently have no separate dashboard page switches. Even if the product does not use tickets, affiliates, or OAuth clients yet, their pages may remain visible to administrators. To hide these entry points completely, adjust the dashboard navigation configuration.

Design permissions before adding staff roles

The current dashboard recognizes only the admin role. Simply changing roles.ts will not give another role access to /dashboard or automatically restrict which modules it can operate.

If your product does not need different permission levels, continue using admin for the dashboard and the same guard for new admin APIs. If staff do need different access levels, you must treat this as a complete authorization requirement: define capabilities, update server-side guards, restrict APIs, and verify every admin page. Hiding frontend entry points alone is not a secure way to restrict access for different roles.

Extend the admin dashboard

After configuring administrators, add your product's management features to the existing /dashboard. You need to implement access controls for the dashboard, frontend, and APIs according to your business requirements.

Protect admin pages

For standalone server-rendered pages, follow src/pages/dashboard.tsx: run the access check first, then confirm administrator status with the administrator guard.

const guardResult = authenticatedGuard(c);

if (!guardResult.success) {
    return c.redirect(
        getFullPath(guardResult.details?.redirectUrl as string, locale),
    );
}

if (!await authz.isAdmin(c)) {
    return c.redirect(getFullPath('/', locale));
}

For a complete example, see:

Admin pages

Protect admin APIs

Admin APIs use requireDashboardAdmin. Mounting it under /api/dashboard automatically protects all child routes:

dashboardApi.use('*', requireDashboardAdmin);

Do not rely only on checking roles.includes('admin') in React components. The client-side role list controls display only and cannot serve as a security boundary.

Add admin pages

For new management features, follow the existing SPA rendering pattern:

  1. Add a page component in src/components/client/Dashboard/pages/.
  2. Add a route in Dashboard/index.tsx.
  3. Add a navigation item in Dashboard/const.ts.
  4. Put the corresponding API in src/api/dashboard/ so it automatically uses the administrator guard.

To view or adjust existing user, role, entitlement, or payment data, use the existing modules first instead of building another listing page. If you do need a new listing page, you must implement its access controls yourself.

Pre-launch checks

The dashboard is a privileged entry point. Before launch, you should confirm at least the following:

  • adminEmails uses an address you can verify instead of admin@saavo.dev.
  • Administrators can open /dashboard and see the expected modules.
  • Ordinary users visiting /dashboard are redirected to the homepage.
  • Ordinary users calling /api/dashboard/* receive 401 or 403.
  • New admin APIs are mounted under dashboard routes or explicitly use requireDashboardAdmin.
  • If analytics is disabled, its dashboard menu no longer appears.

You should test separately with a new administrator account and an ordinary account. Do not rely only on local users that have existed throughout development.

Frequently asked questions

Next steps

Choose further reading based on what you need to build:

For most products, completing this chapter only requires replacing the administrator email with your own.

Add product-specific management pages using the existing dashboard pattern.