Table of Contents
- Development Guide
Development Guide
Getting Started
Prerequisites
- Docker + Docker Compose
- Node.js 18+ (for frontend dev)
- Python 3.11+ (for backend dev)
- SSH access to ub01
Local Development
The simplest approach is working directly on ub01:
ssh ub01
cd /vmPool/r/repos/xpltdco/chrysopedia
For frontend-only work, you can run Vite locally and proxy to the remote API:
cd frontend
npm install
npm run dev # Vite dev server with /api proxy to localhost:8001
Project Structure
chrysopedia/
├── backend/
│ ├── config.py # Settings (env vars, LRU cached)
│ ├── database.py # Async SQLAlchemy engine + session
│ ├── main.py # FastAPI app, router registration
│ ├── models.py # All 13 SQLAlchemy models
│ ├── schemas.py # Pydantic request/response schemas
│ ├── search_service.py # Async search (Qdrant + keyword fallback)
│ ├── redis_client.py # Async Redis client
│ ├── watcher.py # Transcript folder watcher
│ ├── routers/ # FastAPI route handlers
│ ├── pipeline/ # Celery pipeline stages
│ │ ├── stages.py # Stage implementations
│ │ └── quality/ # Prompt quality toolkit
│ ├── services/ # Business logic services
│ └── tests/ # pytest test suite
├── frontend/
│ └── src/
│ ├── App.tsx # Routes, layout
│ ├── App.css # All styles (5,820 lines)
│ ├── main.tsx # React entry point
│ ├── api/ # API client (public-client.ts)
│ ├── pages/ # Page components (11)
│ ├── components/ # Shared components (11+)
│ ├── hooks/ # Custom hooks (3)
│ └── utils/ # Utilities (citations, slugs)
├── prompts/ # LLM prompt templates
├── alembic/ # DB migrations (if configured)
├── docker-compose.yml
├── Dockerfile.api
├── Dockerfile.web
└── CLAUDE.md # AI agent development reference
Common Gotchas
asyncpg Timestamp Errors
Use datetime.now(timezone.utc).replace(tzinfo=None) for all timestamp defaults. asyncpg rejects timezone-aware datetimes for TIMESTAMP WITHOUT TIME ZONE columns.
SQLAlchemy Column Name Conflicts
Never name a column relationship, query, or metadata — these shadow ORM functions. Use from sqlalchemy.orm import relationship as sa_relationship if the schema requires it.
Vite Build Constants
Always wrap with JSON.stringify(): define: { __APP_VERSION__: JSON.stringify(version) }. Without it, the built code gets unquoted values (syntax error).
Docker ARG/ENV Ordering
ARG VITE_FOO=default → ENV VITE_FOO=$VITE_FOO → RUN npm run build. The ENV line must appear before the build step.
Slim Docker Images
python:3.x-slim doesn't include procps (no pgrep, ps). Use python -c "import os; os.kill(1, 0)" for healthchecks.
Host Port 8000 Conflict
Port 8000 on ub01 may be used by kerf-engine. Use 8001 for local testing, or ensure kerf-engine is stopped.
Nginx Stale DNS
After rebuilding API container, restart the web container: docker compose restart chrysopedia-web-8096.
ZFS Filesystem Watchers
Use watchdog.observers.polling.PollingObserver instead of the default inotify observer — inotify doesn't reliably detect changes on ZFS/NFS.
File Stability for SCP Uploads
Wait for file size stability (check twice with 2-second gap) before processing files received via SCP/rsync.
Testing
cd backend
python -m pytest tests/ -v
Tests use:
NullPoolfor async engine (prevents connection pool contention)- Module-level patching for Celery stage globals (
_engine,_SessionLocal) patch('pipeline.stages.run_pipeline')for lazy import mocking (not at the router level)
Adding New Features
New API Endpoint
- Create router in
backend/routers/foo.pywithAPIRouter(prefix="/foo", tags=["foo"]) - Register in
backend/main.py:app.include_router(foo.router, prefix="/api/v1") - Define schemas in
backend/schemas.py - Use paginated response:
{items, total, offset, limit}
New Frontend Route
- Add
<Route>toApp.tsx - Create page component in
frontend/src/pages/ - Call
useDocumentTitle()in the component - Add API functions to
public-client.ts
New Database Model
- Add to
backend/models.py - Add schemas to
backend/schemas.py - Apply DDL manually or via Alembic migration
- Use
_now()helper for timestamp defaults
New CSS
- Append to
App.cssusing BEM naming - Use CSS custom properties for all colors
- Prefer 768px breakpoint for mobile/desktop split
- Namespace Phase 2 selectors:
.p2-feature__element
See also: Architecture, Frontend, Deployment
Chrysopedia Wiki
Architecture
Features
- Chat-Engine
- Search-Retrieval
- Highlights
- Personality-Profiles
- Posts (via Post Editor)
Reference
Operations