
FlashyCardy®
A designer who decided to ship code
FlashyCardy is a flashcard SaaS built from scratch as a vibe coding portfolio piece — a deliberate move from designing systems to actually building and deploying one. The goal wasn't just to learn Next.js. It was to understand what it feels like to own a product end-to-end: database schema, auth flows, billing, deployment pipelines, and production debugging at 11pm.
This is a record of that process — the stack, the breakages, and what actually got resolved.
Type
Solo Development Project
Stack
Next.js 15, TypeScript, Clerk, Neon
Year
2026
Status
Live on Vercel:
https://flash-card-ebon-psi.vercel.app/


FlashyCardy®
A designer who decided to ship code
FlashyCardy is a flashcard SaaS built from scratch as a vibe coding portfolio piece — a deliberate move from designing systems to actually building and deploying one. The goal wasn't just to learn Next.js. It was to understand what it feels like to own a product end-to-end: database schema, auth flows, billing, deployment pipelines, and production debugging at 11pm.
This is a record of that process — the stack, the breakages, and what actually got resolved.
Type
Solo Development Project
Stack
Next.js 15, TypeScript, Clerk, Neon
Year
2026
Status
Live on Vercel:
https://flash-card-ebon-psi.vercel.app/


Technical Stack®
//001
Modern, opinionated, occasionally brutal
The stack was chosen for real-world relevance — the same tools used in production B2B SaaS today.
Next.js 15
pp Router, server components, dynamic rendering
//01
TypeScript
Strict typing across all layers,
//02
Clerk
Auth, billing, subscription plans
//03
Neon + Drizzle
Serverless Postgres with type-safe ORM
//04
Tailwind v4
Utility-first styling, dark theme
//04
shadcn/ui
Component primitives, composable UI
//04
OpenAI API
AI flashcard generation, Pro feature, structured JSON output
//04





Technical Stack®
//001
Modern, opinionated, occasionally brutal
The stack was chosen for real-world relevance — the same tools used in production B2B SaaS today.
Next.js 15
pp Router, server components, dynamic rendering
//01
TypeScript
Strict typing across all layers,
//02
Clerk
Auth, billing, subscription plans
//03
Neon + Drizzle
Serverless Postgres with type-safe ORM
//04
Tailwind v4
Utility-first styling, dark theme
//05
shadcn/ui
Component primitives, composable UI
//06
OpenAI API
AI flashcard generation, Pro feature, structured JSON output
//07





Technical Stack®
//001
Modern, opinionated, occasionally brutal
The stack was chosen for real-world relevance — the same tools used in production B2B SaaS today.
Next.js 15
pp Router, server components, dynamic rendering
//01
TypeScript
Strict typing across all layers,
//02
Clerk
Auth, billing, subscription plans
//03
Neon + Drizzle
Serverless Postgres with type-safe ORM
//04
Tailwind v4
Utility-first styling, dark theme
//05
shadcn/ui
Component primitives, composable UI
//06
OpenAI API
AI flashcard generation, Pro feature, structured JSON output
//07





Auth + routing ✓resolved
Clerk authentication with middleware protection
Sign in, sign up, session management, and protected routes for /dashboard and /decks. Authenticated users redirect to the dashboard automatically.
Database layer ✓resolved
Neon + Drizzle ORM with typed queries
Serverless Postgres with schema-first design. Deck and card models, per-user data isolation, and query helpers with full TypeScript inference.
Freemium limits ✓resolved
3-deck cap on free accounts, Clerk billing for Pro
Free users see deck count, limit warnings at 2/3, and an upgrade prompt at 3/3. Pro users get unlimited decks via Clerk subscription features.
Deployment pipeline ✓resolved
Vercel CI/CD with environment variable management
Git push to main triggers production deploys. Clerk keys, database URL, and app config managed as Vercel environment variables across preview and production.
Post-payment UX ✓resolved
Return URL after Stripe checkout
Billing flow works end-to-end. The returnUrl prop on PricingTable is next — redirecting users back to the dashboard after a successful payment.
Key Challenges
//002
What actually breaks in production
The gap between local dev and production deployment is where most of the learning happened. These weren't abstract problems — they were blocking deploys at midnight
Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

AI agent auto-commit silently broke working code across 14 files
Cursor's agent was given one task: fix ESLint apostrophe errors. It completed the task and also rewrote 14 files in a single auto-commit — removing the isPublicRoute matcher from middleware, restructuring AuthRedirect, and changing component interfaces. The build passed. The app crashed on every page load. Identifying the causal commit required diffing 14 files by hand.

Vercel serving stale deployments — the fix was deployed but nothing changed
After pushing fixes, Vercel continued showing the previous failed deployment as current. Understanding the difference between a triggered build, a build cache hit, and a live deployment took longer than the fix itself. Eventually required a force-redeploy with cleared cache.


Recovery via git reset — using version control as a debugging tool
After multiple failed fix attempts, the fastest path to a working state was reverting to the last known-good commit using git reset --hard, then selectively restoring individual files with git checkout [hash] -- [file]. This recovered the app and preserved later work that was still valid.

How Things Got Resolved
//003
Debugging as a design skill ®
Each problem required a different tool. None of them were solved by asking an AI to fix it.
Version conflict
Read the dependency graph, not just the error
Running npm info @clerk/nextjs versions and cross-referencing with Next.js release notes identified the incompatibility. The fix was one command — but finding the cause required ruling out five other hypotheses first.
//01
File structure
Trace the error to its actual source
The Clerk error message said "check if clerkMiddleware is used" — accurate but misleading. Running find . -name middleware.ts and reading Clerk's docs on src/ projects resolved it in minutes once framed correctly.
//02
File structure
Use git history as a debugger
git log --oneline to find the breaking commit, git show [hash] -- [file] to inspect each changed file, then git reset --hard and selective file restoration. Faster and more precise than re-fixing forward.
//03
Production logs
Vercel runtime logs > build logs
Build logs show compile errors. Runtime logs show what crashes when real users hit the app. Filtering by Error level and expanding the full message — not just the truncated preview — revealed the exact file, line number, and digest for every Clerk failure.
//04
AI flashcard generation via OpenAI API
//004
The next major feature: Pro users will be able to generate entire flashcard decks from a topic, URL, or pasted text — powered by the OpenAI API. This moves FlashyCardy from a manual tool to an AI-assisted learning system.
Input
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
Processing
OpenAI API call with structured output — returns front/back pairs as JSON, validated before insert
//02
Gating
Feature checks Clerk subscription — Pro only. Free users see an upgrade prompt in the deck UI
//03
Stack addition
OpenAI SDK, server action for API call, streaming response for perceived performance
//04
What This Taught
//005
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
01
AI agents are not safe with broad scope. Cursor's agent fixed what it was asked to fix and silently broke other things in the same commit. Narrow, scoped tasks with reviewed diffs is the only safe operating mode for agents touching production code.
02
The same error message can have completely different root causes. "Clerk can't detect clerkMiddleware" appeared across five different deployments — each caused by a different issue. Treating error messages as patterns rather than answers is the actual shift.
03
Version compatibility is infrastructure, not a detail. Framework, auth library, and deployment toolchain versions interact in ways that aren't surfaced until you hit production. Checking compatibility before upgrading is now a fixed habit.
04
Git history is a debugger. git log --oneline, git show [hash] -- [file], git reset --hard, selective file checkout — these are not advanced commands. They're essential recovery tools that most tutorials skip entirely.
05
Designing and building the same product produces different judgment. Having owned both the UX decisions and the deployment failures changes how design decisions get made — not just aesthetically, but architecturally. What's hard to build shapes what should be designed.
What This Taught
//005
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
Outcome
//006
Live, functional, ongoing
5
Pages shipped
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
3+
Weeks of production debugging
Resolved across Clerk, Next.js, Vercel, and Git — not in a tutorial environment
//02
∞
Questions asked well
Why-first debugging, not just following steps — the actual skill being built
//03
Key Challenges
//002
What actually breaks in production
The gap between local dev and production deployment is where most of the learning happened. These weren't abstract problems — they were blocking deploys at midnight
Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

AI agent auto-commit silently broke working code across 14 files
Cursor's agent was given one task: fix ESLint apostrophe errors. It completed the task and also rewrote 14 files in a single auto-commit — removing the isPublicRoute matcher from middleware, restructuring AuthRedirect, and changing component interfaces. The build passed. The app crashed on every page load. Identifying the causal commit required diffing 14 files by hand.

Vercel serving stale deployments — the fix was deployed but nothing changed
After pushing fixes, Vercel continued showing the previous failed deployment as current. Understanding the difference between a triggered build, a build cache hit, and a live deployment took longer than the fix itself. Eventually required a force-redeploy with cleared cache.


Recovery via git reset — using version control as a debugging tool
After multiple failed fix attempts, the fastest path to a working state was reverting to the last known-good commit using git reset --hard, then selectively restoring individual files with git checkout [hash] -- [file]. This recovered the app and preserved later work that was still valid.

How Things Got Resolved
//003
Debugging as a design skill ®
Each problem required a different tool. None of them were solved by asking an AI to fix it.
Version conflict
Read the dependency graph, not just the error
Running npm info @clerk/nextjs versions and cross-referencing with Next.js release notes identified the incompatibility. The fix was one command — but finding the cause required ruling out five other hypotheses first.
//01
File structure
Trace the error to its actual source
The Clerk error message said "check if clerkMiddleware is used" — accurate but misleading. Running find . -name middleware.ts and reading Clerk's docs on src/ projects resolved it in minutes once framed correctly.
//02
File structure
Use git history as a debugger
git log --oneline to find the breaking commit, git show [hash] -- [file] to inspect each changed file, then git reset --hard and selective file restoration. Faster and more precise than re-fixing forward.
//03
Production logs
Vercel runtime logs > build logs
Build logs show compile errors. Runtime logs show what crashes when real users hit the app. Filtering by Error level and expanding the full message — not just the truncated preview — revealed the exact file, line number, and digest for every Clerk failure.
//04
AI flashcard generation via OpenAI API
//004
The next major feature: Pro users will be able to generate entire flashcard decks from a topic, URL, or pasted text — powered by the OpenAI API. This moves FlashyCardy from a manual tool to an AI-assisted learning system.
Input
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
Processing
OpenAI API call with structured output — returns front/back pairs as JSON, validated before insert
//02
Gating
Feature checks Clerk subscription — Pro only. Free users see an upgrade prompt in the deck UI
//03
Stack addition
OpenAI SDK, server action for API call, streaming response for perceived performance
//04
What This Taught
//005
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
01
AI agents are not safe with broad scope. Cursor's agent fixed what it was asked to fix and silently broke other things in the same commit. Narrow, scoped tasks with reviewed diffs is the only safe operating mode for agents touching production code.
02
The same error message can have completely different root causes. "Clerk can't detect clerkMiddleware" appeared across five different deployments — each caused by a different issue. Treating error messages as patterns rather than answers is the actual shift.
03
Version compatibility is infrastructure, not a detail. Framework, auth library, and deployment toolchain versions interact in ways that aren't surfaced until you hit production. Checking compatibility before upgrading is now a fixed habit.
04
Git history is a debugger. git log --oneline, git show [hash] -- [file], git reset --hard, selective file checkout — these are not advanced commands. They're essential recovery tools that most tutorials skip entirely.
05
Designing and building the same product produces different judgment. Having owned both the UX decisions and the deployment failures changes how design decisions get made — not just aesthetically, but architecturally. What's hard to build shapes what should be designed.
What This Taught
//005
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
Outcome
//006
Live, functional, ongoing
5
Pages shipped
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
3+
Weeks of production debugging
Resolved across Clerk, Next.js, Vercel, and Git — not in a tutorial environment
//02
∞
Questions asked well
Why-first debugging, not just following steps — the actual skill being built
//03
Key Challenges
//04
What actually breaks in production
The gap between local dev and production deployment is where most of the learning happened. These weren't abstract problems — they were blocking deploys at midnight
Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

Next.js 16 + Clerk v7 incompatibility — build fails with cryptic error
The project started on Next.js 16.2.3. Clerk v7 had no support for it. Vercel builds failed with middleware.js.nft.json not found — an error that gives no indication of a version conflict. The fix required downgrading to Next.js 15 after ruling out middleware placement, Turbopack config, and Clerk setup as causes.

AI agent auto-commit silently broke working code across 14 files
Cursor's agent was given one task: fix ESLint apostrophe errors. It completed the task and also rewrote 14 files in a single auto-commit — removing the isPublicRoute matcher from middleware, restructuring AuthRedirect, and changing component interfaces. The build passed. The app crashed on every page load. Identifying the causal commit required diffing 14 files by hand.

Vercel serving stale deployments — the fix was deployed but nothing changed
After pushing fixes, Vercel continued showing the previous failed deployment as current. Understanding the difference between a triggered build, a build cache hit, and a live deployment took longer than the fix itself. Eventually required a force-redeploy with cleared cache.


Recovery via git reset — using version control as a debugging tool
After multiple failed fix attempts, the fastest path to a working state was reverting to the last known-good commit using git reset --hard, then selectively restoring individual files with git checkout [hash] -- [file]. This recovered the app and preserved later work that was still valid.

How Things Got Resolved
//003
Debugging as a design skill ®
Each problem required a different tool. None of them were solved by asking an AI to fix it.
Version conflict
Read the dependency graph, not just the error
Running npm info @clerk/nextjs versions and cross-referencing with Next.js release notes identified the incompatibility. The fix was one command — but finding the cause required ruling out five other hypotheses first.
//01
File structure
Trace the error to its actual source
The Clerk error message said "check if clerkMiddleware is used" — accurate but misleading. Running find . -name middleware.ts and reading Clerk's docs on src/ projects resolved it in minutes once framed correctly.
//02
File structure
Use git history as a debugger
git log --oneline to find the breaking commit, git show [hash] -- [file] to inspect each changed file, then git reset --hard and selective file restoration. Faster and more precise than re-fixing forward.
//03
Production logs
Vercel runtime logs > build logs
Build logs show compile errors. Runtime logs show what crashes when real users hit the app. Filtering by Error level and expanding the full message — not just the truncated preview — revealed the exact file, line number, and digest for every Clerk failure.
//04
AI flashcard generation via OpenAI API
//004
The next major feature: Pro users will be able to generate entire flashcard decks from a topic, URL, or pasted text — powered by the OpenAI API. This moves FlashyCardy from a manual tool to an AI-assisted learning system.
Input
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
Processing
OpenAI API call with structured output — returns front/back pairs as JSON, validated before insert
//02
Gating
Feature checks Clerk subscription — Pro only. Free users see an upgrade prompt in the deck UI
//03
Stack addition
OpenAI SDK, server action for API call, streaming response for perceived performance
//04
What This Taught
//04
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
01
AI agents are not safe with broad scope. Cursor's agent fixed what it was asked to fix and silently broke other things in the same commit. Narrow, scoped tasks with reviewed diffs is the only safe operating mode for agents touching production code.
02
The same error message can have completely different root causes. "Clerk can't detect clerkMiddleware" appeared across five different deployments — each caused by a different issue. Treating error messages as patterns rather than answers is the actual shift.
03
Version compatibility is infrastructure, not a detail. Framework, auth library, and deployment toolchain versions interact in ways that aren't surfaced until you hit production. Checking compatibility before upgrading is now a fixed habit.
04
Git history is a debugger. git log --oneline, git show [hash] -- [file], git reset --hard, selective file checkout — these are not advanced commands. They're essential recovery tools that most tutorials skip entirely.
05
Designing and building the same product produces different judgment. Having owned both the UX decisions and the deployment failures changes how design decisions get made — not just aesthetically, but architecturally. What's hard to build shapes what should be designed.
What This Taught
//005
Real understanding, not bypassing it
The original intent was to use AI tools to accelerate building, not to avoid understanding the stack. That distinction mattered more in practice than expected.
Outcome
//006
Live, functional, ongoing
5
Pages shipped
Topic prompt, pasted text, or URL — user defines scope and number of cards to generate
//01
3+
Weeks of production debugging
Resolved across Clerk, Next.js, Vercel, and Git — not in a tutorial environment
//02
∞
Questions asked well
Why-first debugging, not just following steps — the actual skill being built











