Folder Structure
DBS follows a domain-driven organization within the Next.js App Router conventions. This guide explains the purpose of each directory and how they relate to each other.
prisma/
βββ schema.prisma β Database schema (single source of truth)
βββ seed.ts β Seeds roles, permissions, menus, super admin
src/
βββ app/
β βββ api/ β All REST API route handlers
β βββ dashboard/ β All authenticated dashboard pages (UI)
βββ components/
β βββ common/ β Shared UI: PageHeader, EmptyState, DataLoaderβ¦
β βββ common/form/ β Form field wrappers: FormInput, FormSelectβ¦
β βββ dashboard/ β Dashboard-specific layout components
βββ hooks/ β Custom SWR-based data hooks
βββ lib/ β Core utilities and singletons
βββ services/ β Typed API client functions (client-side)
βββ types/ β Shared TypeScript type definitionsprisma/
| File | Purpose |
|---|---|
schema.prisma | Defines every database model: User, Role, Permission, Menu, Task, AuditLog, Notification, etc. |
seed.ts | Populates the database with default roles, permissions, sidebar menus, and the initial super_admin user. Run with npm run db:seed. |
src/app/api/
Every subdirectory maps to a group of REST endpoints:
| Route | Description |
|---|---|
api/auth/[...all] | Better Auth catch-all handler |
api/access/ | RBAC: manage roles, permissions, and sync them |
api/users/ | List users, assign or sync roles |
api/teams/ | Teams CRUD, members, per-team permissions |
api/notifications/ | Notifications CRUD (create, read, mark as read, delete) |
api/logs/ | Audit log retrieval |
api/settings/ | DB-backed system configuration |
api/menus/ | Dynamic sidebar structure (permission-filtered) |
api/stream/events | SSE endpoint for real-time push |
api/tasks/ | Background task creation and status polling |
api/webhooks/tasks/ | Webhook receiver for completing background tasks |
api/mail/ | Test email sending endpoint |
src/app/dashboard/
All pages that require authentication. Each subdirectory contains a page.tsx and a _components/ folder for page-specific components.
| Route | Description |
|---|---|
dashboard/ | Main dashboard with stat cards and analytics |
dashboard/users/ | User list with role assignment |
dashboard/teams/ | Teams management |
dashboard/access/ | Role & permission management UI |
dashboard/settings/ | User profile, 2FA, Passkeys, active sessions |
dashboard/notifications/ | Notification center |
dashboard/logs/ | Audit log viewer |
dashboard/broadcast/ | Send system-wide broadcast messages |
dashboard/analytics/ | Statistics and charts |
dashboard/lab/ | UI component lab / demo playground |
src/components/
common/
Reusable presentational components used across all pages:
| Component | Purpose |
|---|---|
PageHeader | Consistent page title + description header |
EmptyState | Shown when a data table has no results |
ErrorState | Shown when a data fetch fails |
DataLoader | Wrapper that handles isLoading / error / empty states |
PermissionAlert | Shown when a user lacks permission to view content |
common/form/
shadcn/ui wrappers for React Hook Form that handle register, errors, and label automatically:
| Component | Purpose |
|---|---|
FormInput | Text, email, password inputs |
FormSelect | Dropdown select |
FormDatePicker | Date/time picker |
src/hooks/
All client-side data hooks built on top of SWR:
| Hook | Purpose |
|---|---|
useData | Generic SWR wrapper for any GET request |
useDataTable | Full-featured table hook: sort, filter, pagination, search |
usePagination | Lightweight pagination state management |
useAuditLogs | Fetches and filters audit log entries |
useSession | Current user session and refresh helper |
src/lib/
Core singletons and utilities. Never import these directly from client components unless explicitly noted:
| File | Purpose |
|---|---|
prisma.ts | Prisma client singleton (server-only) |
auth.ts | Better Auth server configuration |
auth-client.ts | Better Auth browser client |
api-guard.ts | API route protection (session + rate limit + permission) |
audit-logger.ts | Write structured entries to the AuditLog table |
config.ts | getSystemConfig() β DB-backed settings with .env fallback |
email.ts | sendVerificationEmail() via Resend |
events.ts | In-process EventEmitter bus (powers SSE) |
rate-limit.ts | In-memory rate limiter |
logger.ts | Winston-style structured logger |
role-hierarchy.ts | canManageRole() β role elevation prevention |
rbac/permission.ts | Permission constant definitions |
rbac/hooks/usePermission.ts | Client-side permission check hook |
rbac/components/RouteGuard.tsx | Server-side page-level route protection |
notification-package/ | NotificationContext, useNotifications, useTasks |
src/services/
Typed API client functions for use in client components. Each file mirrors its corresponding api/ route group:
| File | Exported Object | Methods |
|---|---|---|
users/api.ts | usersApi | getUsers(), assignRole(), syncUserRoles() |
teams/api.ts | teamsApi | getTeams(), createTeam(), addMember(), etc. |
access/api.ts | accessApi | getRoles(), getPermissions(), syncPermissions() |
notifications/api.ts | notificationsApi | getNotifications(), markAsRead(), deleteAll() |
tasks/api.ts | tasksApi | createTask(), getTaskStatus() |
Never call Prisma or server utilities from src/services/. The services layer is exclusively for fetch() calls to your own API routes, keeping the client/server boundary clean.