Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Common Gotchas

Known pitfalls for developers and AI agents working in the GrantMaster codebase. These are enforced by ESLint rules, convention, or hard-won experience.

Collection Name Mismatches

The Firestore collection name does not always match the domain concept. These trip up everyone:
Collection NameStoresDomain Feature
employeesUser documentsUsers / HR
timesheetsJournalEntry documentsJournals / Time Tracking
retrospectivesMonthlyJournalSubmission documentsJournal Submissions
Always check src/core/firestoreCollections.ts for the canonical mapping.

Deprecated APIs

DeprecatedUse InsteadNotes
useValidatedFormuseZodForm from @/hooks/useZodFormProvides schema validation, toast notifications, handleSubmit, isSubmitting, isDirty
useOrganizationuseTenant() from @/contexts/TenantContextCanonical way to access org context

Styling Rules (ESLint-enforced)

The no-legacy-tailwind-palette rule blocks builds if you use wrong color tokens:
Never UseUse InsteadSemantic Role
gray-*slate-*Neutral palette
green-*emerald-*Success states
red-*rose-*Error states
blue-* for primaryprimary-*Primary actions
amber-*Warning states
Dark mode backgrounds: Use dark:bg-{color}-500/10 for subtle tints.

Component Rules (ESLint-enforced)

These rules prevent design system bypass:
RuleWhat It BlocksUse Instead
no-raw-button-with-design-systemRaw <button> with inline classes<Button> from @/components/ui/button
no-raw-text-input-with-design-systemRaw <input> / <textarea><Input> / <Textarea> from @/components/ui/
no-status-badge-bypassCustom status badges<StatusBadge> from @/components/ui/StatusBadge
Always use mapDomainStatus() to convert domain strings (e.g. 'approved') to the 6 base StatusType values before passing to <StatusBadge>.

Architecture Rules (ESLint-enforced)

RuleWhat It BlocksCorrect Pattern
no-direct-firestore-importImporting Firestore directlyUse typed refs from src/core/firestoreCollections.ts
no-direct-onsnapshotCalling onSnapshot directlyUse the service layer
no-eventbus-in-componentsEventBus usage in React componentsEmit events only from services
require-firestore-limitFirestore queries without limit()Always add explicit limit() to every query
no-derived-stateStale derived state patternsCompute derived values during render
prefer-typed-firestore-refsUntyped collection referencesUse canonical refs from firestoreCollections

Port Conflicts

These ports are hardcoded and must not be changed:
ServicePortNotes
Vite Dev Server3000Hardcoded for Firebase integration — never change
Firebase Emulator UI4000
Functions Emulator5001
Firestore Emulator8080
Auth Emulator9099
Storage Emulator9199
Never start Firebase emulators or Vite dev server directly — ask the user if they’re already running to avoid port conflicts.

UI Conventions

Common mistakes when building pages:
  • Always wrap page content in <PageLayout> — never build page structure manually
  • Always use <PageHeader> for page titles — never manual <h1>
  • Always use <PageTabs> and render tab content externally — never pass content via the tab’s content prop
  • Always derive major-section tab state from the router — never keep /overview, /onboarding, /AI, or /workflow tab selection in shared component state
  • Always keep breadcrumbs and titles distinct — breadcrumbs show ancestors, title shows the active page/tab once
  • Always use <SecondarySidebar> for left-side navigation — never build custom sidebar navs inline
  • Icons: lucide-react only. Sizes: w-4 h-4 (buttons/badges), w-5 h-5 (headers), w-8 h-8 (stat cards)
  • Use cn() from @/lib/utils for class merging — never string concatenation

Provider Hierarchy

The provider order matters. Three tiers:
  1. GlobalProviders — auth, theme, i18n, query client
  2. DomainProviders — tenant, notifications, feature flags
  3. FeatureProviders — feature-specific contexts (wrapped at route level)
Adding a provider at the wrong tier can cause missing context errors or unnecessary re-renders.

Forms

  • Use useZodForm (not useValidatedForm) — see Deprecated APIs above
  • Zod schemas live in src/schemas/ for shared schemas or src/features/[feature]/types/ for feature-specific
  • Use FormFieldController from useZodForm for controlled inputs
  • Use <FormSection>, <FormGrid>, <FormField>, <FormActions> for layout — never build form layouts manually