Skip to main content

Development Rules

Naming

  • Use explicit names that describe the owning domain or responsibility.
  • Avoid generic filenames such as utils.ts, data.ts, myFunctions.ts, or server.ts for real product logic.
  • Prefer names such as access.ts, directory.ts, profile.ts, billing.ts, or supportHandoff.ts.

Route Ownership

  • Keep route files thin.
  • Keep the page body in page.tsx by default.
  • Keep supporting route-local code under the owning route tree in _components/*, _hooks/*, and _lib/*.
  • Promote code into app-shared folders only when reuse across surfaces is proven.

Surface Boundaries

  • apps/app owns authenticated product surfaces: org, portal, and platform.
  • apps/marketing owns optional public marketing pages.
  • Different surfaces may intentionally diverge in layout, navigation, theming, density, and UX.
  • Do not flatten those differences into a forced shared structure.

Imports

  • Use @/ for cross-boundary imports inside apps/app.
  • Use relative imports only for tightly-coupled local files.
  • Do not deep-import another route tree's private internals.
  • Do not use long relative climbs across boundaries.

Convex

  • Author all backend modules in packages/backend/convex/**.
  • Use @convex/* only from app-side code that consumes generated backend references.
  • apps/app/convex is generated-only and must not become a second backend root.
  • Keep runtime-global Convex root files limited to auth.ts, auth.config.ts, http.ts, crons.ts, and schema.ts.

Shared Code

  • Start app-local.
  • Promote to packages/* only when reuse is real or the module is clearly repo-wide infrastructure.
  • Use the rule of two for DRY extraction: extract only after duplication exists in active code.

Shared State And Interactive Ownership

  • Mount one controller provider for persistent operational state shared across a shell. Pages, dialogs, topbars, and docks consume that owner instead of instantiating parallel stateful hooks.
  • Keep providers for disjoint org, portal, and platform branches separate.
  • Build adjacent actions with ButtonGroup; never overlay a parent-owned button on another component's interactive bounds.
  • Mark genuine coordinate-space controls with data-interactive-overlay, keep decorative overlays pointer-transparent, and use semantic z-index utilities.
  • Run pnpm --filter @starter/app architecture:guard after changing providers, compound controls, overlays, or stacking.

Directory Hygiene

  • Remove empty folders that no longer carry active responsibility.
  • Keep shared folders small and intentional.
  • Put route-owned hooks in _hooks and non-component models, schemas, and types in _lib.
  • Use responsibility folders such as dialogs, editor, navigation, or sections when three or more related components make a flat _components directory hard to scan.
  • Use concrete support filenames instead of generic types.ts, schemas.ts, model.ts, or helpers.ts.
  • Do not leave archived client docs in the live starter folders.

Documentation

  • docs/app/README.md is the app-docs entrypoint.
  • docs/dev/README.md is the developer-docs entrypoint.
  • docs/app should teach the starter kit, not a client implementation.
  • Client-specific material should not live in docs/app; keep starter docs product-agnostic and move temporary client notes into non-source-of-truth working docs outside docs/app.
  • When docs move, update references in the same change.
  • When instructions change under .__ai-rules/*, run pnpm sync:agents in the same change.