Catalyst

The Next.js starter for building with AI

Build your product.
Not your setup.

Every starter kit hands you auth and payments. This one also hands your agent the rules that keep them intact.

Clone the repo

You aren't shipping faster.
You're reviewing more code than you write.

Every turn ends with you reading a diff for mistakes a linter should have caught. By the next prompt, the agent has forgotten them.

  1. youAdd a "last shipped" column to the projects table.
  2. agentDone. Added the column, the query, and the UI. ✓
  3. # you open the diff
  4. projects-table.tsx imports prisma straight into a component
  5. tsc: Property 'shippedAt' does not exist on type 'Project'
  6. getLastShipped() now exists twice, one copy unused
  7. youComponents can't touch Prisma. And tsc is failing.
  8. agentYou're right! Fixed. ✓
  9. # it isn't. the query moved, and a copy stayed behind.

Same mistakes, every turn, and you catch them by hand. Catalyst gives that job back to the agent.

Your agent reviews itself now.

Eight checks run the moment your agent stops. Any failure goes back to the agent with the reason attached. It fixes the code and runs again. You see the diff once everything is green.

  1. youAdd a "last shipped" column to the projects table.
  2. agentDone. Added the column, the query, and the UI.
  3. # stop hook: 8 checks
  4. klintprojects-table.tsx: Prisma belongs in the DAO. Add a function under src/lib/dao/ and call that instead.
  5. tscProperty 'shippedAt' does not exist on type 'Project'
  6. jscpdgetLastShipped() duplicated across 2 files
  7. # sent back to the agent, not to you
  8. agentMoving the query to src/lib/dao/projects.ts, adding shippedAt to the Project model, removing the copy.
  9. # stop hook: 8 checks
  10. check·type-check·knip·jscpd·klint·madge·lf·secretlint
  11. # you open the diff. nothing to fix.

Your review starts at working code.

Finished code isn't finished until it runs.

Push to stage and the agent follows the commit through CI and the deploy to the live URL. Then it opens the page and takes a screenshot. It never opens the PR into main. What reaches production is up to you.

  1. youShip it to stage.
  2. agentPushed 4e1c9a2 to stage.
  3. # following the commit
  4. cibuild·test·type-check
  5. deploystage finished, 4e1c9a2 is live
  6. visual/projects renders the "last shipped" column
  7. agentLive on stage and checked. The PR into main is yours to open.

The agent proves it works. You decide where it goes.

Your next users won't open a browser.

Every app will need an MCP server. Catalyst ships one at /api/mcp, with the hard parts built in: API keys your users mint in settings, rate limits per key, every query scoped to the key's owner, and nothing exposed unless you list it. It starts read-only. Adding write access is your call.

  • Claude Code
  • Cursor
  • OpenCode
  1. API keyminted in your app's settings
  2. Rate limit120 a minute per key, then 429
  3. User scoperows filtered to the key's owner
  4. Allowlistcolumns hidden unless listed

Your models

src/lib/mcp/registry.ts

Read-only today, read-write when you're ready. The plumbing is already there.

A head start you have to dig out of
is not a head start.

Every feature you don't need is code you read, maintain and work around, and your agent reads it too. So most teams tear the boilerplate apart or start over. Catalyst ships with everything wired up, and bun run configure removes what you don't need. A lint rule keeps features independent, so removing one never breaks another.

$bun run configure

after bun run configure

  • Auth
  • Database
  • Stripe
  • Email
  • Storage
  • Redis
  • tRPC
  • MCP

Always there: Next.js·Tailwind·shadcn/ui·Biome·Bun

Start with everything. Ship only what you use.

Now you're shipping faster.
For real this time.

Clone it, run bun run configure, and your agent checks its own work from the first prompt.

$git clone https://github.com/kovrichard/catalyst.git