Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"enabledPlugins": {
"mongodb@claude-plugins-official": true
}
}
29 changes: 29 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "FARM Stack To-Do App",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/FARM-Intro",
"forwardPorts": [8000, 3000, 27017],
"portsAttributes": {
"8000": { "label": "FastAPI backend", "onAutoForward": "notify" },
"3000": { "label": "React frontend", "onAutoForward": "openBrowser" },
"27017": { "label": "MongoDB", "onAutoForward": "silent" }
},
"customizations": {
"vscode": {
"extensions": [
"mongodb.mongodb-vscode",
"ms-python.python",
"ms-python.vscode-pylance",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
},
"remoteEnv": {
"DB_URL": "mongodb://localhost:27017/",
"DB_NAME": "farm_intro"
},
"postCreateCommand": "pip install -r backend/requirements.txt && cd frontend && npm install",
"postStartCommand": "echo 'Backend: DB_URL=mongodb://localhost:27017/ DB_NAME=farm_intro uvicorn main:app --reload (from backend/)'"
}
27 changes: 27 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
services:
mongodb:
image: mongodb/mongodb-atlas-local:8.0.3-20250506T093411Z
ports:
- "27017:27017"
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
healthcheck:
test: mongosh --eval "db.adminCommand({ ping: 1 })"
interval: 10s
timeout: 5s
retries: 5

app:
image: mcr.microsoft.com/devcontainers/python:1-3.13-bookworm
network_mode: service:mongodb
volumes:
- ..:/workspaces/FARM-Intro:cached
command: sleep infinity
depends_on:
mongodb:
condition: service_healthy

volumes:
mongodb-data:
mongodb-config:
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
mongodb:
image: mongo:latest
options: >-
--health-cmd mongosh
--health-cmd "mongosh --eval 'db.adminCommand({ ping: 1 })'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
Expand All @@ -30,12 +30,12 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.13"

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "22"

- name: Repo smoke checks
shell: bash
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
fi

- name: Install integration test dependencies
run: pip install pytest pymongo
run: pip install pytest pymongo pydantic-settings

- name: Run integration tests
env:
Expand Down
85 changes: 85 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# AGENTS.md — FARM Stack To-Do App

Agent guide for AI coding assistants working in this repository.

## Build and Test Commands

```bash
# Backend — install and start
cd backend
pip install -r requirements.txt
DB_URL="mongodb://localhost:27017/" DB_NAME="farm_intro" uvicorn main:app --reload

# Frontend — install and start
cd frontend
npm install
npm start

# Tests (no MongoDB needed)
python tests/test_runtime.py

# Integration tests (MongoDB required)
MONGODB_URI="mongodb://localhost:27017/" pytest tests/test_integration.py -v

# Regenerate backend lockfile
cd backend && pip-compile --upgrade requirements.in
```

## Project Structure

```
FARM-Intro/
├── backend/
│ ├── main.py # FastAPI app, lifespan (DB connect/close), appName
│ ├── config/__init__.py # pydantic-settings: DB_URL, DB_NAME, HOST, PORT
│ ├── apps/todo/
│ │ ├── models.py # TaskModel and UpdateTaskModel (pydantic v2)
│ │ └── routers.py # CRUD handlers for /task/ prefix
│ ├── requirements.in # Direct dependencies (source of truth)
│ └── requirements.txt # Pinned lockfile — regenerate with pip-compile
├── frontend/
│ ├── src/App.js # React 18 task list; polls /task/ every 1 s
│ └── package.json # React 18, antd 5, react-scripts 5
├── tests/
│ ├── test_runtime.py # Offline unit test; stubs FastAPI and pymongo
│ └── test_integration.py # Live CRUD tests against MongoDB
├── .github/workflows/ci.yml # CI: Python 3.13, Node 22, mongo:latest service
├── .devcontainer/ # Codespaces/Dev Container with Atlas Local
├── EDD.md # MongoDB data model specification
└── README.md
```

## Environment Variables

| Variable | Required | Default | Description |
|-------------|----------|----------|-----------------------------------|
| `DB_URL` | Yes | — | MongoDB connection string |
| `DB_NAME` | Yes | — | Database name |
| `HOST` | No | `0.0.0.0`| uvicorn bind address |
| `PORT` | No | `8000` | uvicorn port |
| `DEBUG_MODE`| No | `false` | Enable uvicorn auto-reload |

## Key Conventions

- **Pydantic v2**: use `model_config = ConfigDict(...)` and `json_schema_extra`; never `class Config`
- **Lifespan**: DB init/teardown lives in the `@asynccontextmanager lifespan(app)` function in `main.py`; never use `@app.on_event`
- **appName**: the pymongo client is always created with `appName="farm-intro-api"`
- **No seed script**: tasks are created by users; the integration tests create and clean up their own data
- **Collection name**: `tasks` in the database specified by `DB_NAME`
- **Task `_id`**: UUID string (not ObjectId) — see EDD.md

## When To Use EDD.md

Use [EDD.md](./EDD.md) as the source of truth for the MongoDB data model in this repository.

Consult [EDD.md](./EDD.md) before making changes that touch:

- MongoDB collections, document structure, or field names
- FastAPI routes that read or write database records
- Validation, form fields, API payloads, or UI that depend on persisted data
- Schema documentation, Mermaid diagrams, or entity modelling discussions

## MongoDB Skills

Use the official MongoDB agent skills from https://github.com/mongodb/agent-skills
whenever the task is MongoDB-specific and a matching skill exists.
67 changes: 67 additions & 0 deletions EDD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# EDD — Entity Document Diagram

MongoDB data model for the FARM Stack To-Do App.

## Database

| Setting | Value |
|---------------|--------------|
| Database name | `farm_intro` (set via `DB_NAME` env var) |
| Driver | pymongo 4.x `AsyncMongoClient` |
| appName | `farm-intro-api` |

---

## Collections

### `tasks`

Stores to-do tasks created by users.

#### Fields

| Field | BSON type | Required | Notes |
|-------------|-----------|----------|-------------------------------------------|
| `_id` | String | Yes | UUID v4 string (not ObjectId) |
| `name` | String | Yes | Display label for the task |
| `completed` | Boolean | Yes | `false` on creation; `true` when done |

#### Example Document

```json
{
"_id": "00010203-0405-0607-0809-0a0b0c0d0e0f",
"name": "Buy groceries",
"completed": false
}
```

#### Indexes

| Index | Fields | Type | Notes |
|------------|---------|---------|--------------------------|
| `_id_` | `_id` | Default | Created automatically |

No additional indexes are defined. Add an index on `completed` if you add filtering by status.

---

## ER Diagram

```mermaid
erDiagram
TASKS {
string _id PK "UUID v4"
string name
boolean completed
}
```

---

## Notes

- `_id` is a UUID string, not a MongoDB ObjectId. This is intentional so the frontend can use the ID directly without BSON serialisation.
- The `completed` field defaults to `false` in the Pydantic model; callers can omit it on creation.
- Deleting a task is a hard delete; there is no soft-delete or archive.
- The integration tests (`tests/test_integration.py`) create and drop a separate `farm_intro_integration_test` database and do not affect production data.
Loading
Loading