Architecture Overview
The Ever Works follows a modern, scalable architecture designed for performance, maintainability, and developer experience.
High-Level Architecture
graph TB
Client[Client Browser] --> CDN[CDN/Edge Network]
CDN --> App[Next.js Application]
App --> Auth[Authentication Layer]
App --> API[API Routes]
API --> DB[(Database)]
API --> Git[Git Repository]
API --> Payment[Payment Providers]
API --> Email[Email Services]
API --> Analytics[Analytics Services]
Core Principles
1. Separation of Concerns
- Presentation Layer: React components and UI logic
- Business Layer: Services and repositories
- Data Layer: Database and external APIs
2. Modular Design
- Feature-based organization
- Reusable components
- Plugin-like integrations
3. Type Safety
- TypeScript throughout
- Strict type checking
- Runtime validation with Zod
4. Performance First
- Server-side rendering
- Static generation where possible
- Optimized caching strategies
Application Layers
Frontend Layer
Technology: React 19 + Next.js 15 Responsibilities:
- User interface rendering
- Client-side state management
- User interactions
- Route handling
Key Components:
- Page components (
app/[locale]/) - Reusable UI components (
components/) - Custom hooks (
hooks/) - Context providers (
components/providers/)
API Layer
Technology: Next.js API Routes Responsibilities:
- Business logic execution
- Data validation
- External service integration
- Authentication handling
Structure:
app/api/
├── auth/ # Authentication endpoints
├── admin/ # Admin-only endpoints
├── items/ # Item management
├── payment/ # Payment processing
└── webhooks/ # External service webhooks
Data Layer
Technologies: Drizzle ORM + PostgreSQL Responsibilities:
- Data persistence
- Query optimization
- Transaction management
- Schema migrations
Components:
- Database schema (
lib/db/schema.ts) - Repositories (
lib/repositories/) - Migration files (
lib/db/migrations/)
Content Layer
Technology: Git-based CMS Responsibilities:
- Content synchronization
- Version control
- Collaborative editing
- Content validation
Structure:
.content/
├── config.yml # Site configuration
├── items/ # Item definitions
├── categories/ # Category definitions
└── tags/ # Tag definitions
Design Patterns
1. Repository Pattern
Abstracts data access logic:
interface ItemRepository {
findById(id: string): Promise<Item | null>;
findBySlug(slug: string): Promise<Item | null>;
findWithFilters(filters: ItemFilters): Promise<Item[]>;
create(item: CreateItemRequest): Promise<Item>;
update(id: string, updates: UpdateItemRequest): Promise<Item>;
delete(id: string): Promise<void>;
}
2. Service Layer Pattern
Encapsulates business logic:
class ItemService {
constructor(
private itemRepository: ItemRepository,
private gitService: GitService,
private notificationService: NotificationService
) {}
async submitItem(data: SubmitItemRequest): Promise<SubmissionResult> {
// Business logic here
}
}
3. Factory Pattern
Creates service instances:
class PaymentProviderFactory {
static create(provider: PaymentProvider): PaymentService {
switch (provider) {
case 'stripe':
return new StripePaymentService();
case 'lemonsqueezy':
return new LemonSqueezyPaymentService();
default:
throw new Error(`Unsupported provider: ${provider}`);
}
}
}
4. Observer Pattern
Event-driven updates:
class ContentSyncService {
private observers: ContentObserver[] = [];
addObserver(observer: ContentObserver): void {
this.observers.push(observer);
}
notifyObservers(event: ContentEvent): void {
this.observers.forEach(observer => observer.update(event));
}
}
Data Flow
1. Request Flow
sequenceDiagram
participant C as Client
participant M as Middleware
participant A as API Route
participant S as Service
participant R as Repository
participant D as Database
C->>M: HTTP Request
M->>M: Authentication Check
M->>A: Authorized Request
A->>S: Business Logic
S->>R: Data Operation
R->>D: SQL Query
D->>R: Result
R->>S: Processed Data
S->>A: Response Data
A->>C: HTTP Response
2. Content Sync Flow
sequenceDiagram
participant G as Git Repository
participant S as Sync Service
participant F as File Service
participant R as Repository
participant D as Database
participant C as Cache
G->>S: Webhook/Schedule
S->>G: Pull Changes
S->>F: Parse Files
F->>R: Validate Data
R->>D: Update Database
R->>C: Invalidate Cache
S->>C: Notify Clients
Security Architecture
1. Authentication Flow
graph LR
User --> Auth[Auth Provider]
Auth --> NextAuth[NextAuth.js]
NextAuth --> JWT[JWT Token]
JWT --> Session[Session Store]
Session --> Middleware[Route Protection]
2. Authorization Layers
- Route-level: Middleware protection
- API-level: Endpoint guards
- Data-level: Row-level security
- UI-level: Component-based access control
3. Security Measures
- Input Validation: Zod schemas
- SQL Injection: Parameterized queries
- XSS Protection: Content sanitization
- CSRF Protection: Token validation
- Rate Limiting: Request throttling
Caching Strategy
1. Application Cache
- React Query: Client-side data cache
- Next.js Cache: Page and API route cache
- Static Generation: Pre-built pages
2. Database Cache
- Connection Pooling: Efficient DB connections
- Query Optimization: Indexed queries
- Read Replicas: Distributed read operations
3. CDN Cache
- Static Assets: Images, CSS, JS
- API Responses: Cacheable endpoints
- Edge Locations: Global distribution
Scalability Considerations
1. Horizontal Scaling
- Stateless Design: No server-side sessions
- Database Scaling: Read replicas and sharding
- CDN Distribution: Global edge caching
2. Performance Optimization
- Code Splitting: Dynamic imports
- Image Optimization: Next.js Image component
- Bundle Optimization: Tree shaking and minification
3. Monitoring & Observability
- Error Tracking: Sentry integration
- Performance Monitoring: Core Web Vitals
- Analytics: PostHog integration
- Logging: Structured logging
Technology Decisions
Why Next.js?
- Full-stack framework: API routes + frontend
- Performance: SSR, SSG, and ISR
- Developer experience: Hot reloading, TypeScript support
- Ecosystem: Rich plugin ecosystem
Why Drizzle ORM?
- Type safety: Full TypeScript support
- Performance: Minimal overhead
- Flexibility: Raw SQL when needed
- Migration system: Version-controlled schema changes
Why Git-based CMS?
- Version control: Full history tracking
- Collaboration: Pull request workflow
- Backup: Distributed by nature
- Flexibility: Any Git provider
Why React Query?
- Caching: Intelligent cache management
- Synchronization: Background updates
- Optimistic updates: Better UX
- Error handling: Retry logic
Extension Points
The architecture provides several extension points:
1. Custom Authentication Providers
// lib/auth/providers/custom-provider.ts
export function CustomProvider(options: CustomProviderOptions) {
return {
id: "custom",
name: "Custom Provider",
type: "oauth",
// Implementation
}
}
2. Payment Provider Integration
// lib/payment/providers/custom-payment.ts
export class CustomPaymentProvider implements PaymentProvider {
async createCheckout(params: CheckoutParams): Promise<CheckoutResult> {
// Implementation
}
}
3. Content Source Integration
// lib/content/sources/custom-source.ts
export class CustomContentSource implements ContentSource {
async sync(): Promise<SyncResult> {
// Implementation
}
}