How to Build a SaaS in 2026: The Complete Guide
From idea to first customer: stack, multi-tenancy, payments, security, tests, and deployment for launching a B2B SaaS with Next.js.
Where to start when you want to build a SaaS
Building a SaaS isn't just coding a product. It's assembling about ten pieces that all have to hold together: authentication, data isolated per customer, payments, emails, security, tests, deployment. This guide follows the order in which those decisions actually come up, using the stack behind HeartCo, and links out to the detailed article for each step.
It's aimed at B2B SaaS: organizations with members, roles, and data that must never mix. For a small B2C tool, several of these steps are overkill.
Step 1: validate the need before writing code
Before picking a stack, one question: who's going to pay, and for exactly what problem? A handful of conversations with future users beat a month of development. In each one, note three things: the task that wastes their time today, the tool they currently use, and what they already pay for. If nobody pays for an imperfect solution, the need is probably weaker than you think.
Stick to three features at first. Every feature you add demands the same rigor: data isolation, permissions, tests. Three features done well beat twenty done poorly.
Step 2: pick the stack
Here's HeartCo's actual stack, as it appears in the code:
const stack = {
framework: "Next.js 15 (App Router) + React 19",
api: "tRPC v11",
orm: "Prisma 7",
database: "PostgreSQL (Supabase)",
auth: "NextAuth v5 (Auth.js)",
ui: "Tailwind CSS v4 + shadcn/ui",
payments: "Stripe",
ai: "Mistral AI",
deploy: "Vercel",
monorepo: "pnpm workspaces + Turborepo",
};Why the Next.js App Router?
Server Components change the game. You can run your Prisma queries directly inside your components: no API route needed just for server-side rendering.
// A server component that reads straight from the database
export default async function DashboardPage() {
const session = await auth();
const stats = await db.invoice.aggregate({
_sum: { totalHT: true },
where: { organizationId: session.user.organizationId },
});
return <StatsCard total={stats._sum.totalHT} />;
}Why tRPC?
You define your API once, and TypeScript gives you client-side autocomplete automatically. For a SaaS whose API is only ever consumed by its own frontend, it's the most productive choice. The full picture is in tRPC v11: a fully type-safe API without code generation, and the whole assembly in Next.js 15 + tRPC + Prisma: the winning trio.
// Server side: define the router
export const invoiceRouter = createTRPCRouter({
getAll: staffProcedure.query(async ({ ctx }) => {
return ctx.orgDb.invoice.findMany({
orderBy: { createdAt: "desc" },
});
}),
});
// Client side: automatically typed call
const { data } = api.invoice.getAll.useQuery();
// data is typed: Invoice[]What about the UI?
Tailwind CSS v4 with shadcn/ui components gets you a coherent design system very early, without building one from scratch.
If you'd rather not assemble all of this yourself, a boilerplate saves you weeks of plumbing. How much depends on your own experience, but the comparison is worth doing upfront: Which Next.js SaaS boilerplate should you pick in 2026? compares the options.
Step 3: isolate each customer's data from day one
This is THE critical issue in a B2B SaaS: one organization must never see another's data. Two principles, one for reads and one for writes.
Reads: an automatic filter. A Prisma extension ($extends) adds organizationId to every findMany, findFirst, findFirstOrThrow, count, aggregate, and groupBy call on the models it covers. A developer can no longer forget this filter on a read.
Writes: an explicit rule. create, update, and delete aren't covered by that filter. They carry organizationId in their where, and in their data on creation.
// Read: organizationId is added by ctx.orgDb
const clients = await ctx.orgDb.client.findMany();
// Write: organizationId explicit in the where (IDOR protection)
await ctx.db.client.update({
where: { id: input.id, organizationId: ctx.session.user.organizationId },
data: input.data,
});What the automatic filter doesn't cover
findUnique isn't covered either: its where only accepts unique fields. For
a scoped resource, use findFirst with the identifier instead.
When a resource doesn't belong to the user's organization, respond with NOT_FOUND, not FORBIDDEN: an attacker shouldn't learn that an ID exists at all.
To go deeper on this: Multi-tenant isolation with Prisma and tRPC.
Step 4: authentication and permissions
Authentication isn't just a login form. It's identity, organization membership, and each member's rights. Two simple rules: session and permission are always checked server-side, inside every procedure, never only in the UI; and permissions are described as resource:action, in a single matrix rather than scattered across the code.
The full picture, with roles and organization-level isolation, is covered in Multi-tenant authentication with NextAuth v5. The permissions documentation describes HeartCo's matrix.
Step 5: payments and billing
Use Stripe Checkout rather than a home-built card form, process webhooks idempotently, and verify their signature. When you compare an HMAC signature yourself, use a constant-time comparison (crypto.timingSafeEqual), never ===.
For a French SaaS, VAT and invoicing have their own rules: see Integrating Stripe in a French SaaS: VAT, invoices, webhooks.
Step 6: transactional emails
Confirmations, invoices, reminders: these emails are part of the product. Pick a provider with good deliverability tracking, and set up SPF, DKIM, and DMARC on your domain before launch, not after your first email lands in spam.
Step 7: security, usage limits, and compliance
Any route that costs you money, like sending an email or calling an AI model, needs a per-user limit.
On the personal-data side, the GDPR checklist for a French B2B SaaS lists what to have in place before you accept your first customer. HeartCo's own approach is summarized on the security page.
Step 8: tests and continuous integration
At minimum, write one test proving that a user from organization B gets NOT_FOUND on a resource belonging to organization A, for every critical router. That's the single test that protects you from the worst mistake a B2B SaaS can make. The method is in Testing a multi-tenant SaaS: 7 essential Vitest patterns.
Run lint, type checking, tests, and build on every pull request: CI/CD with GitHub Actions for a Next.js SaaS.
Step 9: deploy
Before launch day, check three things: environment variables are validated at startup, database migrations are versioned, and error and uptime alerts are in place. The full checklist is in our deployment documentation.
Step 10 (optional): add AI
An AI feature is only worth shipping if it solves one specific task. Limit its usage per plan and per user before you open it up.
A four-week timeline
As a rough guide, for a developer starting from a boilerplate:
- Week 1: clone the project, set up auth and the database, deploy to Vercel.
- Week 2: build your SaaS's three key features.
- Week 3: payments, transactional emails, onboarding.
- Week 4: beta testers, feedback, iteration.
This pace assumes the foundations (auth, multi-tenancy, payments) already exist. Built from scratch, they alone take several weeks.
Mistakes to avoid
- Talking about money too late: bring up price from your very first conversations. Fine-tuning it comes later, but you need to know early whether anyone will actually pay.
- Piling on features: three done well beat twenty done poorly.
- Postponing multi-tenancy: bolting it onto an existing product later is one of the most painful migrations there is. Build it in on day 1.
- Rebuilding the foundations: auth, payments, and permissions don't differentiate your product. Your time is better spent elsewhere.
Go further
Related articles
Which Next.js SaaS Boilerplate Should You Pick in 2026? (Full Comparison)
ShipFast, MakerKit, SupaStarter, HeartCo: how to pick a Next.js SaaS boilerplate for your project, stack, and budget.
ReadSteering Claude Code with CLAUDE.md on a Multi-Tenant SaaS
The real rules that govern this SaaS with Claude Code: what goes in CLAUDE.md, what doesn't, and what's actually shipped at purchase.
ReadElectronic Invoicing 2026 for a B2B SaaS in France
Official timeline, PDP and e-reporting vocabulary, generating a Factur-X, and the role of a connector like iopole for a French B2B SaaS.
ReadReady to launch your SaaS?
HeartCo Starter includes everything you need: auth, payments, AI, mobile, audited security. Starting at $219.