Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save maxforbang/53a995870d49e952acfdecd9afffd4a6 to your computer and use it in GitHub Desktop.

Select an option

Save maxforbang/53a995870d49e952acfdecd9afffd4a6 to your computer and use it in GitHub Desktop.

Role

You are a world-class software engineer.

Task

Create a plan for how we're going to make sure our codebase is already well documented, especially for AI Agents.

Follow engineering best principles when working with coding agents like Cursor and Claude Code.

Specifics

  1. Create a live, dynamic document that will keep track of all of our progress for each domain and their current state so we know when to incrementally adopt the next phase of our DDD / hexagonical architecture for each bounded context.

  2. Create a .cursor/rules or appropriately-placed .mdc markdown file that will inform the agent to follow these principles as we build out our implementation based on what you just said @DDD Incremental Adoption SOP.md and make sure it refers to the first document you created which has to current state of each bounded context.

  3. Suggest any other documentation practices we should follow, including any other cursor rules for how to keep the documentation itself updated. Take inspiration from the Arseny AI Coding Workflow and his example markdown files but modified so they're specific to our codebase.

Think through this step by step.

Arseny AI Coding Workflow

Summary

@AI Coding Workflow.md


  

## 1. Philosophy: You Run the Project, Not the AI

  

* The main failure mode of “AI coding” is letting agents freely edit the codebase until it becomes an unmaintainable mess.

* Your goal is to **constrain** the AI with architecture, types, and tests so it behaves like a powerful but supervised junior team, not an autonomous chaos machine.

* Think of yourself as the **architect + tech lead**: AI writes most code; you design the system, define boundaries, and enforce quality.

  

---

  

## 2. Levels of AI Coding Autonomy

  

The video frames AI coding as four levels:

  

* **L0 – Manual**: Humans write all code.

* **L1 – Human-assisted**: Autocomplete and small snippets, occasional “write a function for me.”

* **L2 – Human-monitored (“vibe coding”)**: AI does most of the work in the IDE; human continuously watches, guides, and fixes.

* **L3 – Human out-of-the-loop (“agentic coding”)**: Background agents take tasks from spec to PR; humans mainly review.

  

Key principle:

  

* **Do not jump straight to L3.** First build solid practices at L1/L2:

  

* Good architecture

* Types/interfaces

* Tests

* Conventions for prompting and supervision

* L3 only works if L2 is already disciplined and predictable.

  

---

  

## 3. Core Project Artifacts to Anchor the AI

  

The workflow centers on four key files stored inside the repo (version-controlled):

  

1. **PRD (Product Requirements Document)**

  

* Describes what the feature/system should do, for whom, and why.

* Used by the AI to scope tasks and understand behavior, not UI fluff.

  

2. **Project Structure Specification**

  

* Defines folders, layers, domains, and how components interact.

* Makes clear where new modules, services, handlers, etc. should live.

  

3. **ADR (Architecture Decision Records)**

  

* Short documents capturing **important decisions** and **why** they were made.

* Include tradeoffs, known limitations, and “gotchas” encountered during implementation.

* These are the *memory* for future agents to avoid repeating mistakes.

  

4. **AI Coding Workflow / Rules File**

  

* Explicit instructions to the AI about **how to work in this repo**:

  

* Steps to follow when implementing a feature

* How to use types and tests

* Where to document things

* How to run and interpret tests

* This is the “playbook” your agents must follow every time.

  

---

  

## 4. Step-by-Step AI Coding Workflow

  

### Step 1: Plan Architecture Before Any Code

  

* For each major feature or system:

  

* Use the LLM to interview you and fill out a **PRD**.

* Use the PRD to derive:

  

* Data flow

* Domain boundaries

* Key modules/services

* Events/jobs/background processes, if any

* Break down the PRD into **small, explicit tasks** that:

  

* Reference concrete file paths and modules

* Specify inputs/outputs

* Describe dependencies between tasks

  

Result: The AI doesn’t invent structure on the fly; it fits into a pre-defined architecture.

  

---

  

### Step 2: Define Types First

  

* Before implementation, have the AI **define all relevant types**:

  

* Request/response DTOs

* Domain models

* Persistence/DB models

* Component props and state shapes

* Event payloads, job payloads, etc.

* Principle: **Types are guardrails**:

  

* They reduce hallucinations by forcing the model to respect a schema.

* Static analysis and linters will immediately flag mismatches.

  

You want the AI to code “through” the types rather than improvising data structures.

  

---

  

### Step 3: Write Tests Before Implementation (or Very Early)

  

* While context is still fresh (after PRD + types), instruct the AI to:

  

* Write **tests that express the behavior** of the new feature:

  

* Integration/E2E tests for end-to-end behavior

* Unit tests where appropriate

* Prioritize:

  

* Integration tests that hit real code paths and real APIs (or realistic local equivalents), not just mocks.

* Tests + types + architecture = **rails** that make it hard for the AI to go off-track.

  

Later, you can refactor heavy integration tests into smaller unit tests if needed.

  

---

  

### Step 4: Implement the Feature with Supervised Agents

  

* Now let the AI implement tasks, guided by:

  

* PRD

* Project structure

* Types

* Tests

* AI workflow file

* Use **information-dense commands** when prompting, e.g.:

  

* “Implement: [task name]. Update [file paths]. Add tests at [test file path].”

* Run multiple agents in parallel **only** when:

  

* Tasks clearly touch different areas of the codebase.

* Dependencies are resolved in the right order.

* Your role:

  

* Monitor agent work intermittently.

* Focus on reviewing **tests and key modules**, not every line of code.

* Use version-control diffs to see what each agent changed.

  

---

  

### Step 5: Close the Loop with Tests and Documentation

  

* **Always** have the AI:

  

* Run the tests itself (don’t manually run then paste errors).

* Fix failing tests until green.

* Update or add **ADR entries** for:

  

* Major changes

* Tricky bugs and their solutions

* Important constraints or assumptions

* ADRs act as **long-term memory**:

  

* Future agents must be instructed to read relevant ADRs before modifying that area of the codebase.

  

---

  

## 5. Prompting & Context Management Principles

  

1. **Use information-dense verbs.**

  

* Prefer: “Implement X in Y file; update Z; add test at T”

* Avoid vague prompts like: “Make this better” or “Improve order total logic.”

  

2. **Think about what the AI can actually see.**

  

* Ask yourself: “Could *I* do this task with only this context?”

* If not:

  

* Provide additional files or docs.

* Or reduce the scope of the task.

  

3. **Avoid both starvation and overload.**

  

* Too little context → hallucinations and guesswork.

* Too much, uncurated context → the model misses critical details.

  

4. **Use the smallest capable model for each task.**

  

* Small/fast models: quick edits, refactors, simple tests, micro-tasks.

* Stronger models: scoping, architecture, non-trivial refactors, multi-step reasoning.

* Heaviest models: background/agentic flows only when you know the task can be one-shot safely.

  

5. **Keep templates & rules inside the repo.**

  

* PRD template, task template, ADR template, and AI workflow rules all live in version control.

* This keeps the system transparent and modifiable, instead of burying behavior in opaque SaaS prompts.

  

---

  

## 6. Production Pitfalls & How to Avoid Them

  

1. **Never connect AI directly to production.**

  

* Use a **staging/sandbox environment**:

  

* Same infrastructure & config as production, but with non-production data.

* Restrict any destructive operations to non-production environments.

  

2. **Avoid the “accept all” trap.**

  

* Do **not** blindly accept every AI change:

  

* Review tests and critical paths.

* Be especially careful with security, auth, and data access.

* Consider using frameworks or patterns that centralize security/auth so the AI can’t easily bypass them.

  

3. **Prevent technical-debt explosions (“no broken windows”).**

  

* Add a rule to the workflow: **“No broken windows”**:

  

* If the AI sees code that’s obviously bad or inconsistent (within the scope it touches), it should improve it as part of the change.

* Don’t merge half-finished or obviously messy code “just for now”; that pattern compounds.

  

4. **Avoid over-layering frameworks on top of AI tools.**

  

* Stacking complex prompt frameworks on top of IDE agents makes behavior harder to steer.

* Prefer:

  

* A thin, explicit workflow (the 4 files)

* Direct use of your coding agents (Cursor, Claude Code, etc.)

* The more layers of prompts you add, the less control you have.

  

---

  

## 7. How an LLM Should Use This in Your Codebase

  

When this summary is used as context for your own LLM/agents, they should:

  

* Always:

  

* Read PRD + relevant ADRs + project structure before large changes.

* Define or update types before writing implementation code.

* Write and run tests first (or very early), aiming for integration-level coverage.

* Document key decisions in ADRs after significant work.

* Operate in a **task-based, dependency-aware** way:

  

* Break work into small, file-specific tasks.

* Run tasks in parallel only if dependencies allow and code areas don’t overlap.

* Treat staging/sandbox environments as the only place for automated destructive changes.

* Respect “no broken windows”: leave touched code cleaner than they found it.

  

---

  

Learn more on Glasp: [https://glasp.co/reader?url=https://www.youtube.com/watch?v=3myosgzKvZ0](https://glasp.co/reader?url=https://www.youtube.com/watch?v=3myosgzKvZ0)

Example Markdown Files

AGENTS.MD


AI rules are located in the following directories:

  

- **@.cursor/rules/** — Project-wide rules and documentation, such as:

  

- `PRD.mdc` (Product Requirements Document)

- `ADR.mdc` (Architecture Decision Records)

  

- **@back/.cursor/rules/** — Backend-specific rules and structure, including:

  

- `backend-workflow.mdc` (Backend development workflow)

- `folder-structure.mdc` (Backend folder organization)

- `ADR.mdc` (Backend architecture decisions)

  

- **@front/.cursor/rules/** — Frontend-specific rules and structure, including:

- `frontend-workflow.mdc` (Frontend development workflow)

- `folder-structure.mdc` (Frontend folder organization)

- `ADR.mdc` (Frontend architecture decisions)

tasks/task-template.mdc


---

description:

globs:

alwaysApply: false

---

  

# INSTRUCTIONS — READ THIS FIRST WHEN CREATING NEW TASKS

  

This file is a single, self-contained TASK for an AI agent. **One task = one file.**

Follow the steps below when creating new tasks.

  

1. **Name your file**: place under `./tasks/` and use kebab-case, e.g., `tasks/add-bar-chart.md`.

2. **Fill the frontmatter** (above) completely. Keep `title`, `status`, and `owner` accurate.

3. **Use information-dense keywords** throughout (exact file paths, function signatures, type names, constants, CLI flags).

4. **Define types first** if adding new data structures. Reference those types by exact name in later steps.

5. **Order your steps** so later steps explicitly reference earlier artifacts by name (files, types, functions).

6. **Keep scope tight**: this task should be completable independently. If it’s large, split into multiple task files and add them to `dependencies`.

7. **Acceptance criteria** must be testable and unambiguous. Include file paths for tests and example CLI/API usage.

8. **Context plan** must list the files to add to the model’s context at the start (mark dep files read-only) and which files must exist at the end.

9. **Testing strategy** use primarily integration tests, calling real APIs. No useless unit tests that just test the properties of the class. No tests for front end.

  

---

  

id: "<unique-id-or-ticket>" # e.g., TASK-0123

title: "<short, action-oriented task title>" # e.g., "Add quartile-colored bar chart"

status: "planned" # planned, in-progress, blocked, done

priority: "P1" # P0, P1, P2

labels: ["feature", "cli", "charts"] # free-form tags

dependencies: ["<other-task-file>"] # list other task files that must be completed first

created: "YYYY-MM-DD"

  

# 1) High-Level Objective

  

<One sentence that describes the user-facing end state. Avoid technical jargon.>

  

# 2) Background / Context (Optional but recommended)

  

<Short rationale or business context for why this task exists. Link any tickets/PRDs.>

  

# 3) Assumptions & Constraints

  

- ASSUMPTION: <If any info is missing, state the pragmatic assumption here.>

- Constraint: <e.g., “Use only deps listed in package.json/pyproject.toml”.>

- Constraint: <e.g., “Prefer TypeScript for app, Python for scripts”.>

  

# 4) Dependencies (Other Tasks or Artifacts)

  

- tasks/<other-task-file>.md

- files/<required-existing-file-or-schema>

  

# 5) Context Plan

  

**Beginning (add to model context):**

  

- src/main.ts

- src/types.ts

- package.json _(read-only)_

- pyproject.toml _(read-only)_

  

**End state (must exist after completion):**

  

- src/charts/bar.ts

- src/charts/index.ts

- tests/charts/bar.test.ts

  

# 6) Low-Level Steps (Ordered, information-dense)

  

> Write concrete, atomic steps. Include **file paths, exact names, signatures, params with defaults, return types**.

  

1. **Create bar chart module**

  

- File: `src/charts/bar.ts`

- Exported API:

\```ts

export type WordCounts = Record<string, number>; // or import from src/types.ts

export function renderQuartileBarChart(

counts: WordCounts,

options?: { minCount?: number; outputPath?: string }

): Promise<void>;

\```

- Details:

- Filter out entries with `count < options.minCount ?? 10`

- Sort desc, keep top 100

- Color top quartile green, bottom red, remaining blue

- Write PNG to `options.outputPath ?? "charts/word_freq_bar.png"`

  

2. **Re-export in index**

  

- File: `src/charts/index.ts`

- Add: `export * from "./bar";`

  

3. **CLI wire-up**

  

- File: `src/main.ts`

- Add flag `--chart-type bar`, and when selected, call:

\```ts

await renderQuartileBarChart(result.counts, {

minCount: flags.minCount,

outputPath: flags.output,

});

\```

- Update help text accordingly.

  

4. **Tests**

- File: `tests/charts/bar.test.ts` (Jest)

- Cases:

- Renders without error with mixed frequencies

- Respects `minCount` filter

- Produces output file path when provided

  

# 7) Types & Interfaces (if applicable)

  

> Define or reference types here so the model has a stable contract.

  

\```ts

// src/types.ts

export interface TranscriptAnalysis {

summary: string;

keywords: string[];

}

export type WordCounts = Record<string, number>;

\```

  

# 8) Acceptance Criteria

  

- `src/charts/bar.ts` exports `renderQuartileBarChart(...)` with the exact signature above.

- Running `uv run main --chart-type bar --output charts/out.png` writes a PNG file.

- All tests in `tests/charts/bar.test.ts` pass locally.

  

# 9) Testing Strategy

  

- Create an integration test that draws a quartile bar chart and writes it to a file.

- Run the test and ensure the file exists.

- Integrate into the existing end-to-end tests.

  

# 10) Notes / Links

  

- Reference spec section: <link or section name>

- Related tasks: <list others>

  

front/.cursor/rules/ADR.mdc


---

description: Architectural Decision Records

globs:

alwaysApply: false

---

  

# Architecture Decision Log

  

<!--

ADR_AGENT_PROTOCOL v1.0

  

You (the agent) manage this file as the single source of truth for all ADRs.

  

INVARIANTS

- Keep this exact file structure and headings.

- All ADR entries use H2 headings: "## ADR-XXXX — <Title>" (4-digit zero-padded ID).

- Allowed Status values: Proposed | Accepted | Superseded

- Date format: YYYY-MM-DD

- New entries must be appended to the END of the file.

- The Index table between the INDEX markers must always reflect the latest state and be sorted by ID desc (newest on top).

- Each ADR MUST contain: Date, Status, Owner, Context, Decision, Consequences.

- Each ADR must include an explicit anchor `<a id="adr-XXXX"></a>` so links remain stable.

  

HOW TO ADD A NEW ADR

1) Read the whole file.

2) Compute next ID:

- Scan for headings matching: ^## ADR-(\d{4}) — .+$

- next_id = (max captured number) + 1, left-pad to 4 digits.

3) Create a new ADR section using the “New ADR Entry Template” below.

- Place it AFTER the last ADR section in the file.

- Add an `<a id="adr-XXXX"></a>` line immediately below the heading.

4) Update the Index (between the INDEX markers):

- Insert/replace the row for this ADR keeping the table sorted by ID descending.

- Title in the Index MUST link to the anchor: [<Title>](#adr-XXXX)

- If this ADR supersedes another: set “Supersedes” in this row, and update that older ADR:

a) Change its Status to “Superseded”

b) Add “Superseded by: ADR-XXXX” in its Consequences block

c) Update the older ADR’s Index row “Superseded by” column to ADR-XXXX

5) Validate before saving:

- Exactly one heading exists for ADR-XXXX

- All required fields are present and non-empty

- Index contains a row for ADR-XXXX and remains properly sorted

6) Concurrency resolution:

- If a merge conflict or duplicate ID is detected after reading: recompute next_id from the current file state, rename your heading, anchor, and Index row accordingly, and retry once.

  

COMMIT MESSAGE SUGGESTION

- "ADR-XXXX: <Short Title> — <Status>"

  

END ADR_AGENT_PROTOCOL

-->

  

## Index

  

<!-- BEGIN:ADR_INDEX -->

  

| ID | Title | Date | Status |

| --- | -------------------------------------------- | ---------- | -------- |

| 009 | Testing Strategy - Firebase Emulator Support | 2024-08-23 | Accepted |

| 008 | TypeScript Configuration | 2024-08-23 | Accepted |

| 007 | Project Structure - Essential Files Only | 2024-08-23 | Accepted |

| 006 | Hook Patterns - Status Enum Approach | 2024-08-23 | Accepted |

| 005 | Firebase Initialization Strategy | 2024-08-23 | Accepted |

| 004 | Form Handling - React Hook Form + Yup | 2024-08-23 | Accepted |

| 003 | Firebase Security - Remove App Check | 2024-08-23 | Accepted |

| 002 | State Management - React Context over Jotai | 2024-08-23 | Accepted |

  

<!-- END:ADR_INDEX -->

  

## ADR-002: State Management - React Context over Jotai

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

The original codebase used Jotai for state management, but we needed to simplify the template for broader adoption.

  

### Decision

  

Use React Context API instead of Jotai atoms for authentication state management.

  

### Rationale

  

- Reduces external dependencies

- Built into React - no additional learning curve

- Sufficient for authentication state needs

- Easier to understand for developers new to the codebase

- Maintains compatibility with existing patterns

  

### Consequences

  

- Less performant than Jotai for complex state scenarios

- More boilerplate code required

- Limited to simple state management patterns

  

---

  

## ADR-003: Firebase Security - Remove App Check

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

App Check with reCAPTCHA was included in the original setup but adds complexity to the template.

  

### Decision

  

Remove Firebase App Check and reCAPTCHA integration from the template.

  

### Rationale

  

- Simplifies initial setup and development

- Reduces dependencies

- App Check can be added later when needed for production

- Template focuses on core functionality

- Easier testing during development

  

### Consequences

  

- Less security protection out of the box

- Users need to implement App Check separately for production

- Potential for abuse during development phase

  

---

  

## ADR-004: Form Handling - React Hook Form + Yup

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Forms are essential for authentication and data input in web applications.

  

### Decision

  

Use React Hook Form with Yup for validation.

  

### Rationale

  

- Performance benefits from uncontrolled components

- Built-in validation support

- TypeScript integration

- Minimal re-renders

- Yup provides comprehensive validation schemas

- Industry standard approach

  

### Consequences

  

- Additional dependencies to manage

- Learning curve for form-specific patterns

- More setup required for complex forms

  

---

  

## ADR-005: Firebase Initialization Strategy

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Firebase initialization needed to handle server-side rendering and missing credentials gracefully.

  

### Decision

  

Implement conditional Firebase initialization with fallback empty objects.

  

### Rationale

  

- Prevents SSR errors during build time

- Graceful handling of missing credentials

- Allows template to build successfully without Firebase setup

- Clear error messages when credentials are missing

  

### Implementation

  

\```typescript

let firebaseApp: FirebaseApp | undefined;

if (FIREBASE_CONFIG.apiKey) {

firebaseApp = initializeApp(FIREBASE_CONFIG);

}

export const auth = firebaseApp ? getAuth(firebaseApp) : ({} as Auth);

\```

  

### Consequences

  

- Additional conditional checks required

- Potential runtime errors if Firebase methods are called without proper initialization

- More complex initialization logic

  

---

  

## ADR-006: Hook Patterns - Status Enum Approach

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Needed consistent patterns for data fetching hooks across the application.

  

### Decision

  

Use status enum (`"loading" | "error" | "success"`) pattern instead of separate boolean states.

  

### Rationale

  

- Matches existing codebase patterns

- Prevents impossible states (loading + error)

- More maintainable than multiple boolean flags

- Clear state transitions

- Better TypeScript inference

  

### Implementation

  

\```typescript

const [status, setStatus] = useState<"loading" | "error" | "success">(

"loading"

);

\```

  

### Consequences

  

- Consistent with existing codebase

- Easier state management

- Clear separation of loading states

  

---

  

## ADR-007: Project Structure - Essential Files Only

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Template needed to be minimal while providing complete Firebase integration.

  

### Decision

  

Include only essential files for Firebase integration and authentication.

  

### Included Components

  

- Firebase services (auth, firestore, storage, functions)

- Authentication system with React Context

- Basic pages (home, signin, signup, dashboard)

- Essential hooks for data fetching

- Material-UI theme configuration

  

### Excluded Components

  

- Complex state management solutions

- Advanced routing patterns

- Non-essential UI components

- Advanced Firebase features (Analytics, Remote Config, etc.)

  

### Rationale

  

- Faster onboarding for new projects

- Easier to understand and modify

- Reduces maintenance burden

- Clear separation of concerns

  

### Consequences

  

- May require additional setup for complex applications

- Users need to add advanced features themselves

- More opinionated structure

  

---

  

## ADR-008: TypeScript Configuration

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Template needed strong typing for Firebase operations and React components.

  

### Decision

  

Use strict TypeScript configuration with comprehensive type definitions.

  

### Features

  

- Strict mode enabled

- Custom type definitions for Firebase documents

- Proper interface definitions for hooks

- Type-safe Firebase operations

  

### Rationale

  

- Better developer experience

- Compile-time error catching

- Self-documenting code

- Industry best practices

  

### Consequences

  

- Steeper learning curve for JavaScript developers

- More verbose code in some cases

- Additional type maintenance required

  

---

  

## ADR-009: Testing Strategy - Firebase Emulator Support

  

**Status:** Accepted

**Date:** 2024-08-23

  

### Context

  

Development and testing needed to work without affecting production Firebase resources.

  

### Decision

  

Include Firebase emulator configuration for local development.

  

### Implementation

  

- Emulator configuration in firebase.json

- Environment-based Firebase initialization

- Test mode Firestore rules

  

### Rationale

  

- Safe local development

- Faster iteration cycles

- Cost-effective testing

- Offline development capability

  

### Consequences

  

- Additional setup required

- Emulator-specific behaviors may differ from production

- Need to manage emulator lifecycle

  

---

  

## Future ADRs

  

The following decisions may be documented in future ADRs:

  

- Authentication provider selection

- Deployment strategy

- Error handling patterns

- Performance optimization approaches

- Security rule implementations

- Monitoring and analytics integration

front/.cursor/rules/folder-structure.mdc


---

alwaysApply: true

---

  

# Next.js Firebase Template - Project Structure

  

This project follows a modular architecture pattern for Next.js applications with Firebase integration and Material-UI components.

  

## Folder Structure

  

### `src/` - Source Code

  

#### Core Directories

  

- **app/** - Next.js App Router

- **layout.tsx** - Root layout with providers

- **page.tsx** - Home page

- **(authenticated)/** - Protected routes (requires auth)

- **(public)/** - Public routes (signin, signup, etc.)

- **api/** - API routes (if needed)

  

- **components/** - Reusable UI Components

- **common/** - Shared components (LoadingScreen, SplashScreen, EmptyContent)

- **forms/** - Form components (LoadingButton, etc.)

- **guards/** - Authorization guards

- **AuthGuard/** - Protected route wrapper

- **GuestGuard/** - Public route wrapper

- **layouts/** - Layout components

- **ui/** - Basic UI components

  

- **sections/** - Page-specific sections

- Each page gets its own folder

- Complex components that are page-specific

  

- **lib/** - Core Libraries & Services

- **firebase.ts** - Firebase initialization

- **firestore.ts** - Firestore operations & collections

- **storage.ts** - Firebase Storage operations

- **functions.ts** - Firebase Functions calls

  

- **auth/** - Authentication System

- **AuthProvider.tsx** - Auth context provider

- **authContext.ts** - Context definition

- **authOperations.ts** - Auth functions (login, signup, etc.)

- **useAuth.ts** - Auth hook

- **types.ts** - Auth-related types

  

- **theme/** - MUI Theme Configuration

- **ThemeProvider.tsx** - Theme context provider

- **palette.ts** - Color definitions

- **typography.ts** - Font settings

- **components/** - Component overrides

- **customColors.ts** - Custom color definitions

  

- **hooks/** - Custom React Hooks

- **useFirestore.ts** - Firestore real-time subscriptions

- **useStorage.ts** - File upload/download hooks

- **useSnackbar.ts** - Notification hook

- **useResponsive.ts** - Responsive breakpoints

  

- **utils/** - Utility Functions

- **format.ts** - Data formatting

- **validation.ts** - Form validation

- **constants.ts** - App constants

  

- **types/** - TypeScript Definitions

- **firestore.ts** - Firestore document types

- **api.ts** - API response types

- **common.ts** - Shared types

  

### `public/` - Static Assets

  

- **images/** - Static images

- **fonts/** - Custom fonts

- **icons/** - Icon files

  

## Development Rules

  

### 1. Component Organization

  

- Keep components small and focused

- Use composition over inheritance

- Separate presentational and container components

- Always export from index files for clean imports

  

### 2. State Management

  

- Use React Context for global state (auth, theme, settings)

- Avoid Redux unless absolutely necessary

- Use local state for component-specific data

- Leverage Firebase real-time listeners for live data

  

### 3. Firebase Integration

  

- All Firestore operations through lib/firestore.ts

- Define collection references as constants

- Use TypeScript interfaces for document types

- Implement proper error handling for all Firebase operations

  

### 4. Routing & Navigation

  

- Use Next.js App Router conventions

- Group routes by authentication status

- Implement proper loading states

- Use Link component with href attribute

- For MUI Link, use router.push

  

### 5. Theme & Styling

  

- Use MUI theme variables for all styling

- Define custom colors in theme configuration

- Use sx prop for component-specific styles

- Maintain consistent spacing with theme.spacing()

  

### 6. Type Safety

  

- Define all data types in types/ directory

- Use strict TypeScript configuration

- Avoid 'any' type - use 'unknown' if necessary

- Create proper interfaces for all Firebase documents

  

## Common Patterns

  

### Protected Route

  

\```tsx

// app/(authenticated)/layout.tsx

export default function AuthenticatedLayout({ children }) {

return <AuthGuard>{children}</AuthGuard>;

}

\```

  

### Firestore Collection Hook

  

\```tsx

// hooks/useCollection.ts

export function useCollection(collectionName: string) {

const [data, setData] = useState([]);

const [loading, setLoading] = useState(true);

  

useEffect(() => {

const unsubscribe = onSnapshot(

collection(db, collectionName),

(snapshot) => {

setData(

snapshot.docs.map((doc) => ({

id: doc.id,

...doc.data(),

}))

);

setLoading(false);

}

);

return unsubscribe;

}, [collectionName]);

  

return { data, loading };

}

\```

  

## File Naming Conventions

  

- Components: PascalCase (e.g., `UserProfile.tsx`)

- Hooks: camelCase with 'use' prefix (e.g., `useAuth.ts`)

- Utils: camelCase (e.g., `formatDate.ts`)

- Types: PascalCase for interfaces/types (e.g., `UserDoc`)

- Constants: UPPER_SNAKE_CASE (e.g., `MAX_FILE_SIZE`)

  

## Import Order

  

1. React/Next.js imports

2. Third-party libraries (MUI, Firebase, etc.)

3. Absolute imports (@/ paths)

4. Relative imports

5. Type imports

  

Example:

  

\```tsx

import { useState, useEffect } from "react";

import { Box, Button } from "@mui/material";

import { collection, onSnapshot } from "firebase/firestore";

import { useAuth } from "@/auth/useAuth";

import { LoadingScreen } from "../components/LoadingScreen";

import type { UserDoc } from "@/types/firestore";

\```

front/.cursor/rules/workflow.mdc


---

alwaysApply: true

---

  

# Frontend Development Workflow

  

## Architecture

  

This project uses Next.js with Firebase integration and Material-UI components. The architecture follows a component-based pattern with clear separation of concerns between presentation, business logic, and data management.

  

## Primary Rules

  

Below are the rules that you must follow when developing frontend functionality:

  

### Template and Components

  

- Use Material-UI components as the foundation

- Explore MUI documentation for ready-to-use components before creating custom ones

- Mix components from different MUI versions if necessary (with caution)

- Keep unused template components during early development stages

- Make components reusable but maintainable and understandable

  

### Theme and Context

  

- Customize application through theme context (`ThemeProvider`)

- Use separate contexts for different themes if needed (app theme, widget theme)

- Place theme contexts at the appropriate level (top-level for app, specific for widgets)

- Disable CssBaseline for widget themes to avoid style conflicts

- Always use theme variables for styling (colors, spacing, typography)

- Add custom colors in theme configuration (e.g., `theme.palette.customColors.primaryDark`)

  

### User Experience (UX)

  

- **Always** adopt the perspective of a critical user

- Use `LoadingScreen` or skeletons for loading states

- Display `EmptyContent` component for empty tables/lists

- Use `LoadingButton` for form actions (`loading={isSubmitting}`)

- Show informative error messages using snackbar notifications

- Ensure the app is self-explanatory - users should never wonder "what's happening?"

- Test on various mobile devices and large screens

- Use `100dvh` instead of `100vh` for mobile compatibility

  

### Code Quality

  

- Balance code quality with development speed

- Add comments where logic is complex

- Use TypeScript strictly - avoid 'any' type

- Keep functions and components focused (single responsibility)

- Use proper error boundaries and error handling

  

### State Management

  

- Use React Context for global state (avoid Redux unless necessary)

- Leverage Firebase real-time listeners for live data

- Use local state for component-specific data

- Implement optimistic UI updates where appropriate

  

### Performance Optimization

  

- Use `useCallback` and `useMemo` efficiently

- Pay attention to dependency arrays in hooks

- Lazy load components when appropriate

- Implement proper code splitting

  

### Authorization

  

- Use auth context with `onAuthStateChanged`

- Use `AuthGuard` for protected content

- Always show loading indicators during auth processes

- Handle auth errors gracefully

  

## Workflow

  

When building new features, follow this systematic workflow:

  

### 0. Planning Phase

  

Before starting, create a comprehensive to-do list following this exact process:

  

- Understand the feature requirements

- Identify affected components and pages

- List all necessary UI components

- Plan the data flow and state management

- Consider edge cases and error states

  

### 1. Design Analysis

  

- Review existing components that can be reused

- Identify new components that need to be created

- Plan responsive behavior for all screen sizes

  

### 2. Component Development

  

\```tsx

// Start with the component structure

// components/features/NewFeature.tsx

import { useState, useEffect } from "react";

import { Box, Paper, Typography, Skeleton } from "@mui/material";

import { useAuth } from "@/auth/useAuth";

import { useSnackbar } from "notistack";

  

export function NewFeature() {

const [loading, setLoading] = useState(true);

const [data, setData] = useState(null);

const { user } = useAuth();

const { enqueueSnackbar } = useSnackbar();

  

// Always handle loading states

if (loading) {

return <Skeleton variant="rectangular" height={200} />;

}

  

// Always handle empty states

if (!data) {

return <EmptyContent title="No data available" />;

}

  

return <Paper sx={{ p: 3 }}>{/* Component content */}</Paper>;

}

\```

  

### 3. Firebase Integration

  

\```tsx

// lib/firestore.ts - Define operations

export const dataOperations = {

async create(data: DataType) {

try {

const docRef = await addDoc(collections.data, data);

return docRef.id;

} catch (error) {

console.error("Error creating document:", error);

throw error;

}

},

  

async getById(id: string) {

const docRef = doc(collections.data, id);

const docSnap = await getDoc(docRef);

return docSnap.exists() ? docSnap.data() : null;

},

};

  

// hooks/useData.ts - Create real-time hook

export function useData(dataId: string) {

const [data, setData] = useState(null);

const [loading, setLoading] = useState(true);

  

useEffect(() => {

const unsubscribe = onSnapshot(

doc(db, "data", dataId),

(doc) => {

setData(doc.exists() ? doc.data() : null);

setLoading(false);

},

(error) => {

console.error("Error fetching data:", error);

setLoading(false);

}

);

  

return unsubscribe;

}, [dataId]);

  

return { data, loading };

}

\```

  

### 4. Form Handling

  

\```tsx

// Always use controlled components with proper validation

import { useForm, Controller } from "react-hook-form";

import { yupResolver } from "@hookform/resolvers/yup";

import * as yup from "yup";

  

const schema = yup.object({

name: yup.string().required("Name is required"),

email: yup.string().email("Invalid email").required("Email is required"),

});

  

export function DataForm() {

const {

control,

handleSubmit,

formState: { errors, isSubmitting },

} = useForm({

resolver: yupResolver(schema),

});

const { enqueueSnackbar } = useSnackbar();

  

const onSubmit = async (data) => {

try {

await dataOperations.create(data);

enqueueSnackbar("Data saved successfully", { variant: "success" });

} catch (error) {

enqueueSnackbar(error.message, { variant: "error" });

}

};

  

return (

<form onSubmit={handleSubmit(onSubmit)}>

<Controller

name="name"

control={control}

render={({ field }) => (

<TextField

{...field}

label="Name"

error={!!errors.name}

helperText={errors.name?.message}

fullWidth

margin="normal"

/>

)}

/>

  

<LoadingButton

type="submit"

variant="contained"

loading={isSubmitting}

fullWidth

>

Submit

</LoadingButton>

</form>

);

}

\```

  

### 5. Testing

  

- Check if front end compiles and runs.

-

  

## Common Patterns

  

### Notification Pattern

  

\```tsx

const { enqueueSnackbar } = useSnackbar();

  

// Success

enqueueSnackbar("Operation successful", { variant: "success" });

  

// Error

enqueueSnackbar("Something went wrong", { variant: "error" });

  

// Info

enqueueSnackbar("Please note...", { variant: "info" });

\```

  

### Protected Route Pattern

  

\```tsx

// Use AuthGuard wrapper

<AuthGuard>

<ProtectedContent />

</AuthGuard>;

  

// Or conditional rendering

const { isAuthenticated } = useAuth();

if (!isAuthenticated) {

return <Navigate to="/signin" />;

}

\```

  

## Navigation Rules

  

### Next.js Link

  

\```tsx

// Correct - use href

<Link href="/dashboard">

<Button>Go to Dashboard</Button>

</Link>

\```

  

### MUI Link with Navigation

  

\```tsx

// Correct - use router.push

import { useRouter } from "next/navigation";

  

const router = useRouter();

<MuiLink component="button" onClick={() => router.push("/dashboard")}>

Dashboard

</MuiLink>;

\```

  

## Debugging Checklist

  

When something doesn't work:

  

1. Check browser console for errors

2. Verify Firebase configuration

3. Check network tab for API calls

4. Verify authentication state

5. Check component props and state

6. Verify data types match interfaces

7. Check for race conditions

8. Verify cleanup functions in useEffect

back/.cursor/rules/folder-structure.mdc


---

globs: back/**

alwaysApply: false

---

  

# Python Firebase Functions - Broker Architecture

  

This project follows the broker architecture pattern for Firebase Functions.

  

## Folder Structure

  

### `src/` - Source Code

  

#### Core Components

  

- **brokers/** - Message/event handling layer

  

- **callable/** - Client-callable functions (Firebase callable functions)

- **https/** - HTTP endpoints (REST APIs)

- **triggered/** - Event-triggered functions (Firestore/Storage triggers)

  

- **documents/** - DocumentBase classes

  

- Each document class represents a Firestore collection

- All Firestore operations MUST go through these classes

- Never access Firestore directly

  

- **models/** - Type definitions

  

- **firestore_types.py** - Pydantic models for Firestore documents

- **function_types.py** - Request/response types for functions

- **util_types.py** - Utility types and enums

  

- **services/** - Business logic

  

- Orchestrate operations across multiple documents

- Complex workflows and business rules

  

- **factories/** - Object creation

  

- Create documents from various sources (CSV, JSON, templates)

- Batch operations

  

- **shared/** - Shared components

  

- **Db.py** - Database singleton with ProjectDb class

- **DocumentBase.py** - Base document class

  

- **util/** - Utility functions

  

- Authentication helpers

- CORS handling

- Logging

  

- **exceptions/** - Custom exceptions

- Project-specific error classes

  

### `tests/` - Test Suite

  

- **integration/** - End-to-end tests

- **unit/** - Component tests

- **util/** - Test utilities

back/.cursor/rules/workflow.mdc


---

globs: back/**

alwaysApply: false

---

  

# Backend Development Workflow

  

## Architecture

  

This project uses the event driven broker architecture pattern with Firebase Functions. All business logic is organized into brokers that handle different types of requests and events. The data is saved in firestore and updated on the front end automatically through firestore hooks.

  

## Testing

  

You must always start from tests. We primarily use integration tests that test the user flow from start to finish. For example, for testing item management flow, you would test: creating item -> updating item -> archiving item -> deleting item -> etc. Inside each test case you must check the results in firestore. Test is considered passed, when all document properties are as expected.

  

**Important**: We check real documents in firestore after running each firebase function. The same with external services. Never create useless unit tests that just test properties of the class. Instead, test the actual functionality of the class.

  

Emulator is started automatically when executing `back/run_tests.py` file. Only run tests by running this file, otherwise, they will not work.

  

# Development Principles

  

All code must be clearly readable and maintainable. It must read like a story. Everything should be self-explanatory. You should not need tons of comments to understand what it does. The key idea is to make sure I can understand what the code does in 5 seconds. If I can't, you should refactor the code. Below is a list of principles that you must follow to achieve this:

  

- 🪟 **No broken windows**: Keep code clean from the start. Don't leave anything for later.

- 🔄 **DRY**: Don't repeat yourself. If you are about to write the same code twice, stop, reconsider your approach and refactor.

- 🌐 **Leave it better than you found it**: Improve bad code as you encounter it. Your code should clearly communicate its purpose.

- 🔁 **Write code once**: Don't repeat yourself. Make code modular and extract components when needed. Prefer types over obvious comments.

- 🧪 **Test First**: Do not start integrating any front-end features until they have been fully tested on the back end.

- 👨‍💻 **SOLID**: Follow SOLID principles. Write single purpose short self-contained functions.

  

## Development Rules

  

Below are the rules that you must follow when developing backend functionality:

  

- All firestore documents must be modified **strictly** within `DocumentBase` classes located in `src/documents/DocumentBase.py`. You must **never** modify documents outside of these classes.

- All third party APIs/clients must be wrapped in API wrapper classes located in `src/apis/`.

- Never make calls to firestore directly. Always use `Db` class located in `src/apis/Db.py`.

- All firestore document types should always be updated in `src/models/firestore_types.py`.

- If you are creating multiple documents from an event (like creating items from CSV file) - create a Factory class with a method `.from_csv(csv_path)` - this method should return an array of Document classes.

- Rules for new firestore and storage types must **always** be up to date in `firestore.rules` or `storage.rules`. Define them as soon as possible.

- All third party APIs must be wrapped in APIWrapperBase class located in `src/apis/APIWrapperBase.py`.

- All firestore function request and response types must be in `src/models/function_types.py`.

- Functions should be named as `{action}_{resource}_callable` or `on_{resource}_{event}`.

- All complex functionality that involves multiple documents, other APIBase classes, or complex logic should be wrapped in a Service class, located in `src/services/`.

  

## Workflow

  

When building new features, you must always start from creating new test files or modifying existing test files. Follow the workflow below:

  

0. Before starting, create a to-do list for yourself, following this exact process.

1. Navigate to the `tests` directory and find the most relevant test files that contain a similar user flow.

- If you cannot find any relevant test files, ask clarification from the user.

- If it's a new feature, create a new test file.

2. Incorporate new functionality into the test files. Make sure to check types from the `models` folder or add new types as necessary.

3. Build the new feature following our broker architecture and development principles.

4. Run the affected tests and check the results in terminal.

5. Keep iterating until all tests are passing. Do not stop until all tests are passing.

6. Export any new brokers from the `main.py` file for deployment.

7. Document any key architecture decisions (if any)in the `back/.cursor/rules/ADR.mdc` file.

8. Ensure firestore rules and storage rules are updated to reflect the new functionality in the `firestore.rules` and `storage.rules` files.

  

## Common Patterns

  

### Creating a Callable Function

  

\```python

@https_fn.on_call(

cors=options.CorsOptions(cors_origins=["*"]),

ingress=options.IngressSetting.ALLOW_ALL,

)

def function_name(req: https_fn.CallableRequest):

uid = db_auth_wrapper(req)

# Implementation

\```

  

### Creating a Document Class

  

\```python

class MyDocument(ProjectDocumentBase[MyDocType]):

pydantic_model = MyDocType

  

def __init__(self, id: str, doc: Optional[dict] = None):

self.collection_ref = self.db.collections["my_collection"]

super().__init__(id, doc)

\```

  

### Creating a Service

  

\```python

class MyService:

def __init__(self, doc: MyDocument):

self.document = doc

  

def complex_operation(self):

# Orchestrate multiple documents

\```

  

## Guardrails

  

- NEVER run any deploy commands.

back/.cursor/rules/ADR.mdc


---

description: Log of all the key backend architectural decisions.

alwaysApply: false

---

  

# Architecture Decision Log

  

<!--

ADR_AGENT_PROTOCOL v1.0

  

You (the agent) manage this file as the single source of truth for all ADRs.

  

INVARIANTS

- Keep this exact file structure and headings.

- All ADR entries use H2 headings: "## ADR-XXXX — <Title>" (4-digit zero-padded ID).

- Allowed Status values: Proposed | Accepted | Superseded

- Date format: YYYY-MM-DD

- New entries must be appended to the END of the file.

- The Index table between the INDEX markers must always reflect the latest state and be sorted by ID desc (newest on top).

- Each ADR MUST contain: Date, Status, Owner, Context, Decision, Consequences.

- Each ADR must include an explicit anchor `<a id="adr-XXXX"></a>` so links remain stable.

  

HOW TO ADD A NEW ADR

1) Read the whole file.

2) Compute next ID:

- Scan for headings matching: ^## ADR-(\d{4}) — .+$

- next_id = (max captured number) + 1, left-pad to 4 digits.

3) Create a new ADR section using the “New ADR Entry Template” below.

- Place it AFTER the last ADR section in the file.

- Add an `<a id="adr-XXXX"></a>` line immediately below the heading.

4) Update the Index (between the INDEX markers):

- Insert/replace the row for this ADR keeping the table sorted by ID descending.

- Title in the Index MUST link to the anchor: [<Title>](#adr-XXXX)

- If this ADR supersedes another: set “Supersedes” in this row, and update that older ADR:

a) Change its Status to “Superseded”

b) Add “Superseded by: ADR-XXXX” in its Consequences block

c) Update the older ADR’s Index row “Superseded by” column to ADR-XXXX

5) Validate before saving:

- Exactly one heading exists for ADR-XXXX

- All required fields are present and non-empty

- Index contains a row for ADR-XXXX and remains properly sorted

6) Concurrency resolution:

- If a merge conflict or duplicate ID is detected after reading: recompute next_id from the current file state, rename your heading, anchor, and Index row accordingly, and retry once.

  

COMMIT MESSAGE SUGGESTION

- "ADR-XXXX: <Short Title> — <Status>"

  

END ADR_AGENT_PROTOCOL

-->

  

## Index

  

<!-- BEGIN:ADR_INDEX -->

  

| ID | Title | Date | Status | Supersedes | Superseded by |

| ---- | --------------------------------------------------------- | ---------- | -------- | ---------- | ------------- |

| 0007 | [Test Fixture Cleanup Strategy](#adr-0007) | 2025-01-27 | Accepted | — | — |

| 0006 | [Automated Test Runner Implementation](#adr-0006) | 2025-01-27 | Accepted | — | — |

| 0005 | [Database Class Consolidation](#adr-0005) | 2025-01-27 | Accepted | — | — |

| 0004 | [Real Firebase Emulators Over Mocked Services](#adr-0004) | 2025-01-27 | Accepted | — | — |

| 0003 | [Test Utilities Organization in util/ Folder](#adr-0003) | 2025-01-27 | Accepted | — | — |

| 0002 | [Firebase Emulator Integration Pattern](#adr-0002) | 2025-01-27 | Accepted | — | — |

| 0001 | [Template Testing Strategy](#adr-0001) | 2025-01-27 | Accepted | — | — |

  

<!-- END:ADR_INDEX -->

  

---

  

## ADR-0001 — Template Testing Strategy

  

<a id="adr-0001"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

The Python Firebase template needed a robust testing strategy that supports both rapid development and comprehensive integration testing. Tests needed to work with and without Firebase emulators running.

  

### Alternatives

  

- **All tests require emulators**: Simple but slow for basic function logic testing

- **Mock all Firebase services**: Fast but doesn't test real Firebase behavior

- **Mixed approach with clear categorization**: Support both scenarios with proper documentation

  

### Decision

  

Implement a mixed testing strategy where tests are categorized by emulator requirements:

  

- Tests that only validate function logic can run without emulators

- Integration tests that require database operations use real Firebase emulators

- Clear documentation distinguishes between test types

- Environment variable `SKIP_EMULATORS=true` allows bypassing emulator startup

  

### Consequences

  

- **Pros**: Fast feedback for logic tests, comprehensive integration testing, flexible CI/CD options

- **Cons / risks**: Developers need to understand test categories, some complexity in setup

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Tests documented in `tests/README.md` with clear examples. CI can run both modes: quick logic tests and full integration tests.

  

---

  

## ADR-0002 — Firebase Emulator Integration Pattern

  

<a id="adr-0002"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

The template needed reliable Firebase emulator management for integration testing. The existing github-app project had a proven pattern for emulator lifecycle management that should be adapted.

  

### Alternatives

  

- **Manual emulator management**: Developers start/stop emulators manually

- **Test-level emulator fixtures**: Each test manages its own emulator instance

- **Session-level emulator management**: Emulators start once per test session (github-app pattern)

  

### Decision

  

Adopt the github-app emulator pattern with session-level management:

  

- `tests/util/firebase_emulator.py` handles emulator lifecycle

- Automatic port cleanup and process management

- Configurable emulator services (functions, firestore, storage)

- Robust timeout and error handling

- Optional automatic startup with `setup_emulators` fixture

  

### Consequences

  

- **Pros**: Proven pattern, reliable cleanup, supports multiple emulator services, good error handling

- **Cons / risks**: More complex than manual setup, requires Firebase CLI installation

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Tests use `firebase_emulator` fixture. Emulator utilities must handle port conflicts and process cleanup. Pattern consistency with github-app project.

  

---

  

## ADR-0003 — Test Utilities Organization in util/ Folder

  

<a id="adr-0003"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Test fixtures and utilities were mixed in `conftest.py`, making them harder to reuse and maintain. The `ItemFlowSetup` class and Firebase emulator utilities needed better organization for template users.

  

### Alternatives

  

- **Keep everything in conftest.py**: Simple but becomes unwieldy

- **Split by functionality**: Separate files for different utilities

- **Move to tests/util/**: Follow common Python testing patterns

  

### Decision

  

Move shared test utilities to `tests/util/` folder:

  

- `tests/util/firebase_emulator.py`: Emulator management and fixtures

- `tests/util/item_flow_setup.py`: Database setup fixtures for integration tests

- Import utilities in `conftest.py` for backwards compatibility

- Clear separation of concerns

  

### Consequences

  

- **Pros**: Better organization, easier to find and maintain utilities, follows Python conventions

- **Cons / risks**: Minor refactoring needed for imports, slightly more complex structure

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

All test utilities under `tests/util/` with proper imports. New utilities should follow this pattern.

  

---

  

## ADR-0004 — Real Firebase Emulators Over Mocked Services

  

<a id="adr-0004"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Integration tests needed to validate Firebase Functions behavior including database operations, triggers, and Firebase service interactions. The choice was between mocking Firebase services or using real emulators.

  

### Alternatives

  

- **Mock Firebase services**: Fast but doesn't test real Firebase behavior or edge cases

- **Use production Firebase**: Real but expensive, slow, and affects live data

- **Use Firebase emulators**: Real Firebase behavior in isolated environment

  

### Decision

  

Use real Firebase emulators for all integration testing:

  

- Tests connect to actual Firestore emulator (localhost:8080)

- Real Firebase Functions emulator (localhost:5001) for function execution

- Real document operations in emulator database

- Only mock Firestore trigger events (event object creation, not database operations)

  

### Consequences

  

- **Pros**: Tests real Firebase behavior, catches Firebase-specific issues, validates complete workflows

- **Cons / risks**: Requires Firebase CLI, slower than mocks, more complex setup

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Integration tests must use emulator connections. No mocking of Firebase database operations. Trigger events can be mocked for testing purposes.

  

---

  

## ADR-0005 — Database Class Consolidation

  

<a id="adr-0005"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

The template had two database classes: `Db` (base class) and `ProjectDb` (project-specific subclass). This created unnecessary inheritance complexity and indirection for a template that serves as a starting point for new projects.

  

### Alternatives

  

- **Keep ProjectDb inheritance**: Maintains separation but adds complexity for template users

- **Multiple database singletons**: Each with different collections but more confusing

- **Consolidate into single Db class**: Simplify by merging ProjectDb functionality into base Db class

  

### Decision

  

Consolidate ProjectDb functionality directly into the base Db class:

  

- Merge project-specific collections (items, categories, itemActivities) into base `_init_collections()` method

- Replace all `ProjectDb.get_instance()` calls with `Db.get_instance()`

- Remove ProjectDb class entirely

- Update all imports and type hints across the codebase

  

### Consequences

  

- **Pros**: Simpler codebase for template users, fewer concepts to understand, easier to extend

- **Cons / risks**: Less separation of concerns, template users may need to modify collections directly

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

All references to ProjectDb removed from codebase. Single Db class used throughout with project collections included by default.

  

---

  

## ADR-0006 — Automated Test Runner Implementation

  

<a id="adr-0006"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Developers needed an easy way to run tests with proper Firebase emulator management. Manual emulator startup/shutdown was error-prone and the existing pytest commands required knowledge of emulator setup.

  

### Alternatives

  

- **Manual emulator management**: Simple but error-prone, requires developer to remember setup steps

- **Docker-based testing**: Isolated but complex setup, requires Docker knowledge

- **Automated test runner script**: Single command handles emulator lifecycle and test execution

  

### Decision

  

Implement `run_tests.py` script with automated emulator management:

  

- Automatic Firebase emulator startup/shutdown with proper cleanup

- Command-line options for test types (unit, integration, all)

- Support for existing emulators via `--no-emulator` flag

- Optional emulator log viewing with `--show-logs`

- Graceful error handling and forced cleanup on failures

  

### Consequences

  

- **Pros**: Better developer experience, reliable emulator cleanup, flexible test execution options

- **Cons / risks**: Additional script to maintain, requires Firebase CLI installation

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Test runner documented in README with examples. Script handles all emulator lifecycle automatically. Command-line help available via `--help`.

  

---

  

## ADR-0007 — Test Fixture Cleanup Strategy

  

<a id="adr-0007"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

The `conftest.py` file contained unused test fixtures (`test_category`, `test_item`, `mock_callable_request`) that were not referenced anywhere in the test suite. These created confusion and maintenance overhead.

  

### Alternatives

  

- **Keep all fixtures**: Simple but maintains dead code and confusion

- **Move to test utilities**: Relocate unused fixtures to utils for potential future use

- **Remove unused fixtures**: Clean up conftest.py to only contain actively used fixtures

  

### Decision

  

Remove unused test fixtures from conftest.py:

  

- Remove `test_category`, `test_item`, and `mock_callable_request` fixtures

- Keep only `firebase_app`, `db`, and `test_user_id` fixtures that are actively used

- Move complex test setup logic to dedicated utility modules when needed

- Clean up any broken import references

  

### Consequences

  

- **Pros**: Cleaner conftest.py, reduces confusion for new developers, easier maintenance

- **Cons / risks**: Fixtures need to be recreated if later needed, requires verification that nothing uses them

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

No references to removed fixtures exist in codebase. Tests continue to pass without the removed fixtures. New test fixtures should only be added when actively used.

.cursor/rules/ADR.mdc


---

description: Architectural Decision Records

globs:

alwaysApply: false

---

  

# Architecture Decision Log

  

<!--

ADR_AGENT_PROTOCOL v1.0

  

You (the agent) manage this file as the single source of truth for all ADRs.

  

INVARIANTS

- Keep this exact file structure and headings.

- All ADR entries use H2 headings: "## ADR-XXXX — <Title>" (4-digit zero-padded ID).

- Allowed Status values: Proposed | Accepted | Superseded

- Date format: YYYY-MM-DD

- New entries must be appended to the END of the file.

- The Index table between the INDEX markers must always reflect the latest state and be sorted by ID desc (newest on top).

- Each ADR MUST contain: Date, Status, Owner, Context, Decision, Consequences.

- Each ADR must include an explicit anchor `<a id="adr-XXXX"></a>` so links remain stable.

  

HOW TO ADD A NEW ADR

1) Read the whole file.

2) Compute next ID:

- Scan for headings matching: ^## ADR-(\d{4}) — .+$

- next_id = (max captured number) + 1, left-pad to 4 digits.

3) Create a new ADR section using the “New ADR Entry Template” below.

- Place it AFTER the last ADR section in the file.

- Add an `<a id="adr-XXXX"></a>` line immediately below the heading.

4) Update the Index (between the INDEX markers):

- Insert/replace the row for this ADR keeping the table sorted by ID descending.

- Title in the Index MUST link to the anchor: [<Title>](#adr-XXXX)

- If this ADR supersedes another: set “Supersedes” in this row, and update that older ADR:

a) Change its Status to “Superseded”

b) Add “Superseded by: ADR-XXXX” in its Consequences block

c) Update the older ADR’s Index row “Superseded by” column to ADR-XXXX

5) Validate before saving:

- Exactly one heading exists for ADR-XXXX

- All required fields are present and non-empty

- Index contains a row for ADR-XXXX and remains properly sorted

6) Concurrency resolution:

- If a merge conflict or duplicate ID is detected after reading: recompute next_id from the current file state, rename your heading, anchor, and Index row accordingly, and retry once.

  

COMMIT MESSAGE SUGGESTION

- "ADR-XXXX: <Short Title> — <Status>"

  

END ADR_AGENT_PROTOCOL

-->

  

## Index

  

<!-- BEGIN:ADR_INDEX -->

  

| ID | Title | Date | Status | Supersedes | Superseded by |

| ---- | ------------------------------------------------------------ | ---------- | -------- | ---------- | ------------- |

| 0004 | [Event-Driven Broker Architecture with Firestore](#adr-0004) | 2025-01-27 | Accepted | — | — |

| 0002 | [Monorepo Structure with Frontend and Backend](#adr-0002) | 2025-01-27 | Accepted | — | — |

| 0001 | [Full-Stack Firebase Template Architecture](#adr-0001) | 2025-01-27 | Accepted | — | — |

  

<!-- END:ADR_INDEX -->

  

---

  

## New ADR Entry Template (copy for each new decision)

  

> Replace placeholders, keep section headers. Keep prose concise.

  

\```

  

## ADR-XXXX — \<Short, specific title>

  

<a id="adr-XXXX"></a>

**Date**: YYYY-MM-DD

**Status**: Proposed | Accepted | Superseded

**Owner**: <Name>

  

### Context

  

<1–3 sentences: what changed or what forces drive this decision now>

  

### Alternatives

  

<Quick bullet list of alternatives considered, and why they were rejected.>

  

### Decision

  

\<Single clear decision in active voice; make it testable/verifiable>

  

### Consequences

  

* **Pros**: \<benefit 1>, \<benefit 2>

* **Cons / risks**: \<cost 1>, \<risk 1>

* **Supersedes**: ADR-NNNN (if any)

* **Superseded by**: ADR-MMMM (filled later if replaced)

  

### (Optional) Compliance / Verification

  

\<How we’ll check this is honored: tests, checks, fitness functions, runbooks>

  

\```

  

---

  

## ADR-0001 — Full-Stack Firebase Template Architecture

  

<a id="adr-0001"></a>

**Date**: 2025-01-27 `

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Modern web applications require both frontend and backend components with real-time data synchronization. Firebase provides a comprehensive platform for building full-stack applications, but setting up the architecture with best practices requires significant boilerplate code.

  

### Alternatives

  

- **Separate repositories**: Frontend and backend in different repos, harder to coordinate changes

- **Backend-only template**: Covers only server-side concerns, developers must handle frontend integration

- **Frontend-only template**: Limited to client-side Firebase SDK, missing serverless functions capabilities

- **Full-stack monorepo template**: Single template with both Next.js frontend and Python Firebase Functions

  

### Decision

  

Create a comprehensive full-stack Firebase template with:

  

- Next.js 14 frontend with TypeScript and Material-UI

- Python Firebase Functions backend with broker architecture pattern

- Shared Firebase project configuration

- Integrated testing strategy for both frontend and backend

- Single repository with clear separation of concerns

  

### Consequences

  

- **Pros**: Complete starting point for Firebase projects, coordinated development, shared configuration

- **Cons / risks**: More complex initial setup, larger template size, requires knowledge of both frontend and backend

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Template includes working examples for both frontend and backend. Firebase configuration shared between components. Documentation covers full development workflow.

  

---

  

## ADR-0002 — Monorepo Structure with Frontend and Backend

  

<a id="adr-0002"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Full-stack Firebase applications need coordinated development between frontend (Next.js) and backend (Firebase Functions). The question was how to organize the code structure to support both independent development and shared configuration.

  

### Alternatives

  

- **Separate repositories**: Independent versioning but coordination overhead and duplicate configuration

- **Nested backend in frontend**: Simple structure but mixes concerns and complicates deployment

- **Side-by-side monorepo**: Clear separation with shared root configuration

  

### Decision

  

Implement side-by-side monorepo structure:

  

- `/front/` - Next.js frontend application with its own package.json and dependencies

- `/back/` - Python Firebase Functions backend with its own requirements.txt and structure

- Root-level Firebase configuration (`firebase.json`, `firestore.rules`, `storage.rules`)

- Shared documentation in root README.md with component-specific READMEs

  

### Consequences

  

- **Pros**: Clear separation of concerns, independent tooling, shared Firebase configuration, coordinated documentation

- **Cons / risks**: Slightly more complex initial setup, need to manage two different development environments

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Directory structure clearly separates frontend and backend. Firebase CLI recognizes backend functions source in configuration. Both components can be developed independently.

  

---

  

## ADR-0004 — Event-Driven Broker Architecture with Firestore

  

<a id="adr-0004"></a>

**Date**: 2025-01-27

**Status**: Accepted

**Owner**: AI Agent

  

### Context

  

Modern full-stack applications require consistent data state between frontend and backend components. Traditional request-response patterns create tight coupling and require complex state synchronization logic. Real-time applications need immediate UI updates when data changes, regardless of the source of the change.

  

### Alternatives

  

- **Direct API communication**: Backend returns data directly to frontend, requires manual state management

- **Event streaming with external broker**: Use services like Redis Pub/Sub or RabbitMQ, adds infrastructure complexity

- **WebSocket connections**: Real-time but requires connection management and doesn't persist data

- **Firestore as event-driven broker**: Leverages built-in real-time capabilities and acts as single source of truth

  

### Decision

  

Implement event-driven broker architecture where Firestore serves as both the data store and event broker:

  

- All data mutations flow through Firestore exclusively

- Backend functions save data to Firestore without returning responses to frontend

- Frontend subscribes to Firestore collections/documents using hooks for real-time updates

- Firestore acts as the single source of truth for both backend and frontend

- UI updates automatically through Firestore real-time listeners

  

### Consequences

  

- **Pros**: Eliminates data synchronization issues, automatic real-time updates, reduced coupling between frontend and backend, simplified state management, leverages Firebase's built-in capabilities

- **Cons / risks**: Increased Firestore read operations, requires proper security rules design, potential data consistency challenges with complex operations, network dependency for all data access

- **Supersedes**: —

- **Superseded by**: —

  

### Compliance / Verification

  

Backend functions must only perform Firestore writes without returning data responses. Frontend components must use Firestore hooks (useFirestore, real-time listeners) for all data access. No direct API data responses to frontend. All data mutations trigger UI updates through Firestore change events.

  

---

.cursor/rules/PRD.mdc


---

description:

globs:

alwaysApply: false

---

  

# <Product / Feature Name>

  

<TL;DR: 1–2 sentences: For [target user], build [capability] so they can [value].>

  

---

  

## Users & Value

  

- **Primary user / persona:** <who specifically>

- **Jobs-to-be-done (JTBD):**

- When <situation>, I want <motivation>, so I can <outcome>.

- When <situation>, I want <motivation>, so I can <outcome>.

  

---

  

## Success Metrics

  

- **Primary Goal:** <what success looks like in plain words>

- **Success Criteria:** <what you will measure, with formula> (target: <value>)

  

---

  

## Scope

  

| Must‑have (MVP) | Nice‑to‑have (Later) | Explicitly Out (Not now) |

| --------------- | -------------------- | ------------------------ |

| <bullet> | <bullet> | <bullet> |

| <bullet> | <bullet> | <bullet> |

  

- **Definition of Done (MVP):**

- [ ] <clear acceptance criterion 1>

- [ ] <clear acceptance criterion 2>

- [ ] <clear acceptance criterion 3>

  

---

  

## Tech Stack

  

### Frontend:

  

- Next.js with TypeScript

- React for UI components

- Tailwind CSS for styling

- Firebase Authentication for user management

  

### Backend:

  

- Firebase Functions (Python) for video processing

- 11Labs API for AI voice synthesis

- FFmpeg for audio/video manipulation

- Firebase Storage for video file storage

  

### Database:

  

- Firebase Firestore for user data and processing metadata

- Firebase Storage for video assets and processed files

Notes

Let's keep our codebase well-documented at all times, making sure we have the coding agent principles in place so that we future-proof our development.

I've compiled our "north star" core documentation into @core . The Foundational Architecture Blueprint is a very long document outlining the entire SalesBlaster AI Outbound technical infrastructure (it's probably too long to load entirely into context but can be grepped or indexed)

IMPORTANT: Use the structure of the AI workflow file examples but adapt the actual content to our actual codebase.

Think through this step by step.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment