Building a Full-Stack SaaS MVP using Claude 3.5 Sonnet and Cursor
The secret to not ending up with a "hallucination spaghetti" codebase is how you seed the project. If you just ask Cursor to "build a SaaS," it will give you generic boilerplate that breaks the moment you add a second page. Instead, I use a .cursorrules file in the root directory to force the AI to adhere to a specific stack and pattern.
For this build, I locked it into: Next.js 14 (App Router), Tailwind CSS, Prisma, and Supabase.
In my .cursorrules, I added this specific instruction:
Always use Server Components by default. Only use 'use client' when interactive state is required.
For database schema changes, always provide the Prisma schema update first, then the migration command, then the updated API route.
Prefer Zod for validation and avoid any 'any' types in TypeScript.The actual build process follows a "Schema-First" loop. I don't start with the UI; I start by describing the data model in the Composer. Once the schema.prisma is locked in and migrated, I feed the schema back into the prompt for the UI components. This ensures the AI knows exactly what fields exist in the DB, eliminating those annoying "property does not exist on type" errors.
One massive productivity gain is using the @Web symbol to pull in the latest documentation. Since AI training data lags, I frequently use @Web https://orm.prisma.io/docs or @Web https://ui.shadcn.com when I hit a wall. This prevents the AI from suggesting deprecated API calls.
Here is the exact prompt pattern I use to generate complex features (like a Stripe integration) without it breaking existing code:
@Files (schema.prisma, layout.tsx)
Implement a Stripe webhook handler in /api/webhooks/stripe.
1. Validate the signature using the STRIPE_WEBHOOK_SECRET.
2. Update the User table in Prisma to set 'plan' to 'pro' on checkout.session.completed.
3. Ensure the response is a 200 OK to prevent Stripe retries.
Reference the existing database patterns in @schema.prisma.The "gotcha" that usually trips people up is the context window. After about 20-30 iterations on a single feature, the Composer starts forgetting earlier constraints or introducing regressions. My fix is to periodically "checkpoint" the project: I commit the working code to Git, then start a fresh Composer session, explicitly referencing the current state of the files.
Performance Gains:
- Boilerplate reduction: Setting up Auth, DB connections, and Basic CRUD took about 45 minutes instead of the usual 4 hours.
- Refactoring speed: Highlighting a messy function and hitting Cmd+K to "optimize for readability and type safety" is a game changer.
- Debugging: Pasting a terminal error directly into the chat usually solves the issue in one go because Cursor has the full project context.
The biggest shift is mental. I've stopped thinking about "how to write the loop" and started thinking about "how the data flows." You aren't just coding; you're auditing.
All Replies (0)
No replies yet — be the first!
