Understanding NextReady's structure, design patterns, and architectural decisions that make it production-ready.
Example: Database schema → Prisma types → API validation → Client types
Example: API middleware can be composed with auth, rate limiting, and validation
Example: Interactive CLI, automated setup, and development scripts
Example: Connection pooling, rate limiting, and graceful error handling
app/
├── (auth)/ # Auth group routes
│ ├── signin/ # Sign in page
│ └── signup/ # Sign up page
├── (dashboard)/ # Protected dashboard routes
│ ├── dashboard/ # Main dashboard
│ ├── files/ # File management
│ ├── profile/ # User profile
│ └── settings/ # App settings
├── api/ # API routes
│ ├── auth/ # NextAuth endpoints
│ ├── files/ # File management API
│ ├── users/ # User management API
│ └── email/ # Email system API
├── docs/ # Documentation routes
│ ├── getting-started/ # Setup guide
│ ├── architecture/ # This page
│ └── [other-docs]/ # Other doc pages
├── globals.css # Global styles
├── layout.tsx # Root layout
└── page.tsx # Landing page
components/
├── ui/ # shadcn/ui components
├── auth/ # Authentication components
├── file/ # File management components
├── email/ # Email system components
└── layout/ # Layout components
lib/
├── auth.ts # NextAuth configuration
├── db.ts # Database client
├── validations.ts # Zod schemas
├── permissions.ts # RBAC system
├── api-middleware.ts # API middleware
├── file-storage.ts # File storage utilities
└── email.ts # Email system utilities
scripts/
├── setup.js # Interactive setup
├── db-commands.js # Database utilities
└── brand.js # Branding utilities// lib/api-middleware.ts
export const withApiMiddleware = (
handler: ApiHandler,
options: MiddlewareOptions
) => {
return async (request: NextRequest) => {
try {
// Rate limiting
if (options.rateLimit) {
await checkRateLimit(request, options.rateLimit);
}
// Authentication
if (options.requireAuth) {
const session = await getSession(request);
if (!session) return unauthorized();
}
// Authorization
if (options.requiredRole) {
await checkRole(session.user, options.requiredRole);
}
// Permission checks
if (options.requiredPermission) {
await checkPermission(session.user, options.requiredPermission);
}
return await handler(request);
} catch (error) {
return handleApiError(error);
}
};
};
// Usage in API routes
export const GET = withApiMiddleware(getUsersHandler, {
rateLimit: "default",
requiredRole: UserRole.ADMIN,
requiredPermission: Permission.USER_READ,
});Now that you understand the architecture, learn about specific systems and how to use them effectively.