Prompt Library
Reusable prompt templates for working with Claude Code on this project. Each template follows a consistent structure that produces reliable, scoped results.
Structure of every template
- Context — what Claude needs to know before starting: stack, constraints, files to read
- Task — what to build, with explicit file paths and endpoint names
- Constraints — what NOT to touch (critical for preventing unwanted side effects)
- Validation — how to verify it works without running a full test suite
[BRACKETS], and paste into a new Claude Code session. Review the proposed plan before approving any file writes.00Project Context
Paste at the start of any Claude Code session to orient the model without having to re-explain the stack.
Read `CLAUDE.md` at the project root before doing anything else.
This is the MCLAVIER Actuarial Marketplace — a full-stack app built with:
- **Frontend:** Next.js 14 (pages router), React 18, inline styles only (no Tailwind classes in JSX)
- **Backend:** FastAPI (fully async), Python 3.12, Pydantic v2
- **Database:** PostgreSQL 16, SQLAlchemy 2 async + asyncpg
- **Infra:** Docker / docker-compose
Dark theme: bg=`#0b0d10`, card=`#14171c`, accent=`#4f8cff`, border=`#232932`.
Key constraints that differ from typical projects:
- All components use **inline styles** — never Tailwind class names
- All FastAPI routes are **async def** — no sync SQLAlchemy
- Pydantic v2 — `model_config`, not `class Config`
- `next.config.js` is CJS — no ESM-only plugins (no rehype-highlight)
Current working pages: /, /apps/[id], /history, /monitor, /explorer, /docs/*
Current API routers: apps, runs (+ export), explorer, monitor
I am a senior actuary, not a developer. Keep explanations concrete and analogies
actuarial where relevant. Skip basic programming explanations.01New Feature
Adding any full-stack feature that requires both a new FastAPI router and a new Next.js page.
# Template — New Feature
## Context
Read `CLAUDE.md` and `.claude/context/conventions.md` before starting.
Read the following existing files before writing any code:
- `backend/main.py` (to see current router registrations)
- `frontend/components/Navbar.js` (to see current nav items)
- [LIST ANY OTHER RELEVANT FILES]
Current branch: [BRANCH_NAME]
## Task
Add **[FEATURE NAME]**.
### Backend changes
New router: `backend/routers/[name].py`
Endpoints:
- `[METHOD] /[prefix]/[path]` — [description]
- `[METHOD] /[prefix]/[path]` — [description]
Register in `backend/main.py`:
```python
from routers.[name] import router as [name]_router
app.include_router([name]_router, prefix="/[prefix]")
```
### Frontend changes
New page: `frontend/pages/[path].js`
New components (if needed): `frontend/components/[Name].js`
Navbar update — add "[Label]" between "[Before]" and "[After]":
```js
<NavItem label="[Label]" active={is[Name]} onClick={() => router.push("/[path]")} />
```
### Database changes
[describe schema change, or write "None — no schema changes needed"]
## Constraints
- Do NOT modify any existing file except: `backend/main.py` (router registration only),
`frontend/components/Navbar.js` (nav item only)
- Do NOT install new packages without listing them here first: [packages needed, or "none"]
- All new backend code must use `async def` and `await`
- All new frontend components must use inline styles — no Tailwind class names
- Match the dark theme: bg=`#14171c`, border=`#232932`, accent=`#4f8cff`, text=`#9aa0ab`
## Validation
The feature works when:
1. `curl -s https://backend-production-30991.up.railway.app/[path]` returns [expected JSON shape]
2. Navigating to `http://localhost:3000/[path]` renders [expected UI state]
3. [any other specific check]
## After implementation
Rebuild with: `docker compose build && docker compose up -d`02New Marketplace App
Creating a new actuarial computation tool — manifest.json + function.py — without touching any existing backend files.
# Template — New Marketplace App
## Context
Read `CLAUDE.md` and `.claude/context/domain.md` before starting.
I want to add a new actuarial computation app to the marketplace.
This means creating two files only: manifest.json and function.py.
No backend router changes needed — the existing POST /apps/register handles registration.
## App specification
- **Name:** [APP NAME]
- **Description:** [one sentence — appears in the marketplace card]
- **Actuarial methodology:** [e.g. "Solvency II standard formula, SCR market risk submodule"]
- **Regulatory context:** [e.g. "Solvency II Directive, Article 104"]
## Input schema (manifest.json)
```json
{
"name": "[APP NAME]",
"description": "[one sentence]",
"inputs": {
"[input_key]": {
"type": "number",
"label": "[Human-readable label]",
"min": 0,
"max": 100,
"step": 1,
"default": 50,
"unit": "%"
}
}
}
```
Constraints:
- Use "type": "number" — it is the only supported type
- unit is appended to the displayed value (use " yrs" with leading space for year units)
- Choose default as the most realistic base-case value for an actuary
## Expected output format (function.py return value)
```python
{
"columns": ["Col1", "Col2"], # optional, controls table column order
"table": [{"col1": ..., "col2": ...}], # required — data table
"series": [{"x": 0, "y": 100.0}], # required — line chart
"summary": {"key_metric": "value"}, # optional — KPI cards
}
```
## Methodology
[Describe the exact formula or algorithm. Be precise:]
- Formula: [e.g. "qx = min(0.99, A * exp(B * x)) where A=0.00009, B=0.091"]
- Computation steps: [numbered list]
- Benchmark: [e.g. "For age=65, shock=0: survival at 85 should be ~32% per CMI 2022"]
- Edge cases: [e.g. "age=100 produces single-row table; shock=0 returns base case"]
## Implementation requirements
```python
import asyncio
import numpy as np
async def run(inputs: dict) -> dict:
# 1. Simulate realistic computation time (5-10 seconds)
await asyncio.sleep(5 + np.random.uniform(0, 3))
# 2. Parse inputs — always use .get(key, default) for resilience
val = float(inputs.get("[input_key]", [default]))
# 3. Validate bounds
val = max([min], min([max], val))
# 4. Compute using numpy — no Python loops if vectorized equivalent exists
# 5. Return the structured result
return {...}
```
## File locations
Create:
- `backend/functions/[name]/manifest.json`
- `backend/functions/[name]/function.py`
## Constraints
- Do NOT modify any existing backend file
- Do NOT import any library not already in requirements.txt
- Function must be `async def run(inputs: dict) -> dict` — exact signature
- asyncio.sleep is mandatory — without it, the UI shows no loading state03Debug a Specific Issue
Something is broken. Use when you have a specific error message or reproducible failure.
# Template — Debug a Specific Issue
## Context
Read `CLAUDE.md` before starting.
Read the following files before proposing any fix:
- [FILE WHERE THE BUG IS OBSERVED]
- [FILE WHERE THE ROOT CAUSE LIKELY IS]
## Problem description
**Symptom:** [What the user sees — be specific. Include exact error message.]
**Where it occurs:** [URL, API endpoint, or component name]
**When it occurs:** [Always? Only with specific inputs? After a specific action?]
**What I expected:** [The correct behavior]
## Environment
- Branch: [BRANCH_NAME]
- Last working state: [e.g. "Was working before I added the export endpoint"]
- Error message (exact):
```
[paste exact error from browser console, Docker logs, or terminal]
```
## What I've already tried
- [attempt 1]
- [attempt 2]
## Constraints
- Fix ONLY the identified bug. Do not refactor unrelated code.
- If the fix requires modifying more than 3 lines, explain why before proceeding.
- If the root cause is in a different file than the symptom, identify both.
## How to get Docker logs
```bash
docker compose logs -f backend # Python errors, FastAPI tracebacks
docker compose logs -f frontend # Next.js build errors, runtime errors
```
## Common causes in this codebase
- **greenlet_spawn error** → sync SQLAlchemy in async route — use `await`
- **Cannot find module** → new npm package not installed — rebuild Docker
- **MDX parse error "Could not parse expression with acorn"** →
bare {...} in MDX text outside code block — wrap in backticks or use (...)
- **WebSocket closes immediately** → CORS mismatch or backend not running
- **Empty result from JSONB column** → asyncpg returns None — add `or {}` default
- **rehype-highlight unified error** → ESM-only plugin in CJS next.config.js — remove it04Safe Refactor
Improving code structure without changing behavior. Use when you know what needs to change but want Claude to stay strictly in scope.
# Template — Safe Refactor
## Context
Read `CLAUDE.md` before starting.
Read ALL files that will be touched before writing any code:
- [FILE 1]
- [FILE 2]
## What to refactor
[Describe what is structurally wrong and why it needs to change. Be specific.]
Example: "ResultPanel.js has the API URL hardcoded as a string literal on line 47.
It should use `process.env.NEXT_PUBLIC_API_URL` like all other components."
## Exact scope
Files to change:
- `[file path]` — [what changes and why]
Files NOT to change:
- [file that might look related but must not be touched]
## Behavior must not change
The refactor is correct when:
1. [observable behavior that must still work after]
2. [another observable behavior]
Run this to verify:
```bash
[curl command or UI action that proves nothing broke]
```
## Constraints
- Do NOT add new features during a refactor
- Do NOT change function signatures or API response shapes
- Do NOT rename exported functions or components — this breaks imports
- If you find additional refactor opportunities, document as TODO but do NOT fix now
- Make the smallest possible change that achieves the goal
## Why surgical refactors matter
Each line changed is a potential regression. The frontend and backend are coupled
at the API contract level. Renaming a JSON key in the backend breaks the frontend
silently — no TypeScript to catch it. Minimize surface area.05Code Review Request
Independent review of code you've already written, before merging to main.
# Template — Code Review Request
## Context
Read `CLAUDE.md` and `.claude/context/conventions.md` before reviewing.
I have written the following code and want an independent review before merging.
## Files to review
- `[file path]` — [what this file does]
- `[file path]` — [what this file does]
Or: review the diff against main:
```bash
git diff main..HEAD
```
## What I'm most concerned about
- [ ] Security — SQL injection, XSS, input validation
- [ ] Correctness — does the actuarial calculation match the methodology?
- [ ] Edge cases — what inputs would break it?
- [ ] Performance — anything that would block the event loop or cause N+1 queries?
- [ ] API contract — does the response shape match what the frontend expects?
- [ ] Error handling — does it fail gracefully or silently?
## What I'm NOT asking about
- Code style (no linter beyond ruff for Python)
- Test coverage (not required for new features)
- Documentation (covered by build logs in /docs/build-log/)
## Review format I want
For each issue found:
1. **File and line number**
2. **What the problem is**
3. **Why it matters** (not just "bad practice" — what actually breaks?)
4. **The fix** (exact code, not a description)
Rate each issue: Critical (fix before merge) / Minor (fix later) / Nitpick.
## Self-check I've already done
- [ ] Tested with minimum and maximum slider values
- [ ] Tested with zero inputs where division might occur
- [ ] Verified the API response shape against what ResultPanel expects
- [ ] Checked Docker logs after rebuilding06Add Tests
Writing pytest tests for new or existing backend code.
# Template — Add Tests
## Context
Read `CLAUDE.md` before starting.
Read the file(s) to be tested before writing any test code:
- [file to test]
Existing tests (if any) are in `backend/tests/`. Run them with:
```bash
docker compose exec backend pytest
```
## What to test
Module: `[backend/routers/name.py]` or `[backend/functions/name/function.py]`
### Test cases required
| Test | Input | Expected output |
|------|-------|-----------------|
| Happy path | [inputs] | [expected response/return] |
| Edge case — minimum | [inputs] | [expected] |
| Edge case — maximum | [inputs] | [expected] |
| Error case | [invalid input] | [expected error code/message] |
## Test setup
```python
import pytest
import pytest_asyncio
from httpx import AsyncClient
from main import app
@pytest_asyncio.fixture
async def client():
async with AsyncClient(app=app, base_url="http://test") as c:
yield c
```
## Constraints
- Do NOT use mocks for the database — tests run against the actual Docker DB
- If a test requires specific DB state, create it in a pytest fixture and clean up after
- Test file goes in `backend/tests/test_[name].py`
- Test function names: `test_[endpoint_or_function]_[scenario]`
- Each test must be independent — no shared state between tests
## For function.py tests (actuarial computation)
```python
import pytest
import numpy as np
@pytest.mark.asyncio
async def test_mortality_simulator_base_case():
from functions.mortality.function import run
result = await run({"age": 45, "shock_rate": 0})
# Structural checks
assert "table" in result
assert "series" in result
assert "summary" in result
# Domain correctness: life expectancy at 45 with no shock ≈ 27-32 years
le = result["summary"]["life_expectancy"]
assert 25 <= le <= 35, f"Life expectancy {le} outside expected range"
# All survival values between 0 and 100%
for point in result["series"]:
assert 0 <= point["y"] <= 100
```