NestJS SaaS
starter

Auth, billing, teams, admin, and 14 pages — backend and frontend, wired together. Ship product, not plumbing.

Built by Shantanu Sinha

$199 one-time  ·  Private repo access after purchase  ·  Docs + quickstart

Product demo
billing.service.ts
// billing.service.ts

async handleWebhookEvent(payload: string, headers: WebhookHeaders) {
  // Verify webhook signature
  const event = this.dodo.webhooks.unwrap(payload, { headers });

  // Idempotency — skip duplicate events
  const seen = await this.prisma.webhookEvent.findUnique({
    where: { eventId: headers["webhook-id"] },
  });
  if (seen) return { received: true };

  await this.processEvent(event);
  await this.prisma.webhookEvent.create({ data: { eventId: headers["webhook-id"] } });
}

Numbers below are from the repo as shipped — useful for sanity-checking scope, not hype.

227 Tests Passing
0 TypeScript any Types
10 Integrated Modules
14 App Pages Shipped

See what ships

A real feature traced through every layer — from HTTP request to email notification. This is one flow out of dozens.

1

Verify signature

Payment provider signs every webhook. SDK verifies before any processing.

billing.service.ts
// billing.service.ts — verify the webhook is authentic
try {
  event = this.dodo.webhooks.unwrap(payload, { headers });
} catch (err) {
  const message = err instanceof Error ? err.message : "Unknown error";
  this.logger.error(`Webhook signature verification failed: ${message}`);
  throw new BadRequestException("Invalid webhook signature");
}
2

Idempotency guard

Duplicate webhook? Skip silently — no double charges, no errors.

billing.service.ts
// Duplicate webhook? Skip silently — no double charges
const existing = await this.prisma.webhookEvent.findUnique({
  where: { eventId: webhookId },
});

if (existing) {
  this.logger.log(`Webhook event ${webhookId} already processed, skipping`);
  return { received: true };
}
3

Create purchase record

Persist the payment with a unique payment ID.

billing.service.ts
await this.prisma.purchase.create({
  data: {
    userId,
    paymentId,
    amount,
    currency,
    status: "completed",
  },
});
4

Notify buyer & admin

Fire-and-forget emails — the payment is already safe in the database.

billing.service.ts
// Non-blocking — payment is already recorded
this.emailService
  .sendPurchaseConfirmation(
    user.email, user.name ?? user.email, amountFormatted
  )
  .catch((err: unknown) =>
    this.logger.error("Failed to send purchase confirmation", err)
  );
5

Record webhook event

Mark as processed so duplicates hit the guard in step 2.

billing.service.ts
// Mark processed — future duplicates will hit the idempotency guard
await this.prisma.webhookEvent.create({
  data: {
    eventId: webhookId,
    type: eventType,
  },
});

return { received: true };
6

Test the edge case

The idempotency guard is tested: duplicate webhooks must not create purchases.

billing.service.spec.ts
it("should skip if webhook already processed (idempotency)", async () => {
  prisma.webhookEvent.findUnique.mockResolvedValue({
    id: "wh-1", eventId: "wh_test_123",
    type: "payment.succeeded", processedAt: new Date(),
  });

  const result = await service.handleWebhookEvent("payload", headers);

  expect(result).toEqual({ received: true });
  expect(prisma.purchase.create).not.toHaveBeenCalled();
});

This website runs on the same codebase. You're already using it in production.

What's in the NestJS SaaS Starter

10 backend modules, 14 frontend pages, and production-minded defaults — so you spend time on product, not re-solving auth and billing.

Auth you can ship

JWT + refresh rotation (bcrypt-hashed refresh tokens), Google OAuth, and magic link — wired with Passport.js patterns you can extend.

Billing end-to-end

Checkout, webhooks with signature verification, idempotency via a WebhookEvent table, and purchase tracking — ready to map to your plans.

Dashboard & app shell

React 19 dashboard with onboarding checklist, stat cards, quick actions, sidebar navigation, and team switcher. Dark theme, shadcn/ui components throughout.

Auth, settings & admin UI

Login, register, and OAuth pages. Settings with profile, billing, team, and danger zone tabs. Admin panel with user management. 14 pages ready to white-label.

Teams & invites

Organizations with owner/admin/member roles, email invitations with expiry, and team switching — the usual SaaS multi-tenant baseline.

Admin surface

User management and subscription visibility for operators. Built for a real SaaS, not a toy admin page.

Transactional email

HTML email templates and a queue-backed processor (Resend when configured). Welcome, billing, and team flows have a place to start.

Uploads & CDK-ready storage

Presigned S3 uploads and an AWS CDK stack path for storage + CDN when you want full cloud deployment.

Queues when Redis is on

BullMQ + Redis for async work (e.g. email). Degrades cleanly when Redis is not configured locally.

OpenAPI on every route

Swagger decorators across controllers so you always have a live contract while you build features.

Strict TypeScript monorepo

Shared types in packages, class-validator on DTOs, Zod for env — fewer foot-guns between API and UI.

Docs & deploy guidance

Quickstart, module guides, and a practical deploy path (Railway + optional CDK). Meant to answer “what do I do next?” after clone.

What's in the repo

10 backend modules, 7 frontend page groups, shared types, Prisma schema, and deployment config — all wired together.

nestforge-pro/ 250+ files
apps/api/src/modules/
auth/ 13 files
billing/ 7 files
teams/ 8 files
admin/ 7 files
email/ 16 files
storage/ 4 files
queue/ 4 files
users/ 6 files
apps/web/src/pages/
dashboard/
billing/
teams/
admin/
settings/
auth/
packages/shared/ Shared types
prisma/schema.prisma 6 models
docker-compose.yml Postgres + Redis
infra/ AWS CDK

Simple pricing

One-time purchase. Everything included. No subscription lock-in for the starter itself.

NestForge Pro

Complete starter

$199 one-time

Pay once, own the full codebase. Secure checkout — instant access after payment.

  • Full NestJS 11 + React 19 monorepo source
  • Backend: auth, billing, teams, admin, email, storage, jobs
  • Frontend: dashboard, settings, auth pages, admin panel, billing & team UI
  • Prisma + PostgreSQL, Swagger, Jest + API smoke tests
  • Docs-oriented quickstart and module guides
  • 30-min 1:1 onboarding call with the developer
  • Direct bug support via email
  • Private repo access after purchase
Buy now

All sales are final after source code access is granted. By purchasing, you agree to our Terms and Refund Policy

We offer regional pricing. Your price may adjust based on location.

Honest scope — claims match what ships in the repo.

Frequently asked questions

Purchase, delivery, and what's in the box.

What am I buying?
A one-time license to the NestForge Pro codebase: a fullstack NestJS + React monorepo. The backend has auth, billing, teams, admin, email, storage, and background jobs. The frontend has a React 19 dashboard, settings pages, auth flows, admin panel, and team management UI — all built with shadcn/ui and ready to white-label.
Is this a subscription?
No. NestForge Pro is priced as a one-time purchase ($199). The template includes billing infrastructure for your end customers — that is separate from buying NestForge.
What stack does it use?
Backend: NestJS 11, TypeScript 5, PostgreSQL with Prisma, Dodo Payments, optional Resend and S3, BullMQ with Redis when enabled. Frontend: React 19 with Vite, Tailwind CSS 4, shadcn/ui, TanStack Query, React Router 7. Infrastructure: optional AWS CDK, Docker Compose for local dev. Exact versions are pinned in the repo.
Can I use this for client work or multiple products?
Yes. Each purchase is a single-developer license. You can use NestForge as the foundation for your own products and client projects. One license per developer.
What support is included?
Every purchase includes a 30-minute 1:1 onboarding call and direct bug support via email. You are buying from the developer, not a faceless company. If you get stuck on setup or hit a bug, you get help from the person who built it.