.cursorrules (deprecated)
rules/saas-starter/.cursorrules.cursorrules
Quality
69/100
Scores the file, not the repository.Length
1,093 words
16 headings · 10 code blocksRepository
16
— · pushed 109 days agoLast changed
2 days ago
First indexed 2 days ago.1# SaaS Starter — Cursor Rules2# SaaS boilerplate patterns: auth, billing, multi-tenant, and subscription management34# Project Context5You are building a multi-tenant SaaS application. The stack includes a modern web framework6(Next.js, Remix, or similar), a relational database with an ORM, Stripe for billing, and7email-based authentication. The architecture supports team workspaces, role-based access,8subscription tiers, and usage-based features.910# Multi-Tenancy Architecture11- Use a shared database with tenant isolation via `organizationId` foreign key on all tenant-scoped tables.12- Every tenant-scoped query MUST include the organization filter:13```typescript14 // ALWAYS include organizationId in queries15 const projects = await db.project.findMany({16 where: { organizationId: currentOrg.id },17 });18```19- Create a middleware or helper that automatically scopes queries to the current tenant.20- Use a `memberships` join table for user-to-organization relationships:21```22 User -> Membership (role, joinedAt) -> Organization23```24- Support multiple organization membership per user (users can belong to multiple workspaces).25- DON'T: Trust client-side organization IDs — always verify membership server-side.26- DON'T: Use subdomain-based tenancy unless you need complete brand isolation.2728# Authentication Architecture29- Implement email + password with secure password hashing (bcrypt, argon2).30- Support OAuth providers (Google, GitHub) with account linking.31- Email verification required before full account access.32- Password reset flow: generate time-limited token, send reset email, validate on submission.33- Session management with secure, HttpOnly, SameSite cookies.34- Schema:35```36 User (id, email, name, emailVerifiedAt, hashedPassword)37 Account (id, userId, provider, providerAccountId) -- OAuth accounts38 Session (id, userId, token, expiresAt)39 VerificationToken (token, email, expiresAt)40```4142# Role-Based Access Control (RBAC)43- Define roles per organization membership, not per user:44```typescript45 enum MemberRole {46 OWNER = 'owner', // Full control, billing, can delete org47 ADMIN = 'admin', // Manage members, settings48 MEMBER = 'member', // Standard access49 VIEWER = 'viewer', // Read-only access50 }51```52- Check permissions at the service layer, not in UI components:53```typescript54 function assertPermission(membership: Membership, action: Action): void {55 if (!hasPermission(membership.role, action)) {56 throw new ForbiddenError(`Role ${membership.role} cannot ${action}`);57 }58 }59```60- Hide UI elements based on role, but ALWAYS enforce on the server.61- Organization owners cannot remove themselves — transfer ownership first.6263# Stripe Billing Integration64- Use Stripe Checkout for new subscriptions (hosted payment page).65- Use Stripe Customer Portal for managing existing subscriptions.66- Store Stripe IDs in your database:67```68 Organization (stripeCustomerId, stripeSubscriptionId, stripePriceId, subscriptionStatus)69```70- Sync subscription state via webhooks, not API polling:71```typescript72 // Handle these webhook events:73 // checkout.session.completed — new subscription created74 // customer.subscription.updated — plan change, renewal75 // customer.subscription.deleted — cancellation76 // invoice.payment_succeeded — successful payment77 // invoice.payment_failed — failed payment (trigger dunning)78```79- Create Stripe customer on organization creation, not on checkout.80- Use Stripe's `metadata` to link Stripe objects back to your org: `metadata: { organizationId }`.81- DON'T: Store credit card details — Stripe handles PCI compliance.82- DON'T: Check subscription status from Stripe API on every request — cache in your database.8384# Subscription Tier Enforcement85- Define feature flags per plan tier:86```typescript87 const PLAN_LIMITS = {88 free: { maxMembers: 3, maxProjects: 5, storageGB: 1, hasApiAccess: false },89 pro: { maxMembers: 20, maxProjects: 50, storageGB: 50, hasApiAccess: true },90 enterprise: { maxMembers: -1, maxProjects: -1, storageGB: 500, hasApiAccess: true },91 } as const;92```93- Check limits at the service layer before allowing operations:94```typescript95 async function createProject(orgId: string, data: CreateProjectInput) {96 const org = await getOrganization(orgId);97 const limits = PLAN_LIMITS[org.plan];98 const projectCount = await db.project.count({ where: { organizationId: orgId } });99 if (limits.maxProjects !== -1 && projectCount >= limits.maxProjects) {100 throw new PlanLimitError('projects', limits.maxProjects, org.plan);101 }102 return db.project.create({ data: { ...data, organizationId: orgId } });103 }104```105- Show upgrade prompts when users hit limits.106- Grace period: don't immediately restrict access on payment failure.107108# Invitation System109- Invite users by email to an organization with a specific role.110- Generate time-limited invitation tokens.111- Allow accepting invitations to create account or add to existing account.112- Handle edge cases: expired invites, already-member, invite to non-existent email.113- Schema:114```115 Invitation (id, email, organizationId, role, token, expiresAt, acceptedAt, invitedById)116```117118# Email System119- Use a transactional email provider (Resend, Postmark, SendGrid).120- Template emails with consistent branding:121 - Welcome email (after verification)122 - Email verification123 - Password reset124 - Invitation to organization125 - Subscription confirmation/change126 - Payment failure notice127- Always include unsubscribe links for marketing emails.128- Queue emails for async sending — don't block the request.129130# API Design for SaaS131- Scope all API routes under the organization: `/api/v1/orgs/:orgId/projects`.132- Verify organization membership on every API request.133- Include rate limiting per organization (not per user) for API access.134- Use API keys for programmatic access with scoped permissions.135- Version your API from day one: `/api/v1/`.136137# Onboarding Flow138- Minimal friction: email -> verify -> create org -> first project.139- Guide new users with an onboarding checklist.140- Provide sample data / templates for immediate value.141- Track onboarding completion for analytics.142143# Security Checklist144- [ ] All tenant-scoped queries include organizationId filter.145- [ ] Server-side permission checks on every mutation.146- [ ] Stripe webhook signature verification.147- [ ] Rate limiting on auth endpoints (login, register, password reset).148- [ ] CSRF protection on all state-changing requests.149- [ ] Input validation on all endpoints with zod or similar.150- [ ] Secure session management (HttpOnly, Secure, SameSite cookies).151- [ ] Audit logging for sensitive operations (role changes, billing, data deletion).152153# Database Schema Essentials154- Soft-delete for organizations and user data (regulatory compliance).155- Audit trail table for compliance-sensitive actions.156- Use database-level constraints (unique, foreign key) as the last line of defense.157- Index all foreign keys and commonly filtered columns.158159# Testing SaaS Features160- Test multi-tenant isolation: ensure Org A cannot access Org B's data.161- Test billing webhooks with Stripe's test mode and webhook testing tools.162- Test role-based access: verify each role can/cannot perform expected actions.163- Test invitation flow end-to-end.164- Test subscription limit enforcement.165- Test graceful degradation on payment failure.166167# Common Mistakes to Avoid168- DON'T: Forget tenant scoping on any database query — this is a data leak.169- DON'T: Check permissions only in the UI — always enforce server-side.170- DON'T: Trust Stripe webhook data without verifying the signature.171- DON'T: Block requests to check Stripe API — use webhook-synced local state.172- DON'T: Let users downgrade if they exceed the lower plan's limits without resolution.173- DON'T: Hard-delete user data — use soft-delete for compliance.174
Also in survivorforge/cursor-rules
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 16 | .cursorrules | teststylearchdeployment+2 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-design-rest/.cursorrules · 16 | .cursorrules | lint-formatstylesecurityapi+3 | 69/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 92/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/aws-serverless/.cursorrules · 16 | .cursorrules | teststylearchtypes+6 | 73/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/chrome-extension/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+4 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/clean-code/.cursorrules · 16 | .cursorrules | styledo-notagent-behaviourdocs | 57/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 16 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16 | .cursorrules | setupbuildteststyle+4 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16 | .cursorrules | buildteststylesecurity+3 | 93/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 16 | .cursorrules | buildteststylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 85/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 16 | .cursorrules | teststylearchtypes+5 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/fullstack-nextjs-prisma/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 96/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/go-production/.cursorrules · 16 | .cursorrules | teststylearchtesting-strategy+3 | 89/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/golang-api/.cursorrules · 16 | .cursorrules | buildteststylearch+6 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mcp-server/.cursorrules · 16 | .cursorrules | testlint-formatstylearch+7 | 68/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mern-stack/.cursorrules · 16 | .cursorrules | setupteststylearch+6 | 81/100 | 2 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 16 | .cursorrules | teststylearchtypes+7 | 89/100 | 2 days ago |
Diff against rules/ai-ml-python/.cursorrules Diff against rules/api-design-rest/.cursorrules Diff against rules/api-microservices/.cursorrules Diff against rules/aws-serverless/.cursorrules Diff against rules/chrome-extension/.cursorrules Diff against rules/clean-code/.cursorrules Diff against rules/database-sql/.cursorrules Diff against rules/devops-docker/.cursorrules Diff against rules/devops-infrastructure/.cursorrules Diff against rules/django-rest/.cursorrules Diff against rules/docker-devops/.cursorrules Diff against rules/flutter-dart/.cursorrules Diff against rules/fullstack-nextjs-prisma/.cursorrules Diff against rules/go-gin/.cursorrules Diff against rules/go-production/.cursorrules Diff against rules/golang-api/.cursorrules Diff against rules/langchain-ai/.cursorrules Diff against rules/mcp-server/.cursorrules Diff against rules/mern-stack/.cursorrules Diff against rules/mobile-react-native/.cursorrules
