Skip to content

cuisonenrico/be-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Backend Template

A production-ready NestJS backend template with modular architecture - use only the services you need. Designed for startups and side projects that need to scale.

πŸ“¦ Using this template? Run npm run setup after cloning to rename the project to your app name.

⚑ Choose Your Stack

This template supports multiple configurations - from a minimal API with no external dependencies to a full-featured backend with all services:

Stack Services Setup Time Best For
Minimal Just NestJS + Admin 2 min Simple APIs, microservices
Standard ⭐ + Database + Auth 15 min Most web apps
Full + Storage + Redis + OAuth 30 min Production apps

See STACK_PROFILES.md for detailed comparison and setup guides.


Stack (All Services Optional)

Service Provider Free Tier Auto-Enabled When
Backend NestJS + Fastify - Always
Database Supabase Postgres 500MB, 2 projects SUPABASE_URL set
Auth Firebase Auth 50K MAU FIREBASE_PROJECT_ID set
OAuth Self-hosted JWT - OAUTH_JWT_SECRET set
Storage Cloudflare R2 10GB, 1M requests R2_ACCOUNT_ID set
Cache/Queue Upstash Redis 10K commands/day REDIS_URL set
Deployment Cloud Run / Fly.io Generous free tier -

Features

  • βœ… Modular by Design: Load only the services you need via environment variables
  • βœ… Fast & Lightweight: Fastify adapter (2x faster than Express)
  • βœ… Type-Safe: Full TypeScript with strict mode
  • βœ… Three Auth Systems: Firebase, OAuth, or Admin (mix and match)
  • βœ… Database: Supabase Postgres with connection pooling (port 6543)
  • βœ… Object Storage: Cloudflare R2 with pre-signed URLs (never stream through server)
  • βœ… Caching: Redis-based caching layer with TTL support
  • βœ… Rate Limiting: Built-in throttling (in-memory or Redis-backed)
  • βœ… Background Jobs: BullMQ queues for async processing
  • βœ… API Documentation: Swagger UI at /api/docs
  • βœ… Resource Generator: Scaffold CRUD APIs with one command
  • βœ… Production Ready: Docker + Cloud Run / Fly.io deployment

Quick Start

Choose Your Path:

πŸš€ Option 1: Minimal (No Setup)

git clone <repo>
cd be-template
npm install
cp .env.minimal .env
npm run start:dev

βœ… Running in 2 minutes - No external services required!

🎯 Option 2: Standard (Recommended)

git clone <repo>
cd be-template
npm install
cp .env.standard .env
# Configure Supabase + Firebase (see STACK_PROFILES.md)
npm run start:dev

βœ… Running in 15 minutes - Database + Authentication

πŸ’Ž Option 3: Full Stack

git clone <repo>
cd be-template
npm install
cp .env.full .env
# Configure all services (see STACK_PROFILES.md)
npm run start:dev

βœ… Running in 30 minutes - All features enabled

For detailed setup instructions, see STACK_PROFILES.md


Prerequisites

Rename Project (Template Users)

If you cloned from the template, rename all references to your project name:

npm run setup
# Follow the prompts to enter your project name

This will:

  • Update package.json name and description
  • Update all config files (fly.toml, Dockerfile, etc.)
  • Update documentation references
  • Clean up the setup files

Service Setup Guides

Note: The guides below are for the Full Stack configuration. For Minimal or Standard stacks, you only need to configure the services you're using. See STACK_PROFILES.md for stack-specific setup.

πŸ”₯ Step 1: Firebase Authentication (Optional)

Firebase handles user authentication. Your frontend will use Firebase SDK for login/register, and this backend verifies the JWT tokens.

Required for: Standard Stack, Full Stack
Skip if: Using OAuth-only authentication or no authentication

Create Firebase Project

  1. Go to Firebase Console
  2. Click "Create a project" (or select existing)
  3. Enter project name (e.g., my-app-prod)
  4. Disable Google Analytics (optional for dev)
  5. Click Create project

Enable Authentication

  1. In Firebase Console, go to Build β†’ Authentication
  2. Click "Get started"
  3. Go to Sign-in method tab
  4. Enable your preferred providers:
    • Email/Password - Click, toggle Enable, Save
    • Google - Click, toggle Enable, add support email, Save
    • (Optional) Add other providers as needed

Get Service Account Credentials

  1. Click the βš™οΈ gear icon β†’ Project settings
  2. Go to Service accounts tab
  3. Click "Generate new private key"
  4. Save the downloaded JSON file securely (NEVER commit this file)
  5. Open the JSON and copy these values to your .env:
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQ...(full key)...\n-----END PRIVATE KEY-----\n"

⚠️ Important: The private key must include the \n characters and be wrapped in quotes.

Frontend Integration

Your frontend app uses Firebase SDK to authenticate users:

// Frontend: Login and get token
import { signInWithEmailAndPassword, getIdToken } from 'firebase/auth';

const userCredential = await signInWithEmailAndPassword(auth, email, password);
const token = await getIdToken(userCredential.user);

// Use token in API calls
fetch('https://your-api.com/auth/me', {
  headers: { 'Authorization': `Bearer ${token}` }
});

πŸ—„οΈ Step 2: Supabase Database (Optional)

Supabase provides a managed PostgreSQL database with automatic APIs and Row Level Security.

Required for: Standard Stack, Full Stack
Skip if: Not using a database (e.g., proxy API, static content server)

Create Supabase Project

  1. Go to Supabase Dashboard
  2. Click "New project"
  3. Select your organization (or create one)
  4. Enter:
    • Name: my-app-db
    • Database Password: Generate a strong password (save this!)
    • Region: Choose closest to your users
  5. Click "Create new project" (takes ~2 minutes)

Get Connection Details

  1. Go to Project Settings (gear icon) β†’ Database
  2. Scroll to Connection string section
  3. Select URI tab
  4. Copy the connection string

⚠️ Critical: Change the port from 5432 to 6543 for pooled connections (required for serverless)

DATABASE_URL=postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres

Get API Keys

  1. Go to Project Settings β†’ API
  2. Copy these values to your .env:
SUPABASE_URL=https://[project-ref].supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

⚠️ Security: The service role key bypasses RLS. Never expose it to the frontend.


πŸ“¦ Step 3: Cloudflare R2 Storage (Required)

R2 provides S3-compatible object storage with no egress fees. Files are uploaded directly from the client using pre-signed URLs.

Enable R2

  1. Go to Cloudflare Dashboard
  2. Select your account (or create one)
  3. In the sidebar, click R2 Object Storage
  4. Click "Create bucket"
  5. Enter bucket name (e.g., my-app-storage)
  6. Click Create bucket

Create API Token

  1. In R2, click "Manage R2 API Tokens" (top right)
  2. Click "Create API token"
  3. Configure:
    • Token name: backend-api
    • Permissions: Object Read & Write
    • Specify bucket(s): Select your bucket
  4. Click Create API Token
  5. Copy the credentials immediately (shown only once!)
R2_ACCOUNT_ID=your-cloudflare-account-id
R2_ACCESS_KEY_ID=your-access-key-id
R2_SECRET_ACCESS_KEY=your-secret-access-key
R2_BUCKET_NAME=my-app-storage

Get Account ID

  1. Your Account ID is in the Cloudflare dashboard URL: dash.cloudflare.com/[ACCOUNT_ID]/...
  2. Or find it in R2 β†’ Overview β†’ right sidebar

(Optional) Set Up Public Access

If you need public URLs for files:

  1. Go to your bucket β†’ Settings
  2. Under Public access, click "Allow Access"
  3. Add a custom domain or use the R2.dev subdomain
  4. Add to .env:
R2_PUBLIC_URL=https://pub-xxxx.r2.dev

⚑ Step 4: Upstash Redis (Required)

Upstash provides serverless Redis for caching, rate limiting, and background job queues.

Create Redis Database

  1. Go to Upstash Console
  2. Click "Create Database"
  3. Configure:
    • Name: my-app-cache
    • Type: Regional
    • Region: Choose closest to your deployment
  4. Click Create

Get Connection URL

  1. In your database, go to Details tab
  2. Find REST URL or Redis URL
  3. Copy the Redis URL (starts with redis:// or rediss://)
REDIS_URL=rediss://default:xxxxxxxxxxxx@usw1-xxxx.upstash.io:6379

πŸ’‘ Tip: Upstash also shows a REDIS_TOKEN for REST API access. You can ignore this for now.


5. Configure Remaining Settings

Add these final settings to your .env:

# Server
PORT=3000
HOST=0.0.0.0
NODE_ENV=development

# Rate Limiting
THROTTLE_TTL=60
THROTTLE_LIMIT=100

# CORS (update for production)
CORS_ORIGIN=*

Verify Setup

Start the Server

npm run start:dev

You should see:

Application is running on: http://0.0.0.0:3000
Swagger UI available at: http://0.0.0.0:3000/api/docs

Test Endpoints

# Health check
curl http://localhost:3000/health

# Swagger UI
open http://localhost:3000/api/docs

Common Startup Errors

Error Solution
Firebase credentials not configured Check FIREBASE_* env vars are set correctly
R2 configuration is incomplete Check all R2_* env vars
ECONNREFUSED (Redis) Verify REDIS_URL is correct
Connection refused (Database) Check DATABASE_URL, ensure port is 6543

Development Workflow

Available Commands

npm run start:dev      # Start with hot reload
npm run build          # Production build
npm run lint           # Fix linting issues
npm run format         # Format with Prettier
npm run generate       # Generate CRUD resource

Generate a REST API Resource

Quickly scaffold a complete CRUD API for a database table:

npm run generate Product name:string price:number description:string? inStock:boolean

This creates:

  • src/modules/product/ - Module, Controller, Service
  • src/modules/product/dto/ - Create & Update DTOs with validation
  • src/modules/product/entities/ - TypeScript interface
  • migrations/ - SQL migration with RLS policies

Then:

  1. Add ProductModule to app.module.ts imports
  2. Run the SQL migration in Supabase SQL Editor

Authentication Pattern

This backend only verifies Firebase tokens. Users authenticate on the frontend:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Frontend  │────▢│   Firebase  │────▢│   Backend   β”‚
β”‚   (React)   β”‚     β”‚    Auth     β”‚     β”‚   (NestJS)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚                    β”‚                    β”‚
      β”‚ 1. Login/Register  β”‚                    β”‚
      │───────────────────▢│                    β”‚
      β”‚                    β”‚                    β”‚
      β”‚ 2. Get JWT Token   β”‚                    β”‚
      │◀───────────────────│                    β”‚
      β”‚                    β”‚                    β”‚
      β”‚ 3. API Request with Bearer Token        β”‚
      │────────────────────────────────────────▢│
      β”‚                    β”‚                    β”‚
      β”‚                    β”‚ 4. Verify JWT      β”‚
      β”‚                    │◀───────────────────│
      β”‚                    β”‚                    β”‚
      β”‚ 5. Response                             β”‚
      │◀────────────────────────────────────────│

Protected Routes

Use the FirebaseAuthGuard on any route requiring authentication:

import { UseGuards } from '@nestjs/common';
import { FirebaseAuthGuard } from './common/guards/firebase-auth.guard';
import { CurrentUser } from './common/decorators/current-user.decorator';

@UseGuards(FirebaseAuthGuard)
@Get('profile')
getProfile(@CurrentUser() user: any) {
  return {
    uid: user.uid,
    email: user.email,
  };
}

API Documentation

Swagger UI

Interactive API documentation at http://localhost:3000/api/docs:

  • Browse all endpoints with request/response schemas
  • Test endpoints directly in the browser
  • Click "Authorize" and paste your Firebase JWT to test protected routes
  • View DTO validation requirements

Core Endpoints

Method Endpoint Auth Description
GET /health No Health check
POST /auth/verify No Verify a Firebase token
GET /auth/me Yes Get current user profile
PUT /auth/me Yes Update current user
DELETE /auth/me Yes Delete current user account

Deployment

See DEPLOYMENT.md for detailed instructions.

Quick Deploy to Cloud Run

# 1. Install gcloud CLI
# 2. Authenticate
gcloud auth login
gcloud config set project YOUR_PROJECT_ID

# 3. Deploy
./deploy-cloud-run.sh

# 4. Set environment variables in Cloud Run Console

Quick Deploy to Fly.io

# 1. Install flyctl
# 2. Authenticate
flyctl auth login

# 3. Launch and deploy
flyctl launch --no-deploy
flyctl secrets set DATABASE_URL="..." FIREBASE_PROJECT_ID="..." # all env vars
flyctl deploy

Project Structure

src/
β”œβ”€β”€ main.ts                 # Application entry + Swagger setup
β”œβ”€β”€ app.module.ts           # Root module
β”œβ”€β”€ app.controller.ts       # Health check endpoint
β”œβ”€β”€ common/
β”‚   β”œβ”€β”€ guards/             # FirebaseAuthGuard
β”‚   └── decorators/         # @CurrentUser() decorator
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ configuration.ts    # Environment config
β”‚   └── database.module.ts  # Supabase client setup
β”œβ”€β”€ modules/
β”‚   β”œβ”€β”€ auth/               # Firebase auth verification
β”‚   β”œβ”€β”€ storage/            # R2 storage with pre-signed URLs
β”‚   β”œβ”€β”€ cache/              # Redis caching service
β”‚   └── queue/              # BullMQ job processing
└── example.*               # Example implementations (optional)

Environment Variables Reference

Variable Required Description
PORT No Server port (default: 3000)
HOST No Server host (default: 0.0.0.0)
NODE_ENV No Environment (development/production)
DATABASE_URL Yes Supabase Postgres URL (use port 6543)
SUPABASE_URL Yes Supabase project URL
SUPABASE_ANON_KEY Yes Supabase anonymous key
SUPABASE_SERVICE_ROLE_KEY Yes Supabase service role key
FIREBASE_PROJECT_ID Yes Firebase project ID
FIREBASE_CLIENT_EMAIL Yes Firebase service account email
FIREBASE_PRIVATE_KEY Yes Firebase private key (with \n)
R2_ACCOUNT_ID Yes Cloudflare account ID
R2_ACCESS_KEY_ID Yes R2 access key
R2_SECRET_ACCESS_KEY Yes R2 secret key
R2_BUCKET_NAME Yes R2 bucket name
R2_PUBLIC_URL No Public URL for R2 bucket
REDIS_URL Yes Upstash Redis URL
THROTTLE_TTL No Rate limit window in seconds (default: 60)
THROTTLE_LIMIT No Max requests per window (default: 10)
CORS_ORIGIN No Allowed origins (default: *)

πŸ“š Documentation


Troubleshooting

Firebase Private Key Issues

If you see error:1E08010C:DECODER routines::unsupported:

  1. Ensure the key is wrapped in double quotes in .env
  2. The key should contain literal \n characters, not actual newlines
  3. Copy directly from the JSON file, including -----BEGIN PRIVATE KEY-----

Database Connection Issues

  • Always use port 6543 (pooler) not 5432 (direct)
  • Check if your IP is allowed in Supabase β†’ Database β†’ Network

Redis Connection Issues

  • Use rediss:// (with double s) for TLS connections
  • Upstash URLs should work as-is

License

ISC

About

Backend Template

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published