A production-ready NestJS boilerplate with Sequelize ORM, email service, and complete user authentication system.
Jumpstart your backend development with pre-configured modules for building robust APIs.
Features β’ Quick Start β’ Documentation β’ API Endpoints
- π NestJS Framework - Progressive Node.js framework for efficient server-side applications
- ποΈ Sequelize ORM - Full-featured ORM with PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL support
- π Multiple Authentication Methods
- JWT-based authentication
- Google OAuth 2.0 integration
- OTP (One-Time Password) login - Passwordless authentication via email
- π§ Email Service - Professional SMTP email service with HTML templates
- Login notifications with IP tracking
- OTP delivery with styled templates
- Async email sending
- π€ User Management - Complete user model with UUID primary keys
- β‘ TypeScript - Full TypeScript support for enhanced developer experience
- π§ Database Migrations - Sequelize CLI integration for schema management
- π Validation - Built-in request validation with class-validator
- π Environment Configuration - Dotenv-based configuration management
- π‘οΈ Security - JWT tokens, secure headers, and OTP expiration
Click to expand
- Node.js (v18 or higher)
- npm or yarn
- Database: PostgreSQL, MySQL, MariaDB, SQLite, or MSSQL
- Git
- Clone the repository:
git clone https://github.com/sofiatechnology/nestjs-sequelize-starter.git
cd nestjs-sequelize-starter- Install dependencies:
npm install- Set up environment variables:
cp .env-example .env-
Configure your
.envfile (see Configuration) -
Run database migrations (in development):
npm run start:dev
# Sequelize will auto-sync the schema in development mode- Start the application:
# Development mode with hot reload
npm run start:dev
# Production mode
npm run build
npm run start:prodThe API will be available at http://localhost:3000
Create a .env file in the root directory with the following variables:
# Database Configuration
DB_HOST=localhost
DB_PORT=5432 # 5432 for PostgreSQL, 3306 for MySQL
DB_USERNAME=postgres
DB_PASSWORD=your_password
DB_DATABASE=nestjs_sequelize_starter
# Application Configuration
NODE_ENV=development # development | production | test
PORT=3000
APP_NAME=Your App Name
APP_URL=http://localhost:3000
# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
# Google OAuth 2.0
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/callback
# Email Configuration (SMTP)
SMTP_HOST=smtp.gmail.com # or your SMTP provider
SMTP_PORT=587
SMTP_SECURE=false # true for port 465, false for other ports
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password # Use app-specific password for Gmail
SMTP_FROM=noreply@yourapp.com- Go to Google Cloud Console
- Create a new project or select existing one
- Enable Google+ API
- Go to Credentials β Create Credentials β OAuth 2.0 Client ID
- Add authorized redirect URI:
http://localhost:3000/auth/google/callback - Copy Client ID and Client Secret to your
.envfile
For Gmail, you need to use an App Password:
- Enable 2-Factor Authentication on your Google account
- Go to App Passwords
- Generate a new app password for "Mail"
- Use this password in
SMTP_PASS
This starter supports multiple databases through Sequelize:
- PostgreSQL (recommended)
- MySQL
- MariaDB
- SQLite
- Microsoft SQL Server
In development, Sequelize will automatically sync your models:
// Database auto-syncs on startup in development
await sequelize.sync({ alter: true });For production, create proper migrations:
-- Add OTP columns to users table
ALTER TABLE users
ADD COLUMN otp VARCHAR(255) NULL,
ADD COLUMN otpExpiry TIMESTAMP NULL;Users Table:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
googleId VARCHAR(255) NULL,
otp VARCHAR(255) NULL,
otpExpiry TIMESTAMP NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);This starter provides three authentication methods:
Flow:
- User clicks "Login with Google"
- Redirects to Google consent screen
- Google redirects back with user info
- Server creates/finds user and returns JWT token
Endpoints:
GET /auth/google- Initiates Google OAuth flowGET /auth/google/callback- Google callback handler
Flow:
- User requests OTP with email
- System validates email exists (returns 404 if not)
- 6-digit OTP sent via email (valid for 10 minutes)
- User submits OTP
- System validates and returns JWT token
Endpoints:
POST /auth/otp/send- Request OTPPOST /auth/otp/verify- Verify OTP and login
All authenticated endpoints require JWT token in Authorization header:
Authorization: Bearer <your-jwt-token>
GET /auth/googleDescription: Initiates Google OAuth flow. Redirects to Google consent screen.
GET /auth/google/callbackDescription: Handles Google OAuth callback. Returns JWT token and user info.
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe"
}
}POST /auth/otp/send
Content-Type: application/json
{
"email": "user@example.com"
}Success Response (200):
{
"message": "OTP sent successfully"
}Error Response (404):
{
"statusCode": 404,
"message": "Email not found"
}POST /auth/otp/verify
Content-Type: application/json
{
"email": "user@example.com",
"otp": "123456"
}Success Response (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe"
}
}Error Responses:
404- Email not found401- Invalid OTP401- OTP expired (10 minutes)401- No OTP found (request new one)
GET /auth/profile
Authorization: Bearer <jwt-token>Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"name": "John Doe"
}The starter includes professional HTML email templates:
- Clean, modern design
- Large, easy-to-read OTP code
- 10-minute expiration warning
- Mobile-responsive
- IP address tracking
- Timestamp of login
- Security alert styling
- Links to account security
Email templates are located in src/email/email.service.ts:
private getOTPTemplate(name: string, appName: string, otp: string, appUrl: string): string {
// Customize HTML template here
}nestjs-sequelize-starter/
βββ src/
β βββ auth/ # Authentication module
β β βββ guards/ # Auth guards (JWT, Google)
β β βββ auth.controller.ts # Auth endpoints
β β βββ auth.service.ts # Auth business logic
β β βββ auth.module.ts # Auth module definition
β β βββ jwt.strategy.ts # JWT strategy
β β βββ google.strategy.ts # Google OAuth strategy
β βββ email/ # Email service module
β β βββ email.service.ts # Email sending & templates
β β βββ email.module.ts # Email module definition
β βββ models/ # Database models
β β βββ user.model.ts # User model (Sequelize)
β βββ app.module.ts # Root application module
β βββ main.ts # Application entry point
βββ .env-example # Environment variables template
βββ .gitignore # Git ignore rules
βββ package.json # Dependencies & scripts
βββ tsconfig.json # TypeScript configuration
βββ README.md # This file
# Development mode with hot reload
npm run start:dev
# Production build
npm run build
# Production mode
npm run start:prod
# Run tests
npm run test
# Run e2e tests
npm run test:e2e
# Test coverage
npm run test:cov
# Lint code
npm run lint
# Format code
npm run format- Create a new module:
nest generate module feature-name
nest generate controller feature-name
nest generate service feature-name- Create database model:
// src/models/feature.model.ts
import { Table, Column, Model, DataType } from 'sequelize-typescript';
@Table({ tableName: 'features' })
export class Feature extends Model {
@Column({ type: DataType.UUID, primaryKey: true })
id: string;
// Add your columns here
}- Register model in module:
import { SequelizeModule } from '@nestjs/sequelize';
import { Feature } from '../models/feature.model';
@Module({
imports: [SequelizeModule.forFeature([Feature])],
// ...
})Ensure all production environment variables are set:
- Use strong
JWT_SECRET(minimum 32 characters) - Set
NODE_ENV=production - Use production database credentials
- Configure production
APP_URL
Run migrations before deploying:
-- Production migration script
ALTER TABLE users
ADD COLUMN IF NOT EXISTS otp VARCHAR(255),
ADD COLUMN IF NOT EXISTS otpExpiry TIMESTAMP;Recommended platforms:
- Heroku - Easy deployment with PostgreSQL addon
- Railway - Modern platform with automatic deployments
- DigitalOcean App Platform
- AWS Elastic Beanstalk
- Google Cloud Run
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start:prod"]# 1. Request OTP
curl -X POST http://localhost:3000/auth/otp/send \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'
# 2. Check email for OTP code
# 3. Verify OTP
curl -X POST http://localhost:3000/auth/otp/verify \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "otp": "123456"}'
# 4. Use JWT token
curl http://localhost:3000/auth/profile \
-H "Authorization: Bearer <your-jwt-token>"Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- NestJS - The progressive Node.js framework
- Sequelize - Promise-based ORM for Node.js
- Passport - Authentication middleware
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Built with β€οΈ using NestJS and TypeScript