Think Throo is in Beta — Some features are still evolving. Expect improvements and the occasional rough edge.
Canopy Codebase Architecture
1 chapter
Canopy Codebase Architecture
Stop explaining your architecture to your AI agent on every task. This collection, inspired by LobeChat's OSS codebase, gives it the full picture — project structure, API layer, state management, components structure, error handling, and performance patterns — once, permanently.
Install
SKILL.md
/--- name: canopy-codebase-architecture description: > Full-stack Next.js codebase architecture guide. Use when scaffolding a new feature, placing files, wiring up an API endpoint, adding a Zustand store, protecting a route, handling errors, or optimising performance. Covers the complete vertical slice from database to UI using a Todo app as the canonical example. Triggers on any task involving project structure, API design, state management, security, components, error handling, or performance in a Next.js App Router codebase. license: MIT metadata: author: thinkthroo version: "1.0.0" series: amazon-rainforest /---
Canopy — Codebase Architecture
A comprehensive architecture guide for production-grade Next.js applications, demonstrated through a Todo app. Contains rules across 7 categories, prioritised by impact.
All code examples use
TodoItem,createTodo,store/todo/, etc. so the patterns transfer cleanly to any domain — swap the entity name for your own.
When to Apply
Reference these guidelines when:
- Scaffolding a new feature end-to-end (DB → API → store → UI)
- Deciding where a new file belongs
- Writing or reviewing tRPC routers and client services
- Creating or refactoring Zustand stores
- Protecting routes or procedures
- Adding error handling and observability
- Optimising re-renders or bundle size
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rule file |
|----------|----------|--------|--------|-----------|
| 1 | Project Structure | CRITICAL | struct- | rules/project-structure.md |
| 2 | API Layer | CRITICAL | api- | rules/api-layer.md |
| 3 | Security | HIGH | sec- | rules/security.md |
| 4 | State Management | MEDIUM-HIGH | state- | rules/state-management.md |
| 5 | Component Structure | MEDIUM | comp- | rules/component-structure.md |
| 6 | Error Handling | MEDIUM | err- | rules/error-handling.md |
| 7 | Performance | LOW-MEDIUM | perf- | rules/performance.md |
Quick Reference
1. Project Structure (CRITICAL)
struct-directory-layout— One folder per concern at the top level; never mix concernsstruct-data-flow— Unidirectional: UI → Store → Service → tRPC → Server Service → DBstruct-feature-colocation— Components used by one page live next to that pagestruct-naming-conventions— PascalCase components, camelCase hooks/utils, UPPER_SNAKE_CASE constantsstruct-env-imports— Always import env vars through a validatedutils/env.ts, neverprocess.envdirectly
2. API Layer (CRITICAL)
api-single-client— One pre-configured tRPC client instance; never create duplicatesapi-router-per-entity— One tRPC router file per entity, all registered in a root indexapi-service-abstraction— Client service wraps tRPC client calls; exported as a singletonapi-typed-input— All procedure inputs validated with Zod schemasapi-authed-procedure— All user-data endpoints useauthedProcedure, neverpublicProcedure
3. Security (HIGH)
sec-auth-middleware— Route protection lives inmiddleware.ts, not in page componentssec-authed-procedure— ReaduserIdonly fromctx, never from request body or paramssec-no-token-state— Tokens are never stored inlocalStorageor Zustandsec-input-validation— Validate at the API boundary; never trust client-supplied datasec-database-rls— Every user-owned table has RLS enabled with all CRUD policiessec-service-role-server-only— Admin/service-role DB client used only in server-side code
4. State Management (MEDIUM-HIGH)
state-store-per-entity— One Zustand store per entity with a standard five-file structurestate-initial-shape— Explicit TypeScript interface + zero-value default objectstate-selectors— All selectors live inselectors.ts; never write inline selectors in componentsstate-actions-call-services— Actions are the only place that call client servicesstate-devtools-naming— Passfalse, 'actionName'to everyset()call for DevTools tracing
5. Component Structure (MEDIUM)
comp-server-first— Default to Server Components; add"use client"only when the component needs interactivitycomp-ui-library— Use the shared UI package; never install shadcn components individually per appcomp-feature-colocation— One page → co-locate; two or more pages → promote tocomponents/comp-modal-pattern— All modals acceptopenandonOpenChangeprops; useDialogfrom the UI librarycomp-typed-props— Every component has explicit prop types; no implicitany
6. Error Handling (MEDIUM)
err-catch-and-capture— Everycatchblock callsSentry.captureExceptionwithtags.hookandtags.actionerr-user-toast— Showtoast.error()for every user-visible failure; neveralert()or log-onlyerr-boundaries— Add route-levelerror.tsxnext to every page that fetches dataerr-structured-logging—Sentry.loggeron the client;pinoon the servererr-no-swallow— Never swallow errors silently; everycatchmust capture or re-throw
7. Performance (LOW-MEDIUM)
perf-dynamic-import— Lazy-load heavy components withnext/dynamic; always provide a loading fallbackperf-memo— Wrap expensive components withReact.memowhen the parent re-renders frequentlyperf-use-memo— Memoize expensive derived values; keep dependency arrays exhaustiveperf-debounce— Debounce side-effects triggered by fast user input; useuse-debounceperf-fine-grained-selectors— Subscribe to specific state slices, never the whole store object
How to Use
Read a rule file for the detailed explanation and code examples:
rules/project-structure.md — struct-* rules
rules/api-layer.md — api-* rules
rules/security.md — sec-* rules
rules/state-management.md — state-* rules
rules/component-structure.md — comp-* rules
rules/error-handling.md — err-* rules
rules/performance.md — perf-* rules
Each rule contains:
- Why it matters — the problem it prevents
- Bad example — what not to do, with explanation
- Good example — the correct pattern, with explanation
Full Compiled Document
For all rules expanded in one flat document: AGENTS.md