Skip to content

Latest commit

 

History

History
193 lines (145 loc) · 8.74 KB

File metadata and controls

193 lines (145 loc) · 8.74 KB

TheBlueprintCode logo

TheBlueprintCode: Engine 🚀

A battle-tested, highly configurable multi-tenant backend template built on NestJS and Fastify, utilizing PostgreSQL schemas and Drizzle ORM.

This template is designed to be completely configuration-driven and plug-and-play. Simply clone the repo, fill out your .env secrets, define your JSON policies, and launch a production-ready enterprise SaaS backend instantly.


🎨 Brand Palette

Used across email templates (src/mail/templates/layout.hbs), the favicon (public/favicon.png), and the logo (public/assets/logo.png).

Name Hex Swatch
Darkest #001E5F #001E5F
Dark #002982 #002982
Active #00379E #00379E
Primary #0041BA #0041BA
Secondary #CFD8E8 #CFD8E8
Accent #D38A00 #D38A00

⚡ Performance: Fastify & Drizzle ORM

I chose Fastify over Express and Drizzle ORM over Prisma/TypeORM because when building a scalable multi-tenant SaaS, performance is non-negotiable.

xychart-beta
    title "Requests per Second (Throughput) 🔥"
    x-axis ["Express + TypeORM", "Express + Prisma", "Fastify + Drizzle ORM"]
    y-axis "Req/Sec" 0 --> 70000
    bar [12000, 18000, 65000]
Loading

Fastify handles significantly more requests per second than Express, and Drizzle's zero-overhead SQL generation means no heavy runtime engine dragging down your DB queries.


🏗️ Multi-Tenant Architecture

This engine guarantees absolute data isolation by separating tenant data at the PostgreSQL schema level.

graph TD
    Client[Client App / Frontend] -->|API Request| Gateway[Fastify / NestJS API]
    Gateway --> Context{TenantContextService}
    
    Context -->|Root Request| RootDB[(Root Schema)]
    Context -->|Tenant Request| TenantDB[(Tenant Schema: tenant_xyz)]

    subgraph PostgreSQL Database
        RootDB -.-> |system_settings| Global[Global Configurations]
        RootDB -.-> |accounts| Tenants[Tenant Registry]
        RootDB -.-> |billing| Subscriptions[Global Subscriptions]
        
        TenantDB -.-> |users| TUsers[Tenant Employees]
        TenantDB -.-> |roles| TRoles[Tenant Custom Roles]
        TenantDB -.-> |locations| TLocs[Tenant Locations]
    end
Loading
  • Root Schema (root): Stores platform-level data (Accounts, Root Users, System Settings, Global Subscriptions).
  • Tenant Schemas (tenant_<accountId>): Stores strictly isolated operational data per company.

Tenant context is dynamically propagated through the entire request lifecycle using AsyncLocalStorage via the TenantContextService.


⚙️ Configuration-Driven Setup

Caution

Strict Mode Enforcement I've removed hardcoded fallbacks from the codebase. The engine is strict: if a required environment variable or policy is missing, it fails fast on boot. This guarantees your production environment is exactly what you expect.

1. Environment Secrets (.env)

Copy .env.example to .env and fill in your secrets. Joi actively validates these at boot (src/config/validation.schema.ts) — a missing Required variable fails the app fast at startup instead of surfacing as a runtime bug later.

cp .env.example .env
Variable Required Default Description
NODE_ENV No development development | production | test
PORT Yes Port the Fastify server listens on
API_BASE_URL Yes Public base URL of this API — used to build OAuth callback URLs and asset links (logo, email header) served from /public
FRONTEND_URL Yes Base URL of the frontend app — used in email links (dashboard, password reset)
DATABASE_URL Yes Postgres connection string
MIGRATIONS_AUTO_APPLY No false Run Drizzle migrations automatically on boot
DB_POOL_MAX Yes Max connections for the template (public) schema pool
TENANT_POOL_MAX Yes Max connections per per-tenant schema pool
TENANT_POOL_IDLE_TTL_MS Yes Idle time (ms) before an unused tenant pool is evicted
REDIS_HOST Yes Redis host (queues)
REDIS_PORT Yes Redis port
JWT_ACCESS_SECRET Yes Signing secret for access tokens
JWT_REFRESH_SECRET Yes Signing secret for refresh tokens
JWT_ACCESS_EXPIRES_IN Yes Access token lifetime (e.g. 15m)
JWT_REFRESH_EXPIRES_IN Yes Refresh token lifetime (e.g. 30d)
SMTP_HOST Yes SMTP host for transactional email
SMTP_PORT Yes SMTP port (465 = implicit TLS)
SMTP_USER No (empty) SMTP auth username
SMTP_PASS No (empty) SMTP auth password
MAIL_FROM Yes From address on all outgoing email
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET No Google OAuth SSO
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET No GitHub OAuth SSO
MICROSOFT_CLIENT_ID / MICROSOFT_CLIENT_SECRET No Microsoft (Azure AD) OAuth SSO
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET No Discord OAuth SSO
APPLE_CLIENT_ID / APPLE_TEAM_ID / APPLE_KEY_ID / APPLE_PRIVATE_KEY No Sign in with Apple

SSO variables are optional as a group — only fill in the providers you actually enable; unset ones simply leave that strategy unconfigured.

2. Deep Role-Based Access Control (RBAC)

I use a robust, module-based permission architecture (e.g., view_billing, manage_users) rather than flat generic permissions. You control the entire RBAC system natively via two JSON files at the root:

  • rbac-root.json: Defines roles (e.g., Super Admin) and module-specific permissions for system administrators managing the platform.
  • rbac-tenant.json: Defines the default blueprint of roles (e.g., Admin, Mobile) and module-specific permissions for users operating inside a tenant account.

3. Session & Authentication Policy

At the root of the project, you'll find auth-policy.json. This securely controls our dynamic, sliding-window refresh token architecture.

sequenceDiagram
    participant User
    participant Engine
    participant AuthPolicy
    
    User->>Engine: Refresh Token Request (Device #3)
    Engine->>AuthPolicy: Check Max Sessions (e.g., limit 2)
    AuthPolicy-->>Engine: Limit Exceeded!
    Engine->>Engine: Evict Oldest Active Session (Device #1)
    Engine-->>User: Issue New Access & Refresh Tokens
Loading

You can dynamically configure the maximum number of concurrent device sessions allowed for your users (tenantWeb, tenantMobile, root).


🤝 Contributing & Help Wanted

TheBlueprintCode is built to be a robust, open-source foundation, and I am actively looking for community contributions!

While the core architecture is complete, integrating with paid, enterprise-level third-party services requires specialized accounts that I don't always have access to.

Here are the primary areas where I'd love your help:

1. Enterprise SSO Providers

The authentication system natively supports JWT-based login and free SSO strategies (✅ Google, ✅ GitHub, ✅ Microsoft, ✅ Discord, ✅ Apple). However, I need help implementing Passport.js strategies for:

  • Okta
  • Auth0
  • SAML 2.0
  • Facebook / Meta
  • LinkedIn

2. Billing & Payment Adapters

The engine includes a strict BillingService interface and database tables for subscriptions. I need help building the adapters for:

  • Stripe
  • Zoho Billing
  • Razorpay

3. Cloud Storage Adapters

The engine currently falls back to a functional LocalStorageAdapter. I need help building out cloud integrations like:

  • AWS S3
  • Google Cloud Storage

How to Contribute:

  1. Fork the repository.
  2. Add your integration (e.g., in src/common/billing/ or src/auth/strategies/).
  3. Read secrets strictly using this.configService.getOrThrow().
  4. Open a Pull Request!

💻 Local Development

# Install dependencies
npm install

# Start local infrastructure (Postgres & Redis)
docker-compose up -d

# One-shot bootstrap: creates .env (with generated JWT secrets), runs
# migrations, and interactively seeds a root admin + a first tenant company
npm run setup

# Start the NestJS backend
npm run start:dev

npm run setup is idempotent — re-running it skips .env creation if it already exists, and skips seeding any root user / tenant account that's already there.