Documentation Index
Fetch the complete documentation index at: https://docs.folksbase.joselito.dev/llms.txt
Use this file to discover all available pages before exploring further.
Why These Rules Exist
folksbase uses strict rules to keep the codebase consistent and catch bugs early. Biome handles formatting and linting (replacing ESLint + Prettier), and TypeScript is configured with maximum strictness. CI rejects any violations — there’s no “fix it later.”Biome
Biome handles both formatting and linting in a single tool. Configuration lives inbiome.json at the repo root.
dist,.next,node_modules,migrations— build artifactsstorybook-static— Storybook build outputtest-results,playwright-report— Playwright artifacts**/globals.css— uses modern CSS features (@starting-style,@theme inline) that Biome can’t parse yet
TypeScript Strictness
Everytsconfig.json in the project has strict: true and noUncheckedIndexedAccess: true. This means:
- All function parameters and return types must be explicitly typed
- Array indexing returns
T | undefined— you must narrow with?.or?? - No
anytype, ever — useunknownand narrow, or create a proper type - No
// @ts-ignoreor// @ts-expect-error
Import Rules
- Use path aliases for cross-package imports:
@folksbase/db,@folksbase/types,@folksbase/emails - Within an app, use
@/*alias (e.g.,@/lib/logger.js,@/env.js) - Backend imports must include
.jsextension for ESM compatibility - Never use relative paths crossing package boundaries (
../../packages/dbis forbidden)
Export Rules
- Named exports only — no
export defaultexcept Next.js pages and layouts (framework requirement) - No barrel files (
index.tsre-exporting everything) insideapps/ - Import directly from the source file
Key Conventions
Types
- Use
typeoverinterfaceunless you need declaration merging - Check
@folksbase/typesbefore creating new types — it may already exist - Zod schemas are the source of truth for runtime validation; derive TS types with
z.infer<>
Error Handling
- Never
throwraw strings - API errors follow the
{ code, message, details? }shape from@folksbase/types - Let errors propagate to the global
errorHandlermiddleware — don’t add manual try/catch in route handlers
Logging
- No
console.login production code — ever - Use the structured logger:
import { logger } from "@/lib/logger.js" - Methods:
logger.info(),logger.warn(),logger.error()— all accept(message, extra?)where extra isRecord<string, unknown>
Variables
- Prefer
constoverlet— restructure with ternary or early return when possible - Every
letmust have an explicit type annotation (Biome rule:noImplicitAnyLet) - Don’t shadow restricted names (
Error,Object,Number, etc.) - Use
async/awaitover.then()chains
CSS and Design Tokens
- All colors use oklch-based CSS custom properties from
globals.css - Use Tailwind token classes (
text-gray-10,bg-green-a-3) — never hardcoded hex/hsl or Tailwind defaults likeslate-* - Card containers use the
.cardclass - Error states use token colors (
border-red-a-7,text-red-a-9)
Accessibility
All interactive UI components must include proper ARIA attributes:| Component | Required |
|---|---|
| Dialog | aria-modal, aria-labelledby, aria-describedby |
| Dropdown menu | role="menu" on container, role="menuitem" on items |
| Select | aria-haspopup="listbox", aria-expanded |
| Input (with error) | aria-invalid="true", aria-describedby pointing to error element |
| Icon-only buttons | aria-label describing the action |
| Navigation links | aria-current="page" on active link |
| Table headers | scope="col" on <th> elements |
| Error messages | role="alert" |
Quick Reference: Common Pitfalls
| Pitfall | Fix |
|---|---|
Using any | Use unknown and narrow |
console.log | Use logger.info/warn/error |
process.env.X | Import env from @/env or @/env.js |
Non-null assertion (!) | Use ??, ?., or explicit null check |
let without type | Add explicit type or use const |
| Hardcoded colors | Use oklch design tokens |
| Missing ARIA attributes | See accessibility table above |