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.

Feature Development Checklist

Step-by-step checklist for adding a new feature end-to-end. Canonical example: src/features/expenses/.

Checklist

1. Folder Structure

Create the feature directory with standard subfolders:
src/features/[name]/
├── components/
│   └── pages/          # Page-level components
├── hooks/              # Custom React hooks
├── services/           # Service classes (extend BaseService)
├── types/              # TypeScript types and interfaces
├── constants/          # Feature constants and enums
├── [Name]Context.tsx   # Feature context provider
├── modals.registry.ts  # Modal definitions
├── pages.config.ts     # Page definitions (if using page system)
├── index.ts            # Barrel export (public API)
└── [name].md           # Feature documentation

2. Barrel Export

Create src/features/[name]/index.ts exporting only the public API:
export { MyFeatureProvider, useMyFeature } from './MyFeatureContext';
export type { MyEntity } from './types/myEntity.types';

3. Types

Create src/features/[name]/types/[name].types.ts:
  • Define the core entity type
  • Add Zod schemas for validation (read schema with graceful degradation, write schema strict)
  • Export from barrel

4. Firestore Collection

Add typed collection reference in src/core/firestoreCollections.ts. Reminder: Collection names may not match the domain concept — see Common Gotchas.

5. Service

Create src/features/[name]/services/[Name]Service.ts:
import { BaseService, type ServiceResult } from '@/core/BaseService';

export class MyService extends BaseService<MyEntity> {
  protected collectionName = 'myEntities';
  protected serviceName = 'MyService';

  async create(entity: MyEntity, userId: string): Promise<ServiceResult<MyEntity>> {
    return this.withErrorBoundary(
      async () => {
        this.validateInput(entity);
        // ... Firestore write
        this.logSuccess('CREATE', entity.id, userId);
        return entity;
      },
      { operation: 'create', entityId: entity.id }
    );
  }
}

6. Context Provider

Create src/features/[name]/[Name]Context.tsx:
  • Use React Context for feature-level state
  • Use React Query for server state
  • Export useMyFeature() hook for consuming components

7. Page Component

Create page in src/features/[name]/components/pages/[Name]Page.tsx:
import { PageLayout } from '@/components/ui/PageLayout';
import { PageHeader } from '@/components/ui/PageHeader';

export function MyPage() {
  return (
    <PageLayout>
      <PageHeader title="My Feature" />
      {/* content */}
    </PageLayout>
  );
}

8. Route Registration

Add route in the appropriate file under src/routes/config/:
import { createLazyRoute } from '../routeLazy';

{
  path: 'my-feature',
  lazy: createLazyRoute(
    () => import('@/features/myFeature/components/pages/MyPage'),
    (mod) => mod.MyPage ?? mod.default,
  ),
}

9. Navigation

Add sidebar nav item in src/components/layout/navConfig.ts with path, label, icon, and optional permission.

10. Modal Registration

Create src/features/[name]/modals.registry.ts:
import type { ModalDef } from '@/components/modals/modal.types';

export const myModals: ModalDef[] = [
  {
    id: 'my-modal',
    component: () => import('./components/MyModal'),
    select: (mod) => mod.MyModal ?? mod.default,
    size: 'lg',
    variant: 'modal',
    scope: 'feature',
  },
];

11. EventBus Events

Emit events from services for significant state changes:
  • Approval/rejection workflows
  • Entity lifecycle (created, archived, deleted)
  • Critical thresholds (budget limits, deadlines)
  • Compliance events
Do NOT emit for: read operations, trivial updates, internal optimizations. See: Base Service and EventBus

12. Provider Hierarchy

If your feature needs a context provider at the app level:
  1. Add to the appropriate tier (usually FeatureProviders)
  2. Wrap at the route level if the provider is route-scoped

13. Unit Tests

Create colocated test files: src/features/[name]/services/[Name]Service.test.ts
  • 60% coverage threshold
  • Use Vitest with jsdom environment for DOM testing
  • Run: npm run test

14. Feature Documentation

Create src/features/[name]/[name].md with:
  • Purpose and overview
  • Data model (Firestore collections, TypeScript types)
  • Key behaviors
  • Service contracts
  • EventBus events (emitted and consumed)
  • Dependencies and file structure
Follow the pattern in src/features/expenses/expenses.md.