- All exports must be named exports. Default exports are forbidden except for Next.js page.tsx and layout.tsx files.
- Import statements must use named imports:
import { Button } from '@/components/Button'neverimport Button from '@/components/Button' - Re-export barrels must use
export { ComponentA } from './ComponentA'syntax, neverexport { default as ComponentA }
- React components live in
/app/components/with PascalCase filenames:UserCard.tsx,LoginForm.tsx - Server components must have
.server.tsxsuffix:UserList.server.tsx - Client components must have
.client.tsxsuffix:SearchInput.client.tsx - Utility functions live in
/lib/with camelCase filenames:formatDate.ts,validateEmail.ts - API routes live in
/app/api/following Next.js App Router structure:/app/api/users/route.ts - Database queries live in
/lib/db/with camelCase filenames:getUser.ts,createPost.ts - Hooks live in
/lib/hooks/with camelCase filenames prefixed withuse:useAuth.ts,usePagination.ts - Tests live adjacent to source files with
.test.tsor.test.tsxsuffix:Button.test.tsxnext toButton.tsx
- Fetch data in Server Components only. Never use
useEffectfor data fetching in Client Components. - Async Server Components must render
<Suspense>boundaries with explicit fallback UI:<Suspense fallback={<LoadingSpinner />}><UserList /></Suspense> - Every async Server Component must have a
.server.tsxsuffix and must export an async function. - Client Components that need data must receive it as props from Server Component parents.
- Use
fetch()with{ cache: 'force-cache' }or{ cache: 'no-store' }explicitly set — never omit cache option.
- Database clients must be imported from
/lib/db/client.tssingleton, never instantiated inline. - Supabase client must be imported from
/lib/supabase/client.tsfor client-side or/lib/supabase/server.tsfor server-side. - All database queries must be in
/lib/db/functions, never raw queries in components or API routes. - API routes must call database functions from
/lib/db/, never instantiate clients directly.
- Never use
anytype. Useunknownand type guard it, or use Zod.parse()for runtime validation. - Never use
astype assertions outside of.test.tsfiles. Use type guards or discriminated unions instead. - Function parameters must have explicit types:
function getName(user: User): stringnotfunction getName(user) - React component props must be typed with interfaces:
interface ButtonProps { label: string; onClick: () => void }not inline types. - API request/response bodies must be validated with Zod schemas in
/lib/schemas/:const UserSchema = z.object({ id: z.string(), name: z.string() })
- Environment variables must be declared in
.env.local(git-ignored) and.env.example(git-tracked with placeholder values). - Client-side environment variables must be prefixed with
NEXT_PUBLIC_only. All other env vars are server-only. - Never hardcode API keys, database URLs, or tokens in any file. Use environment variables exclusively.
- Never log environment variables or secrets. If logging user data, redact sensitive fields.
- API keys must never appear in Client Components. Pass data through API routes instead.
- Every async function must have try/catch. Caught errors must be typed:
catch (err) { if (err instanceof AppError) { ... } } - Never catch with
catch (e: any)or barecatch (e). Always type the error. - API routes must return structured error responses:
{ error: string; code: string; statusCode: number } - Errors must be logged to
/lib/logger.tswith context:logger.error('User fetch failed', { userId, error }) - Client Components must display error states explicitly:
{error && <ErrorBoundary error={error} />}
- Every async Server Component must have a loading state. Use
<Suspense fallback={<Skeleton />}> - Every data list must have an empty state:
{items.length === 0 ? <EmptyState /> : <ItemList items={items} />} - Every form submission must show loading state:
<button disabled={isLoading}>{isLoading ? 'Saving...' : 'Save'}</button> - Pagination components must show current page and total count:
Page {currentPage} of {totalPages}
- All form inputs must be validated with Zod schemas before submission.
- API route handlers must validate request bodies:
const data = UserSchema.parse(req.body) - URL search parameters must be validated:
const page = z.coerce.number().parse(searchParams.page) - Never trust user input. Validate at the boundary (API routes, form handlers).
- Client Components must use
'use client'directive at the top of the file. - Server Components must never import Client Components directly. Use composition with children prop.
- Components larger than 300 lines must be split into smaller components in a subdirectory.
- Prop drilling deeper than 3 levels requires context or state management, never pass through 4+ levels.
- Every utility function in
/lib/must have a.test.tsfile with minimum 80% line coverage. - Every API route must have a
.test.tsfile testing success and error paths. - Component tests must use React Testing Library, never Enzyme or Snapshot testing.
- Tests must use
describe()blocks organized by function:describe('formatDate', () => { it('formats ISO dates', () => {...}) }) - Mock external services (Supabase, APIs) with Jest mocks in test files, never in source code.
- Never use
/pagesdirectory. All routes must be in/appdirectory. - Route segments must use lowercase with hyphens:
/app/user-profile/page.tsxnot/app/UserProfile/page.tsx - Dynamic routes must use bracket syntax:
/app/posts/[id]/page.tsxnot/app/posts/:id/page.tsx - Layout files must be named
layout.tsxand wrap all child routes. - Metadata must be exported from
layout.tsxorpage.tsx:export const metadata = { title: '...' }
- Use
/lib/logger.tsfor all logging. Never useconsole.log()in production code. - Log levels must be:
logger.debug(),logger.info(),logger.warn(),logger.error() - Every error log must include context object:
logger.error('message', { userId, action, error }) - Remove all
console.log()statements before committing. Use linter rule to enforce.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>