Skip to Content
LaunchfastDocs

Admin dashboard

Revenue and sign-up analytics, recent payments and user management at /admin.

Make yourself an admin

Sign up in the app first, then run:

npm run make-admin -- you@example.com
you@example.com is now an admin. Open /admin.

This reads DATABASE_URL from .env.local. Production uses the same database when you deployed with setup, so the same command works for your live site. If production has its own database, run it with that URL:

DATABASE_URL="postgresql://…production…" node --env-file-if-exists=.env.local scripts/make-admin.mts you@example.com

What's on it

Pick a period: 7 days, 30 days, 90 days or 12 months. Each number is compared with the period before it.

MetricWhat it counts
Net revenueWhat reached your Dodo balance from payments in the period (the settlement amount, after Dodo's fees and taxes), in your payout currency. Refunded payments don't count
MRRMonthly recurring revenue right now from active subscriptions (yearly plans divided by 12), with the number of subscribers
New customersUsers whose first payment was in the period
Sign-upsNew accounts
ConversionShare of the period's sign-ups who have paid
Revenue by planWhich plans earn the most
Recent paymentsThe latest charges, with user and amount

Below that is a searchable user list with each user's plan, and Ban / Unban buttons. A banned user is signed out and can't sign in again.

Who can see it

Only users with the admin role. Everyone else, signed in or not, gets a 404 Not Found, not a "forbidden" page, so the admin area isn't advertised. Ban and unban go through Better Auth's admin API, which checks the role again.

To remove someone's admin role, run in the Neon SQL editor:

update "user" set role = 'user' where email = 'someone@example.com';

Adding your own admin pages

Put them under src/app/admin/, and call requireAdmin() from src/lib/admin.ts inside a <Suspense> boundary, like requireUser() in Authentication. The admin area always uses the light theme.

On this page