Nextbase Docs
Nextbase Docs
HomeBlogWelcome to Nextbase v5!Choose your starterGetting startedLocal Supabase per agent
Next.js + ConvexInstallationEnvironment variablesAuthenticationAgent connectionsProject structureDeployment
AuthenticationWorkspaces and the admin area
Building with agentsEmails with Resend
TroubleshootingNextbase v5
The 8 starter kitsNext.js + Convex

Project structure

The Next.js + Convex monorepo layout and where to make changes to routes, data, schema, auth, the admin app, emails, jobs, MCP and tests.

The kit is a pnpm and Turborepo monorepo with four apps and one shared package. convex.json at the root points the Convex CLI at apps/database/convex/, so run all Convex commands from the repository root.

proxy.ts
environment.d.ts
.env.local.example
next.config.ts
netlify.toml
vitest.config.mts
proxy.ts
environment.d.ts
.env.local.example
next.config.ts
vitest.config.mts
schema.ts
auth.ts
auth.config.ts
convex.config.ts
http.ts
crons.ts
seed.ts
workspaces.ts
projects.ts
users.ts
onboarding.ts
admin.ts
impersonation.ts
platform.ts
vitest.config.ts
convex.json
turbo.json
vercel.admin.json
pnpm-workspace.yaml
package.json
setup.sh
AGENTS.md
CHANGELOG.md

The four apps

PackagePathRole
webapps/webNext.js 16 customer application and Fumadocs content. Dev server on port 3000
adminapps/adminNext.js 16 admin application: /app-admin, admin login, admin MCP consent, feedback and roadmap moderation. Dev server on port 3002
databaseapps/databaseConvex backend: schema, functions, MCP servers, tests. Exports database/api and database/data-model
@nextbase/emailapps/email41 React Email templates and the preview server on port 3001

packages/typescript-config holds the shared tsconfig.base.json. The root scripts/ folder has the local bootstrap, verify-local.sh and the gh signoff wrapper. vercel.admin.json at the root is the Vercel configuration for the admin project. docs/separate-admin-app.md describes the admin split and impersonation; docs/mcp-connections.md is the MCP reference. AGENTS.md at the root and in each app is the hand-edited source for all generated AI tool configs (CLAUDE.md, GEMINI.md, .cursor/, .codex/ and so on); run pnpm agents:sync after editing it.

Where to make changes

Routes and pages

Web routes live in apps/web/src/app, grouped by access level:

  • (external-pages)/ public marketing site: landing, blog/, changelog/, docs/, terms/.
  • (dynamic-pages)/(login-pages)/ for /login and /sign-up; (misc-login-pages)/ for password reset and the legacy auth callbacks.
  • (dynamic-pages)/(authenticated-pages)/ for the signed-in app: dashboard/, onboarding/, user/ (settings, connections, notifications, invitations) and (application-pages)/workspace/[workspaceSlug]/ and project/[projectSlug]/. Layouts use @navbar/ and @sidebar/ parallel route slots.
  • (dynamic-pages)/(updates-pages)/ for feedback boards and the roadmap.
  • api/ route handlers: stripe/webhooks, invitations, chat, search, revalidate, health, OG images and v1/.
  • auth/impersonate/ receives impersonation handoffs from the admin app; mcp/authorize/ is the user MCP consent page.

Admin routes live in apps/admin/src/app:

  • app-admin/(admin-pages)/ with users/, workspaces/, marketing/ (blog, changelog, authors, tags), payment-gateway/, settings/, connections/ and the @navbar/ and @sidebar/ slots. The layout calls unauthorized() for anyone without the admin platform role.
  • (dynamic-pages)/(updates-pages)/ for the admin views of feedback and the roadmap.
  • login/, auth/callback/ and mcp/authorize/ for the admin's own sign-in and the Admin MCP consent page.
  • api/admin/marketing/media/ for media uploads.

Cache Components are on in both apps. Code that reads cookies, auth tokens or Convex data at request time must sit inside <Suspense>, and route params arrive as Promise<unknown>; parse them with the schemas in src/utils/zod-schemas/params.ts. The new-page skill in .agents/skills/ has the per-area checklist.

Server and data access

All data access goes through Convex functions. On the server, call fetchQuery or fetchMutation from convex/nextjs with { token: await convexAuthNextjsToken() }. In client components use useQuery, usePaginatedQuery and useMutation from convex/react. Import api from database/api and Id or Doc from database/data-model.

src/data/{user,admin,anon}/ in each app holds "use server" functions and server actions built with next-cool-action clients from that app's src/lib/safe-action.ts. apps/web/src/rsc-data/user/ holds React cache() wrappers for server components. Many files in src/data/ still import the Supabase clients; port them to Convex functions when you touch them and do not add new code on src/supabase-clients/ or apps/web/src/middlewares/.

Admin publication actions call the web app's POST /api/revalidate with the shared REVALIDATE_SECRET so the customer app refreshes its public content caches.

Schema and migrations

Convex has no SQL migrations. Edit apps/database/convex/schema.ts, then pnpm convex:dev or pnpm convex:once pushes it. The push fails if existing documents violate the new schema, so make breaking changes in steps: add fields as v.optional(...), backfill with an internal mutation, then tighten. Run pnpm convex:codegen and commit apps/database/convex/_generated/. When seed data changes, update convex/seed.ts (bump SEED_VERSION) and seed.test.ts. The db-migration skill describes this flow.

apps/database/supabase/ (SQL migrations, pgTAP tests) and apps/database/lib/database.types.ts are legacy. Don't add to them.

Authentication and authorization

Providers and callbacks are in convex/auth.ts; the issuer is convex/auth.config.ts; the redirect allowlist is convex/lib/auth_redirect.ts. Authorization helpers are in convex/lib/authz.ts and must be the first line of every public function. Operator-only functions such as platform:grantAdmin (convex/platform.ts) are internalMutations. The Next.js gates are apps/web/src/proxy.ts and apps/admin/src/proxy.ts. Details are on the authentication page.

Emails

Templates are React components in apps/email/emails/; preview them at http://localhost:3001 with pnpm dev:email. Auth emails are sent by the backend in convex/auth.ts through the Resend API. Application emails from the Next.js server go through apps/web/src/utils/api-routes/utils.ts, which uses Mailpit in development and Resend otherwise.

Background jobs and crons

convex/crons.ts registers the hourly MCP credential prune. Add more jobs there with crons.interval or crons.cron, pointing at internal functions. The schema also has integrationJobs, webhookEvents and idempotencyKeys tables for retryable work. @convex-dev/migrations, @convex-dev/aggregate and @convex-dev/rate-limiter are installed but not registered in convex.config.ts; add app.use(...) before importing them.

MCP

Everything is under apps/database/convex/mcp/, with the consent UI in src/components/mcp-consent.tsx of each app (user consent in web, admin consent in admin). See agent connections.

Tests

KindWhereCommand
Convex functionsapps/database/convex/*.test.ts, Vitest with convex-test on the edge runtimepnpm --filter database test
Web unitscolocated *.test.ts(x) under apps/web/src, Vitest with jsdom and Testing Librarypnpm --filter web test
Admin unitscolocated *.test.ts(x) under apps/admin/srcpnpm --filter admin test
End to endapps/web/e2e/{anon,user,admin,...}/*.spec.ts, Playwright config in apps/web/playwright/pnpm test-integration after a build
Everything before handofflint, typecheck, unit tests, compile-mode buildpnpm verify:local

Code style is Oxlint and Oxfmt (pnpm lint:fix), not ESLint, Prettier or Biome.

Agent connections

The User MCP and Admin MCP of the Next.js + Convex starter: endpoints, tools, OAuth consent and how to add a tool.

Deployment

Publish the Convex backend, configure its variables, and deploy the web and admin Next.js apps for the Next.js + Convex starter.

On this page

The four appsWhere to make changesRoutes and pagesServer and data accessSchema and migrationsAuthentication and authorizationEmailsBackground jobs and cronsMCPTests