rodeo: A free React starter for Claude Code and Codex.
Checks every , catches , and keeps
on track.
npx degit quinnsprouse/rodeo my-appA better foundation to build on.
Agents copy whatever's already in a codebase. Give them a messy one and you get more mess, just faster. So Rodeo starts with the foundation. The pyramid shows where its effort goes: most into the codebase, less into static analysis and prose, and the least into human review, which scales the worst.
Codebase
Layers, tokens, server-only files.
Static analysis
Every error names its fix.
Prose
Short guides, read when needed.
Human review
Only the exceptions, each marked.
Adapted from poteto's post on X
Rodeo has opinions.
In a Rodeo app, agents read the code far more often than people do, and every line they read costs tokens. So Rodeo drops a few habits that suit people but waste an agent's time.
No code comments
Most comments restate in English what the code already says, and an agent can read the code. So each one costs tokens and adds nothing. Agents also copy what they see, so one comment leads to more.
Browser tests, not unit tests
Agents often write unit tests like "the header says Welcome." Change the copy and the test fails though nothing broke, so the agent spends tokens rewriting it. A browser test clicks through a real flow. When it fails, a person would have hit the same bug.
Lint rules stay on
When a lint rule gets in the way, the easy fix for an agent is a disable comment, and the problem hides. Rodeo rejects those comments. Exceptions go in vite.config.ts with a reason, so you can see them all in one file.
Docs stay short
An agent loads docs into the same context window it needs for the task, so every extra paragraph crowds out the work. Docs also go stale, and an agent believes them anyway. Rodeo ships seven short guides, and an agent opens one only when the task needs it.
One design system
Left alone, an agent reaches for a new gray or a 13px font whenever it needs one, and each screen drifts a little further. Lint knows the theme's sizes and colors and rejects anything else, so new screens match the old ones without you checking.
Code flows one way
Routes import components, components import hooks, and hooks import src/lib. Lint blocks any import that points back up. So when an agent edits a component, it knows nothing below can break.
Mistakes go back to the agent, not to you.
Rodeo checks the agent's work as it goes. When a check fails, the agent gets the error and fixes it before you look.
Add a pricing page with live prices from Stripe.
- Read AGENTS.md
- Edit src/routes/pricing.tsx
- process.env in browser code. Loaders run in the browser too. Move Stripe to a .server.ts file.
- Move Stripe to prices.server.ts
- Format, lint, and types pass
- Your pricing page is ready.
RodeoLint and types pass
src/routes/pricing.tsx−3 +2
import { createFileRoute } from "@tanstack/react-router";import Stripe from "stripe";const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);import { getPrices } from "@/lib/prices"; export const Route = createFileRoute("/pricing")({ loader: () => stripe.prices.list({ active: true }), loader: () => getPrices(), component: PricingPage,});RodeoLint and types pass
Start with the guardrails in place.
Clone it and point Claude Code or Codex at AGENTS.md. Both run the same hooks, and Vite+, TanStack Start, React 19, Tailwind v4, and shadcn/ui come set up.
npx degit quinnsprouse/rodeo my-app