Steering 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.
The problem: plausible code, not compliant code
Without instructions, an AI assistant writes code that compiles and looks correct. On a multi-tenant SaaS, "looks correct" isn't enough: a findUnique({ where: { id } }) on an organization-scoped resource compiles perfectly fine and leaks one customer's data to another. The model has no way to guess on its own that this specific project requires findFirst({ where: { id, organizationId } }).
CLAUDE.md and the files under .claude/ exist to close that gap. Not a magic prompt you paste once, but a set of rules versioned in the repository, read at the start of every session, that make explicit what a senior developer on the project already knows without thinking about it.
A second example, less obvious than the IDOR one, also pulled from this repository: NextAuth v5 renamed its session cookies from __Secure-next-auth.* to __Secure-authjs.*. A getToken({ req }) call without an explicit cookieName and secret compiles, throws no error, and silently returns null in production, a user who looks logged out with no exception surfacing anywhere. Nothing in the function's signature hints at the trap. The only way to stop rediscovering it every new work session is to write it down once, in a rule.
CLAUDE.md: what goes in, what doesn't
This repository's CLAUDE.md opens with the project structure (the product's two layers, so an AI never mixes the sales-site code with the shipped SaaS code), then commands (pnpm dev, pnpm typecheck...), architecture (the ~/ alias, where the generated Prisma client lives), and an explicit list of prohibitions: don't touch this certified module, don't use npm, don't add any without justification.
What goes in: verifiable facts about this project that a model can't guess from the code alone. The findFirst over findUnique choice is one of them: both compile, only a human who knows the project's history knows which one is correct here.
What doesn't go in: generic stack documentation (Next.js, Prisma, that's findable elsewhere). A finer line: some instructions only make sense for our organization, not for the code itself. This repository runs with several Claude Code sessions in parallel on the same working tree, so CLAUDE.md carries a precise startup protocol (how to triage another session's uncommitted files, never run git add -A, check git reflog before touching a file modified less than five minutes ago). Useful here, moot for a buyer working solo on their own repo. That process content stays in this repository's CLAUDE.md, but doesn't ship with the product: a buyer inherits the code, not our internal workflow. The file itself isn't exported either (more on that below).
Rules by domain
Beyond the root file, .claude/rules/ holds one rule per domain: security, Prisma, testing, git, design, frontend. Split apart rather than crammed into one file, so the security rule stays short and you can find it without scrolling.
A concrete example, drawn from this repository's security.md:
## Multi-tenant isolation
- Every `db.model.update()` and `db.model.delete()` MUST have
`organizationId` in the `where`
- Required pattern: `findFirst({ where: { id, organizationId } })`,
never `findUnique({ where: { id } })`
- IDOR → NOT_FOUND (not FORBIDDEN), so as not to confirm that a
resource exists in another organizationThese aren't general principles, they're decisions already made for this project, with the reasoning written right next to them. A model that reads this rule before writing an update knows exactly which where to produce, without anyone having to ask again in every session.
prisma.md does the same for migrations (never hand-edit prisma/migrations/, always add organizationId on a new multi-tenant model), testing.md for tests (mock Prisma, never a real database in unit tests), git.md for commits (format, language, what never gets committed).
The format that makes a rule useful
A generic rule like "write secure code" changes nothing: a model has no way to translate it into a concrete decision on this project. What actually works has three properties, all visible in the security.md example above:
- Short and testable: "
findFirstwithorganizationId, neverfindUnique" can be verified in a single read of the code, unlike "be careful about data isolation" - The reason next to the instruction: "so as not to confirm that a resource exists in another organization" explains the why, so the rule still applies to a case it doesn't cover word for word
- A code example, not an abstract sentence: showing the correct
whereinstead of describing what it should contain removes any ambiguity in interpretation
A rule that fails any one of these three gets worked around or forgotten. It's the same bar as a good human team norm: if nobody can say in one sentence why it exists, it ends up ignored.
Skills: a workflow, not a prompt
A rule says what not to do. A skill does the task, in order, with the checks built in. feature-factory, one of this repository's skills, shows the difference: asked for a new business module, it starts with an interview (name, fields, roles, an optional freemium quota), presents a full scaffolding plan before writing a single line of code, then generates layer by layer: Prisma model, entry in ORG_SCOPED_MODELS, RBAC permissions, tRPC router, dashboard page, tests.
A prompt pasted once does none of that: it hands over an intent, not a sequence of operations with checks between each step. The skill encodes the procedure itself, so it produces the same result whether you trigger it today or in six months, with a different model.
This repository has nine of them. feature-factory scaffolds a feature end to end. tenant-security-audit audits multi-tenant isolation with automatic fixes, rather than just listing problems. prisma-migration secures the migration workflow (the exact order of prisma generate then prisma migrate dev, handling the Windows query-engine file lock). safe-refactor handles a rename that crosses several layers: a field renamed in the schema also has to change in the router, the permissions, and the tests, with none of the four layers left behind. pre-deploy-checklist runs before a merge to main. heartco-debugger diagnoses a tRPC error, a broken Prisma scope, or an unexpected 401/403. prisma-performance catches N+1 queries and unpaginated queries. docs-generator writes end-user documentation pages. The ninth, internal to reselling the boilerplate itself, isn't relevant to a buyer.
A real session: adding a module
Concretely, asking to "add a vehicle-tracking module" triggers feature-factory, which answers with a plan before touching any code:
Feature: vehicles (Vehicle tracking)
Files to create/modify:
1. prisma/schema.prisma → Vehicle model
2. lib/prisma-org-scope.ts → Add to ORG_SCOPED_MODELS
3. lib/permissions/matrix.ts → vehicles:read/create/edit/delete permissions
4. server/api/routers/vehicles.ts → CRUD router
5. server/api/root.ts → Register the router
6. app/dashboard/vehicles/page.tsx → Dashboard page
7. server/api/routers/__tests__/vehicles.test.ts → Tests
The plan waits for approval before it continues. That's the part that changes everything compared to a generic prompt: the AI doesn't guess the list of files to touch for adding a module to this specific architecture, it has it written down already, it already knows a new scoped model needs to go into ORG_SCOPED_MODELS, a fact only this repository's Prisma rule makes explicit.
Limits: what AI doesn't replace
A rules file cuts the error rate, it doesn't cancel it out. What it doesn't do: guess a product decision nobody wrote down anywhere (what freemium limit makes sense for your market), replace a human code review on an RBAC permission change, or catch a problem that doesn't match any pattern already documented in the rules. An audit skill finds the IDOR bugs it was written to look for, not the ones nobody has thought of yet.
The discipline is the same as with a junior developer handed these same rules: they cut down on known mistakes, they don't excuse skipping a re-read of anything touching security or billing.
What you actually get with HeartCo
One thing to correct before citing a number: CLAUDE.md and .claude/rules/ are not exported with the boilerplate. They're this development repository's internal rules, not a generic product meant to be copied as-is into a project with neither the same freemium plans nor the same two-layer structure. What actually ships with the code: 8 of the 9 skills (audit-ai-signals, which concerns reselling the boilerplate itself, stays internal), and 6 scaffolding commands (new-model, new-module, new-page, new-router, ship, fix-build) out of the larger set used internally.
You leave with the tools, not with our business rules. Writing your own CLAUDE.md takes about an hour once you've seen the structure; the bundled /docs/en/vibe-coding-guide lists 17 ready-to-paste prompts, modeled on this repository's actual files, so you don't start from a blank page.
Go further
Related articles
Electronic 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.
ReadShipFast vs HeartCo: Which SaaS Boilerplate Should You Choose in 2026?
A direct, honest comparison of ShipFast and HeartCo: stack, pricing, features, and which kind of project each one actually fits.
ReadWhich 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.
ReadReady to launch your SaaS?
HeartCo Starter includes everything you need: auth, payments, AI, mobile, audited security. Starting at $219.