Overview
The Postiz backend is built with NestJS 10 , following enterprise-grade architectural patterns and best practices. It provides a robust REST API that handles authentication, post management, integrations, and more.
Architecture Principles
Layered Architecture
Critical Rule : When working on the backend, you must always follow the 3-layer pattern:Controller → Service → Repository Never skip layers. In some cases, there’s a 4-layer pattern: Controller → Manager → Service → Repository
┌─────────────────────────────────────────┐
│ Controllers Layer │
│ (apps/backend/src/api/routes) │
│ - HTTP request handling │
│ - Request validation │
│ - Response formatting │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Services Layer │
│ (libraries/nestjs-libraries/services) │
│ - Business logic │
│ - Data transformation │
│ - Orchestration │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Repository Layer │
│ (libraries/nestjs-libraries/database) │
│ - Database access (Prisma) │
│ - Data persistence │
│ - Query optimization │
└─────────────────────────────────────────┘
Code Organization
Important : Most of the server logic lives in libraries/nestjs-libraries/src/services.The backend repository (apps/backend) is mostly used to write controllers and import files from libraries/nestjs-libraries.
Project Structure
apps/backend/
├── src/
│ ├── api/
│ │ ├── routes/ # Controllers
│ │ │ ├── auth.controller.ts
│ │ │ ├── posts.controller.ts
│ │ │ ├── analytics.controller.ts
│ │ │ └── integrations.controller.ts
│ │ └── api.module.ts # API module
│ ├── services/ # Application-specific services
│ │ └── auth/
│ │ ├── auth.service.ts
│ │ └── providers/
│ ├── public-api/ # Public API (no auth)
│ ├── app.module.ts # Root module
│ └── main.ts # Entry point
└── dist/ # Build output
libraries/nestjs-libraries/src/
├── services/ # Shared services (business logic)
├── database/ # Prisma and repositories
├── integrations/ # Social media integrations
├── dtos/ # Data transfer objects
└── ... (other shared modules)
Main Application Module
The root application module configures all global services:
apps/backend/src/app.module.ts
import { Global , Module } from '@nestjs/common' ;
import { DatabaseModule } from '@gitroom/nestjs-libraries/database/prisma/database.module' ;
import { ApiModule } from '@gitroom/backend/api/api.module' ;
import { ThrottlerModule } from '@nestjs/throttler' ;
import { APP_GUARD } from '@nestjs/core' ;
import { PoliciesGuard } from '@gitroom/backend/services/auth/permissions/permissions.guard' ;
@ Global ()
@ Module ({
imports: [
DatabaseModule , // Prisma database
ApiModule , // API routes
ThrottlerModule . forRoot ({ // Rate limiting
throttlers: [{
ttl: 3600000 ,
limit: 30 ,
}],
}),
],
providers: [
{
provide: APP_GUARD ,
useClass: PoliciesGuard , // Global auth guard
},
],
})
export class AppModule {}
Key Features
Authentication & Authorization
JWT-based authentication with cookie storage
CASL for permission management
OAuth 2.0 for social media integrations
Rate limiting via Redis-backed throttler
Request Handling
Swagger/OpenAPI documentation
Class validator for DTO validation
Transformation pipes for data sanitization
Exception filters for error handling
External Services
Temporal integration for background jobs
Redis for caching and sessions
S3 for file storage
Sentry for error monitoring
Development Workflow
Start development server
Runs on http://localhost:3000 (or configured port)
Watch for changes
The dev server uses nodemon for hot-reloading on file changes
Access Swagger docs
API documentation available at http://localhost:3000/api
Environment Variables
Key environment variables for backend:
# Database
DATABASE_URL = "postgresql://user:password@localhost:5432/postiz"
# Redis
REDIS_URL = "redis://localhost:6379"
# JWT
JWT_SECRET = "your-secret-key"
# Frontend URL (for CORS)
FRONTEND_URL = "http://localhost:5173"
# API Rate Limiting
API_LIMIT = 30
# Disable Registration
DISABLE_REGISTRATION = false
# Email
EMAIL_PROVIDER = "resend" # or nodemailer
Global Guards & Middleware
Authentication Guard
The PoliciesGuard is applied globally to protect routes:
@ Global ()
@ Module ({
providers: [
{
provide: APP_GUARD ,
useClass: PoliciesGuard ,
},
],
})
Rate Limiting
ThrottlerModule . forRoot ({
throttlers: [
{
ttl: 3600000 , // 1 hour
limit: 30 , // 30 requests per hour
},
],
storage: new ThrottlerStorageRedisService ( ioRedis ),
})
CORS Configuration
app . enableCors ({
origin: process . env . FRONTEND_URL ,
credentials: true ,
});
API Documentation
Swagger is configured for automatic API documentation:
import { SwaggerModule , DocumentBuilder } from '@nestjs/swagger' ;
const config = new DocumentBuilder ()
. setTitle ( 'Postiz API' )
. setDescription ( 'Social media scheduling API' )
. setVersion ( '1.0' )
. addBearerAuth ()
. build ();
const document = SwaggerModule . createDocument ( app , config );
SwaggerModule . setup ( 'api' , app , document );
Error Handling
Sentry integration for error monitoring:
import { SentryModule } from '@sentry/nestjs/setup' ;
@ Module ({
imports: [
SentryModule . forRoot (),
// ... other modules
],
})
Best Practices
Always follow the layered architecture - Never skip layers
Put business logic in services - Controllers should be thin
Use DTOs for validation - Validate all incoming data
Import from shared libraries - Reuse code from libraries/nestjs-libraries
Use dependency injection - Constructor injection for all dependencies
Handle errors properly - Use NestJS exception filters
Document with Swagger - Use @ApiTags, @ApiOperation decorators
Next Steps
Controller Patterns Learn how to write controllers
Service Layer Understand service patterns
Database Schema Explore the database structure