diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a1d90897..71619e23 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,6 +4,50 @@ Voyage is a self-hosted travel companion web application built with SvelteKit fr **ALWAYS follow these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.** +## Architecture + +**Stack**: SvelteKit 2 (TypeScript) frontend · Django REST Framework (Python) backend · PostgreSQL + PostGIS database · Memcached · Docker · Bun (frontend package manager) + +**Key architectural pattern — API Proxy**: The frontend never calls the Django backend directly. All API calls go to `src/routes/api/[...path]/+server.ts`, which proxies requests to the Django server (`http://server:8000`), injecting CSRF tokens and managing session cookies. This means frontend fetches use relative URLs like `/api/locations/`. + +**Services** (docker-compose): +- `web` → SvelteKit frontend at `:8015` +- `server` → Django (via Gunicorn + Nginx) at `:8016` +- `db` → PostgreSQL + PostGIS at `:5432` +- `cache` → Memcached (internal) + +**Authentication**: Session-based via `django-allauth`. CSRF tokens fetched from `/auth/csrf/` and passed as `X-CSRFToken` header on all mutating requests. There's also a `X-Session-Token` header path for mobile clients (handled in middleware). + +## Codebase Conventions + +**Backend layout**: The Django project lives in `backend/server/`. Apps are `adventures` (core: locations, collections, itineraries, notes, transportation), `users`, `worldtravel` (countries/regions), and `integrations`. Views inside `adventures` are split into per-domain files under `adventures/views/` (e.g. `location_view.py`, `collection_view.py`). + +**Backend patterns**: +- DRF `ModelViewSet` subclasses for all CRUD resources; custom actions with `@action` +- `get_queryset()` always filters by `user=self.request.user` to enforce ownership +- `GenericForeignKey` (`content_type` + `object_id`) used in `CollectionItem` to allow collections to contain heterogeneous items +- Background geocoding runs in a daemon thread via `threading.Thread` +- Money fields use `djmoney` (`MoneyField`); geospatial queries use PostGIS via `django-geojson` + +**Frontend layout**: Source lives in `frontend/src/`. Pages are in `src/routes/` (file-based SvelteKit routing). Shared code lives in `src/lib/`: +- `src/lib/types.ts` — all TypeScript interfaces (`Location`, `Collection`, `User`, `Visit`, etc.) +- `src/lib/index.ts` — general utility functions +- `src/lib/index.server.ts` — server-only utilities (used in `+page.server.ts` and `+server.ts` files) +- `src/lib/components/` — Svelte components organized by domain (`locations/`, `collections/`, `map/`, `cards/`, `shared/`) +- `src/locales/` — i18n JSON files (uses `svelte-i18n`); wrap all user-visible strings in `$t('key')` + +**Frontend patterns**: +- Use `$t('key')` from `svelte-i18n` for all user-facing strings; add new keys to locale files +- API calls always use `credentials: 'include'` and the `X-CSRFToken` header (get token from the `csrfToken` store/prop) +- Reactive state updates require reassignment to trigger Svelte reactivity: `items[i] = updated; items = items` +- DaisyUI component classes (e.g. `btn`, `card`, `modal`) plus Tailwind utilities for layout; use daisyUI semantic color names (`bg-primary`, `text-base-content`) not raw Tailwind colors so themes work +- Map features use `svelte-maplibre` with MapLibre GL; geospatial data is GeoJSON + +**Running a single Django test**: +```bash +docker compose exec server python3 manage.py test adventures.tests.TestLocationAPI +``` + ## Working Effectively ### Essential Setup (NEVER CANCEL - Set 60+ minute timeouts) diff --git a/.gitignore b/.gitignore index 32668163..e88171b6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,4 @@ docs/GITHUB_COMMENTS.md BUGFIX_DOCUMENTATION.md # Local agent knowledge DB / cache -.megamemory/ +.memory/ diff --git a/AGENTS.md b/AGENTS.md index f26a9d18..f5b3000a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,63 +1,61 @@ -# Voyage Agent Project Notes +# Voyage Development Instructions (OpenCode) -This file captures project-local commands and conventions for working in the Voyage repository. +## Project +- **Name**: Voyage +- **Purpose**: Self-hosted travel companion web app (fork of AdventureLog) +- **Stack**: SvelteKit 2 (TypeScript) frontend · Django REST Framework (Python) backend · PostgreSQL + PostGIS · Memcached · Docker · Bun (frontend package manager) -## Frontend (SvelteKit) +## Architecture Overview +- **API proxy pattern**: Frontend never calls Django directly. All API calls go through `frontend/src/routes/api/[...path]/+server.ts`, which proxies to `http://server:8000`, handles cookies, and injects CSRF behavior. +- **Service ports**: + - `web` → `:8015` + - `server` → `:8016` + - `db` → `:5432` + - `cache` → internal only +- **Authentication**: Session-based via `django-allauth`; CSRF token from `/auth/csrf/`; mutating requests send `X-CSRFToken`; mobile middleware path supports `X-Session-Token`. -- Working directory: `frontend/` -- Package manager: `bun` -- Install dependencies: `bun install` -- Dev server: `bun run dev` (Vite dev server; frontend is configured to work with the Django backend in development) -- Build: `bun run build` -- Preview production build: `bun run preview` -- Type check: `bun run check` (`svelte-check`) -- Lint: `bun run lint` (currently runs `prettier --check .`; no ESLint config file is present right now) -- Format: `bun run format` (runs `prettier --write .`) -- Type check (watch mode): `bun run check:watch` +## Codebase Layout +- **Backend**: `backend/server/` + - Apps: `adventures/`, `users/`, `worldtravel/`, `integrations/`, `achievements/`, `chat/` +- **Frontend**: `frontend/src/` + - Routes: `src/routes/` + - Shared types: `src/lib/types.ts` + - Components: `src/lib/components/` + - i18n: `src/locales/` -## Backend (Django + DRF) +## Development Commands -- Working directory: `backend/server/` -- Python environment: use project-root `.venv/` if available, otherwise standard Django/Python environment setup -- Install dependencies: `pip install -r requirements.txt` -- Run development server: `python manage.py runserver` -- Apply migrations: `python manage.py migrate` -- Create admin user: `python manage.py createsuperuser` -- Run tests: `python manage.py test` -- Django app locations: - - `backend/server/adventures/` - - `backend/server/achievements/` - - `backend/server/integrations/` - - `backend/server/main/` - - `backend/server/users/` - - `backend/server/worldtravel/` -- Linting: `ruff check .` -- Formatting: `ruff format .` +### Frontend +- `cd frontend && npm run format` +- `cd frontend && npm run lint` +- `cd frontend && npm run check` +- `cd frontend && npm run build` -## Docker Compose Workflows +### Backend +- `docker compose exec server python3 manage.py test` +- `docker compose exec server python3 manage.py migrate` -- Development stack: `docker compose -f docker-compose.dev.yml up` -- Production-like stack: `docker compose up` -- Traefik stack: `docker compose -f docker-compose-traefik.yaml up` -- Rebuild images after changes: add `--build` to the selected command +### Docker +- `docker compose up -d` +- `docker compose down` -## Testing Notes +## Pre-Commit Checklist +Run in this order: +1. `cd frontend && npm run format` +2. `cd frontend && npm run lint` +3. `cd frontend && npm run check` +4. `cd frontend && npm run build` -- Frontend tests: no `test` script is currently defined in `frontend/package.json` -- Backend tests: run `python manage.py test` from `backend/server/` +## Known Issues (Expected) +- Frontend `npm run check`: **3 type errors + 19 warnings** expected +- Backend tests: **2/3 fail** (expected) +- Docker dev setup has frontend-backend communication issues (500 errors beyond homepage) -## Code Style and Quality +## Key Patterns +- i18n: use `$t('key')` for user-facing strings +- API calls: route through proxy at `/api/[...path]/+server.ts` +- Styling: use DaisyUI semantic colors/classes (`bg-primary`, `text-base-content`, etc.) +- Security: handle CSRF tokens via `/auth/csrf/` and `X-CSRFToken` -- Python style tooling: Ruff (`ruff check .` and `ruff format .`) -- Ruff config location: no `pyproject.toml` or `ruff.toml` was found in this repository, so Ruff defaults (or editor/tooling settings) apply unless added later -- TypeScript/Svelte style tooling: Prettier is configured in `frontend/.prettierrc`; ESLint config files are not currently present -- Commit style: Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`) - -## Project Structure Quick Reference - -- Frontend source: `frontend/src/` -- Backend apps: `backend/server//` -- Documentation site: `documentation/` (VitePress) -- Container images: - - `ghcr.io/alex-wiesner/voyage-frontend` - - `ghcr.io/alex-wiesner/voyage-backend` +## Conventions +- Do **not** attempt to fix known test/configuration issues as part of feature work. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..ed42e71b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,69 @@ +# Voyage Development Instructions (Claude Code) + +## Project +- **Name**: Voyage +- **Purpose**: Build and maintain a self-hosted travel companion web app (fork of AdventureLog). +- **Stack**: SvelteKit 2 (TypeScript) frontend · Django REST Framework (Python) backend · PostgreSQL + PostGIS · Memcached · Docker · Bun (frontend package manager) + +## Architecture Overview +- Use the API proxy pattern: never call Django directly from frontend components. +- Route all frontend API calls through `frontend/src/routes/api/[...path]/+server.ts`. +- Proxy target is `http://server:8000`; preserve session cookies and CSRF behavior. +- Service ports: + - `web` → `:8015` + - `server` → `:8016` + - `db` → `:5432` + - `cache` → internal only +- Keep authentication session-based with `django-allauth`. +- Fetch CSRF token from `/auth/csrf/` and send `X-CSRFToken` on mutating requests. +- Preserve mobile middleware support for `X-Session-Token`. + +## Codebase Layout +- Backend root: `backend/server/` + - Apps: `adventures/`, `users/`, `worldtravel/`, `integrations/`, `achievements/`, `chat/` +- Frontend root: `frontend/src/` + - Routes: `src/routes/` + - Shared types: `src/lib/types.ts` + - Components: `src/lib/components/` + - Locales: `src/locales/` + +## Development Workflow +- Develop Docker-first. Start services with Docker before backend-dependent work. +- Use these commands: + +### Frontend +- `cd frontend && npm run format` +- `cd frontend && npm run lint` +- `cd frontend && npm run check` +- `cd frontend && npm run build` + +### Backend +- `docker compose exec server python3 manage.py test` +- `docker compose exec server python3 manage.py migrate` + +### Docker +- `docker compose up -d` +- `docker compose down` + +## Pre-Commit Checklist +Run in this exact order: +1. `cd frontend && npm run format` +2. `cd frontend && npm run lint` +3. `cd frontend && npm run check` +4. `cd frontend && npm run build` + +**ALWAYS run format before committing.** + +## Known Issues (Expected) +- Frontend `npm run check`: **3 type errors + 19 warnings** expected +- Backend tests: **2/3 fail** (expected) +- Docker dev setup has frontend-backend communication issues (500 errors beyond homepage) + +## Key Patterns +- i18n: wrap user-facing strings with `$t('key')` +- API access: always use proxy route `/api/[...path]/+server.ts` +- Styling: prefer DaisyUI semantic classes (`bg-primary`, `text-base-content`) +- CSRF handling: use `/auth/csrf/` + `X-CSRFToken` + +## Conventions +- Do **not** attempt to fix known test/configuration issues as part of feature work.