Skip to Content
ServerServer Overview

Server Overview

The Fast Forward Dev server is an Express application built with TypeScript, MongoDB, and Mongoose. It provides a REST API for authentication, user management, billing, and Stripe integration.

Architecture

src/ ├── index.ts # Server entry point ├── routes/ # API endpoint routes ├── models/ # Mongoose database models ├── mailersend/ # Email templates and sending logic ├── utils/ # Helper functions ├── google/ # Google OAuth verification └── types/ # TypeScript type definitions

Tech Stack

Core

  • Express - Web framework
  • TypeScript - Type-safe development
  • Node.js - Runtime environment

Database

  • MongoDB - NoSQL database
  • Mongoose - ODM (Object Document Mapping)

Authentication

  • JWT - JSON Web Tokens for sessions
  • pbkdf2 - Password hashing
  • Google OAuth - Social login

Payments

  • Stripe - Payment processing
  • Webhooks - Real-time payment events

Email

  • Resend - Email delivery service
  • React Email - Email templates

Project Structure

Entry Point (index.ts)

The main server file (src/index.ts) handles:

  • Express Initialization: Sets up the app and middleware (CORS, JSON parsing)
  • Database Connection: Connects to MongoDB via Mongoose
  • Route Registration: Mounts the API routes (/api/user, /api/stripe, etc.)
  • Server Startup: Listens on the configured port (default: 5001)

Routes Directory

API endpoints organized by feature:

routes/ ├── user/ │ ├── user.ts # GET /api/user (get current user) │ ├── user-auth.ts # POST /api/user/auth (login) │ ├── user-signup.ts # POST /api/user/signup (register) │ ├── user-google-auth.ts # POST /api/user/google-auth (OAuth) │ ├── user-list.ts # GET /api/user/list (admin) │ ├── user-detail.ts # GET /api/user/:id (admin) │ ├── user-update.ts # PUT /api/user/:id (admin) │ ├── user-delete.ts # DELETE /api/user/:id (admin) │ ├── user-plan.ts # GET /api/user/plan (get user plan) │ ├── user-invite.ts # POST /api/user/invite (admin) │ └── user-link-provider.ts # POST /api/user/link-provider ├── billing/ │ ├── billing.ts # GET /api/billing (get billing info) │ └── billing-history.ts # GET /api/billing/history ├── stripe/ │ ├── stripe.ts # Stripe checkout session │ └── stripe-webhook.ts # POST /api/stripe/webhook └── github-access.ts # GitHub repository access

Models Directory

Mongoose schemas for MongoDB:

models/ ├── user.model.ts # User profile data ├── identity.model.ts # Authentication identities ├── billing.model.ts # Billing and subscriptions ├── stripe.model.ts # Stripe-specific data └── jwt.model.ts # JWT token management

Utils Directory

Helper functions:

utils/ ├── auth-token.ts # JWT generation and verification └── authenticate-token.ts # Middleware for protected routes

Data Models

Three-Model Architecture

Fast Forward Dev uses a modern three-model architecture:

  1. User - Core user profile
  2. Identity - Authentication providers
  3. Billing - Payment and subscription data

This separation allows:

  • Multiple login methods per user
  • Pre-purchase billing records
  • Clean data organization
  • Easy provider additions

API Design

RESTful Conventions

  • GET - Retrieve data
  • POST - Create new resources
  • PUT - Update existing resources
  • DELETE - Remove resources

Response Format

Success response:

{ "user": { "id": "123", "name": "John Doe", "email": "john@example.com" }, "accessToken": "jwt-token-here" }

Error response:

{ "error": "User not found" }

Status Codes

  • 200 - Success
  • 201 - Created
  • 400 - Bad request (validation error)
  • 401 - Unauthorized (not logged in)
  • 403 - Forbidden (insufficient permissions)
  • 404 - Not found
  • 409 - Conflict (duplicate resource)
  • 500 - Server error

Authentication Flow

Signup Process

  1. User purchases a plan (creates Billing record)
  2. User signs up with email/password
  3. Server creates User and Identity
  4. Server links Billing to User
  5. Server returns JWT token

Login Process

  1. User submits email/password
  2. Server finds Identity by email
  3. Server verifies password hash
  4. Server loads User and Billing
  5. Server generates JWT token
  6. Client stores token in cookie

Protected Routes

Routes use authentication middleware:

import { authenticateToken } from '../utils/authenticate-token' router.get('/api/user', authenticateToken, async (req, res) => { // req.user contains decoded JWT const user = await User.findById(req.user.id) res.json({ user }) })

Environment Variables

Required environment variables (.env):

# Database MONGODB_URI=mongodb+srv://... # JWT JWT_SECRET=your-secret # Stripe STRIPE_SECRET_KEY=sk_test_... STRIPE_WEBHOOK_SECRET=whsec_... # Email RESEND_API_KEY=re_... # Google OAuth GOOGLE_CLIENT_ID=... # Server NODE_ENV=development PORT=5001 CLIENT_URL=http://localhost:3000

Middleware

CORS

Allows cross-origin requests from the client:

app.use(cors({ origin: process.env.CLIENT_URL, credentials: true }))

Body Parser

Parses JSON request bodies:

app.use(express.json())

Authentication

The authenticateToken middleware is used to protect private routes. It:

  1. Extracts the JWT from the Authorization header (Bearer <token>)
  2. Verifies the token signature using the JWT_SECRET
  3. Attaches the decoded user data to req.user
  4. Returns 401 if invalid or missing
router.get('/protected', authenticateToken, (req, res) => { // Access user data console.log(req.user.id) })

Error Handling

All routes follow consistent error handling:

try { // Route logic res.json({ success: true }) } catch (error) { console.error('Error:', error) res.status(500).json({ error: 'Internal server error' }) }

Development vs Production

Development Mode

  • Uses test Stripe keys
  • Connects to dev MongoDB
  • Detailed error logging
  • CORS allows localhost

Production Mode

  • Uses live Stripe keys
  • Connects to production MongoDB
  • Minimal error exposure
  • CORS restricted to production domain

Database Connection

MongoDB connection with Mongoose:

mongoose.connect(process.env.MONGODB_URI) .then(() => console.log('MongoDB connected')) .catch(err => console.error('MongoDB error:', err))

Features:

  • Automatic reconnection
  • Connection pooling
  • Schema validation
  • Indexes for performance

Performance Considerations

Database Indexes

All models have appropriate indexes:

  • User: primaryEmail
  • Identity: provider + providerAccountId, email
  • Billing: userId, stripeCustomerId, email

Query Optimization

  • Use .lean() for read-only queries
  • Select only needed fields
  • Use indexes for filtering
  • Paginate large result sets

Caching

Consider adding caching for:

  • User profile data
  • Billing information
  • Frequently accessed data

Security Best Practices

Password Security

  • Passwords hashed with pbkdf2
  • 100,000 iterations
  • Unique salt per user
  • Never store plain text

JWT Security

  • Tokens expire (configurable)
  • Signed with secret key
  • Verified on every request
  • Stored in HTTP-only cookies (client-side)

Input Validation

  • Validate all user input
  • Sanitize email addresses
  • Check password strength
  • Prevent SQL injection (Mongoose handles this)

Rate Limiting

Consider adding rate limiting:

import rateLimit from 'express-rate-limit' const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per windowMs }) app.use('/api/', limiter)

Next Steps

Last updated on