Every new project I start repeats the same decisions: framework, auth, lint rules, folder layout, billing. I used to copy an old repo and delete things. Now I keep a catalog instead. It is called Parts, and it is built for agents to read.
A catalog, not a template
A template is a finished app you clone and then strip. You inherit everything, including what you do not need, and the app you cloned keeps drifting from the one you build.
Parts is not a running application. It is a source of conventions and building blocks. In a new repo, I tell an agent which parts to bring over. The agent copies them, adapts them to the project, and connects them.
The baseline stays small. Each optional capability is a module with a clear entry point and its own dependencies and README. Today that covers Better Auth, Stripe catalog tooling, an optional French locale, a Tauri 2 desktop shell, and two hosting targets (Vercel and Cloudflare Workers).
Gates that do not bend
Agents write a lot of code fast. Without limits, the code gets tangled fast too. The base ships with strict checks that fail the build.
- Oxlint plus full ESLint, zero warnings, no inline suppression.
- Strict TypeScript and Effect diagnostics.
- Knip for dead code.
- Cyclomatic complexity capped at 6.
- A handwritten file may not pass 1,000 lines.
- A folder may not hold more than 8 handwritten code files.
The last two are the ones that change how an agent works. When a file hits the cap, the agent has to split it by responsibility. When a folder fills up, it has to group files by concern. Generated code is excluded. The whole gate runs as one script:
"check": "bun run lint && bun run typecheck && bun run knip"The limits are harsh on purpose. A cap of 6 means functions stay small and branches move into named pieces. I would rather the agent split a function than argue with me about why it did not.
Replaceable service boundaries
The starter is a todo app, but the useful part is how it is wired. Session, task, account, and billing dependencies are Effect Layers. Feature code calls a service such as TodoService or BillingService. It never calls Better Auth or Convex directly.
That means a destination can swap a provider at one boundary. The billing provider in the starter returns a deterministic mock receipt and makes no external payment call. Replace that one layer with a real Stripe adapter and the callers do not change. The same seam lets a test supply a signed-out session without touching the access service.
Server rules stay on the server. The roles and permissions module puts identity and authority checks in shared Convex builders, so hiding a button is never the only lock.
How an agent imports a part
The README starts with a prompt I paste into any coding agent. It points at the repo and asks the agent to read README.md, AGENTS.md, and instructions/start-project.md. Then it sets the rules of the job:
- Ask me for the project name, destination, and which parts I want.
- Explain the tradeoffs and confirm my choices before changing files.
- Set up the agreed base and parts, then verify the result.
- Do not commit, push, or deploy unless I say so.
The start-project guide interviews me about billing, languages, native targets, and hosting. Then it creates a new project or merges the chosen parts into an existing one without replacing the stack already there.
Each module README says what it provides, what files to import, what to configure, and how to verify the result. Importing also means connecting. If an agent brings over roles and permissions, it also applies the shared builders to the protected backend functions. If it brings over agent login, it signs in and exercises the admin flows.
Being honest about status
Parts labels what is real. Some pieces are implemented templates. Some are integration references adapted from my other projects, and some are still planned. A WorkOS adapter and an OpenRouter module are on the planned list. The agent is told to report which is which and to verify imported behavior in the destination before calling anything done.
That honesty is part of the design. A foundation you cannot trust is worse than none.
Why it works for me
Starting a project is now a conversation and a checklist, not a day of setup. The quality bar is the same on project five as on project one, because the gates travel with the parts. And when I improve a part, every future project gets the improvement.