Skip to main content
Lighthouse 95+
Case Study

SaaS Growth Engine

Northstar — Full-stack B2B SaaS platform for growth operations, team collaboration, and subscription billing

Overview

SaaS Growth Engine (Northstar) is a full-stack B2B SaaS platform for managing growth operations, team collaboration, and subscription billing. Built as a production-ready monorepo with authentication, multi-tenancy, Stripe billing, analytics, and audit logging.

Architecture


┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Frontend      │────▶│    Backend      │────▶│    MongoDB      │
│   (Angular)     │     │   (NestJS)      │     │   (Atlas)       │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                               │
                               ▼
                        ┌─────────────────┐
                        │    Stripe       │
                        │  (Billing)      │
                        └─────────────────┘
                               │
                               ▼
                        ┌─────────────────┐
                        │    Resend       │
                        │   (Email)       │
                        └─────────────────┘

Key Design Decisions

  • Monorepo for shared types, simplified CI, atomic commits
  • MongoDB for flexible tenant-scoped documents; indexes created automatically in dev
  • Hash-based routing on frontend for static hosting compatibility
  • Server-side authority — all billing, auth, and RBAC enforced on backend

Features Implemented

Authentication & Identity

  • Email/password signup with organization creation
  • Email verification via one-time tokens
  • Password reset flow
  • JWT access tokens (15 min) + rotated opaque refresh cookies (7 days)
  • Invitation acceptance (existing or new users)

Multi-Tenancy & RBAC

  • Organizations with unique slugs
  • Roles: Admin, Manager, Viewer
  • Membership resolution on every protected request
  • Minimum-one-admin protection on role changes/removals
  • Organization-scoped data access

Team Management

  • Invite members with role selection
  • Role changes (Admin only)
  • Member removal (Admin only, self-protection)
  • Pending invitations with revocation
  • Paginated member listing

Billing & Subscriptions (Stripe)

  • 3 Plans: Starter, Growth, Scale — prices fetched live from Stripe
  • Server-created Checkout Sessions (subscription mode)
  • Customer Portal for self-service management
  • Webhook handling with signature verification
  • Idempotent event processing (duplicate-safe)
  • Subscription state sync: created/updated/deleted, invoice paid/failed
  • Plan availability gated by configured Stripe Price IDs

Analytics Dashboard

  • MRR (Monthly Recurring Revenue) with currency support
  • Churn rate calculation
  • Active subscription count
  • New member growth (30-day rolling)
  • Monthly growth bar chart
  • Date-range filtering (max 366 days)

Audit Logging

  • Immutable event log per organization
  • Redacted metadata (passwords, tokens, emails masked)
  • Admin-only access
  • Paginated, newest-first

Workspace Settings

  • Organization name update (Admin only)
  • Workspace ID display
  • Sign out

UI/UX

  • Responsive layout (desktop sidebar → mobile bottom nav)
  • Light/Dark theme (CSS variables, persisted)
  • Loading, empty, and error states
  • Accessible markup (ARIA, semantic HTML)

Project Structure

                
saas-growth-engine/
├── backend/
│   ├── src/
│   │   ├── main.ts                 # App bootstrap, raw body for webhooks
│   │   ├── app.module.ts           # Module imports, global config
│   │   ├── config/environment.ts   # Zod-validated env schema
│   │   ├── modules/
│   │   │   ├── database/           # Mongoose models, connection, retry
│   │   │   ├── auth/               # Signup, login, tokens, guards
│   │   │   ├── users/              # Member CRUD, invitations
│   │   │   ├── organizations/      # Org settings, current org
│   │   │   ├── billing/            # Stripe integration, webhooks
│   │   │   ├── analytics/          # Aggregation pipelines
│   │   │   ├── audit/              # Audit log recording
│   │   │   └── email/              # Resend service
│   │   └── ...
│   └── package.json
├── frontend/
│   ├── src/app/
│   │   ├── app.ts                  # Main component, state, API calls
│   │   ├── app.html                # Template (all sections)
│   │   ├── app.scss                # Styles (CSS variables, responsive)
│   │   ├── core/
│   │   │   ├── api.service.ts      # HTTP client, token refresh
│   │   │   └── auth.interceptor.ts # Auto-attach auth, 401 retry
│   │   └── app.routes.ts           # Hash routes for billing pages
│   └── package.json
├── vercel.json                     # Frontend deploy config
├── render.yaml                     # Backend deploy config
├── .env.example                    # Environment template
└── pnpm-workspace.yaml
              

Challenges & Solutions

Hash routing + static hosting

Avoids server config complexity for SPAs by using hash-based routing.

Idempotent webhooks

Critical for Stripe; use unique event IDs + status locking to prevent duplicate processing.

Retry with backoff

MongoDB Atlas cold starts need connection retries with exponential backoff.

Server-side price fetching

Keeps frontend in sync with Stripe Dashboard by fetching prices at runtime.

Environment validation at startup

Fails fast with clear messages using Zod-validated environment schema.

Future Enhancements

  • Team workspaces (multiple orgs per user)
  • Usage-based billing / metered prices
  • Email templates with React Email
  • Webhook retry dashboard
  • API keys for programmatic access
  • Slack/Discord notifications
  • Export analytics to CSV

Deployment

Frontend

Vercel

Backend

Render

Database

MongoDB Atlas

CI/CD

GitHub Actions

Tech Stack

NestJSAngularMongoDBStripeTypeScriptpnpm