Architecture
Overview
NeoSaaS is a multi-tenant SaaS boilerplate built on Next.js 15/16 (App Router). It ships with user management, e-commerce, appointment booking, customer support, Stripe billing, and a complete admin panel — all in one codebase.
Route organization
Four route groups: (auth) for authentication pages, (private) requiring a valid session, (public) for anonymous access, and (errors) for error pages.
Request flow
React component → Server Action or fetch() → auth check → business logic (lib/) → Drizzle ORM → PostgreSQL → JSON response → state update.
No middleware.ts
Next.js 16 replaced middleware.ts with proxy.ts, scoped strictly to network rewrites, redirects, and header changes. Access control lives in server components/functions instead. proxy.ts handles, in order: forced HTTPS, maintenance mode, locale prefixing, and page-level access enforcement (the only check that runs before every /admin and /dashboard request) — checked against a page_permissions table with longest-prefix matching.
Multi-tenancy
A companies table isolates every tenant. Users, orders, payments, and settings are all scoped by companyId — there is no code path that reads across tenants by accident.
Roles and permissions
Two scopes: platform (global admin, companyId = null) and company (tenant admin). Role checks are performed against the database on every sensitive request, not trusted from the JWT alone — a role change takes effect immediately, not after the token expires.
Data model
The schema covers six functional domains beyond core auth/billing: e-commerce (products, orders, carts, coupons), appointment booking (slots, exceptions), customer support (conversations, messages), email (providers, templates, history), integrations & AI (service configs, API keys, LLM usage logs), and compliance (Terms of Service versions, cookie consent records). Migrations are generated by Drizzle Kit into drizzle/.