Before you start
- Get the app running: Run the app locally
- Skim the architecture guide, especially the data layer
- Find your feature in Features & Routes
Where does my code go?
Start inside a feature. Promote to
shared/ on the second use, not the first.
Recipe: add a new API call
1
Add the service function
Services are plain async functions built on the shared client. Use Always accept and forward
apiData when the endpoint
returns a single resource, apiRequest when you need the pagination envelope too.context. It carries the abort signal and, server-side, cookies.2
Add a query key
detail(projectId) means invalidating the project also invalidates its
contributors.3
Add the hook
4
Use it in a component
fetch directly.5
Mock the endpoint
Local development will return 501 until the mock knows the route. See
the Mock API guide.
Recipe: add a mutation
getErrorMessage() from src/shared/lib/get-error-message.ts
and a sonner toast, which is the pattern the rest of the app follows.
Recipe: add a page
1
Create the route
2
Create the view
The view is a client component in the feature that calls the hooks and composes components:
src/features/projects/views/contributors.view.tsx.3
Protect it if needed
Add the path to the protected list in
src/middleware.ts, and to the disallow list in
src/app/robots.ts if it shouldn’t be indexed.Recipe: add a UI component
Checksrc/shared/components/ui/ first. There are already 60-odd components covering uploads,
comboboxes, cards, tables, pagination, and markdown rendering.
For a new shadcn primitive:
cn(), and use design tokens rather than raw colours:
src/app/globals.css. There is no tailwind.config.js.
Style rules that will fail your build
Biome runs in CI, and a few rules surprise people:TypeScript `enum` is banned (noEnum)
TypeScript `enum` is banned (noEnum)
Use a union type or a
const object:Formatting is enforced, not suggested
Formatting is enforced, not suggested
80-column lines, 2-space indent, double quotes, ES5 trailing commas, semicolons always.
pnpm lint fails on drift. Run pnpm lint:write.Import order is enforced
Import order is enforced
Biome’s
organizeImports assist sorts imports. Don’t reorder them by hand; let
pnpm lint:write do it.Other rules at error level
Other rules at error level
noInferrableTypes, noParameterAssign, noUselessElse, useAsConstAssertion,
useDefaultParameterLast, useSingleVarDeclarator, useNumberNamespace.noUnusedVariables and useExhaustiveDependencies are warnings. They won’t fail CI, but
fix them anyway.Several accessibility rules are disabled project-wide. Lint passing does not mean your
component is accessible. Check keyboard navigation and labelling yourself.
Before you push
type-check won’t.
Contribution workflow
Branches, commits, and opening the pull request.