A web-based tool for digitizing, dating, and organizing a large collection of family photographs.
- Python 63.8%
- TypeScript 25.5%
- CSS 10.2%
- Mako 0.3%
- HTML 0.2%
- Callback now issues a 302 to CIRCA_POST_LOGIN_REDIRECT_URL (default: http://localhost:5173) instead of returning raw JSON, completing the browser-based login flow correctly - Login button label changed from "Sign in with Google" to "Sign in" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| backend | ||
| docs | ||
| frontend | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| LICENSE | ||
| README.md | ||
Circa
A web-based tool for digitizing, dating, and organizing a large collection of family photographs.
Status
Phase 1 is implemented and running. Core review workflow is functional.
Stack
- Backend: Python 3.11+ · FastAPI · SQLAlchemy 2 · Alembic · SQLite (WAL mode)
- Frontend: React 19 · TypeScript · Vite · TanStack Query · React Router v7
- Auth: OAuth/OIDC via Authlib (Google by default) · itsdangerous signed session cookies
- Storage: Local filesystem (content-addressed by SHA-256)
Repo Layout
backend/
app/
api/routes/ — HTTP endpoints (auth, photos, jobs, ingest, health)
auth/ — OAuth client, session helpers
db/ — SQLAlchemy engine and session
models/ — ORM models and enums
repositories/ — DB access layer
services/ — business logic (ingest, projections, storage, parsers)
workers/ — background job scaffold
alembic/versions/ — database migrations
frontend/
src/
api/ — typed fetch client
components/ — AppShell
hooks/ — useAuth
pages/ — Dashboard, PhotoBrowser, ReviewWorkspace, Jobs, Login
types/ — shared TypeScript types
docs/ — product, implementation, UI, wireframe, API, and planning docs
Running Locally
Backend
cd backend
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m alembic upgrade head
.venv/bin/uvicorn app.main:app --reload
The backend starts at http://localhost:8000.
Configuration — copy .env.example to .env or set environment variables with the CIRCA_ prefix:
| Variable | Default | Description |
|---|---|---|
CIRCA_DATABASE_URL |
sqlite:///./circa.db |
SQLAlchemy DB URL |
CIRCA_SECRET_KEY |
change-me-in-production |
Session signing key |
CIRCA_OAUTH_CLIENT_ID |
(empty) | OAuth app client ID |
CIRCA_OAUTH_CLIENT_SECRET |
(empty) | OAuth app client secret |
CIRCA_OAUTH_REDIRECT_URI |
http://localhost:8000/api/auth/callback |
OAuth callback URL |
CIRCA_FIRST_ADMIN_EMAILS |
(empty) | Comma-separated emails promoted to admin on first login |
CIRCA_STORAGE_LOCAL_ROOT |
./storage |
Directory for stored photo files |
Without OAuth credentials configured the app starts but the login button won't complete (for development you can directly create a User in the DB or add a dev-login bypass later).
Frontend
cd frontend
npm install
npm run dev
The frontend starts at http://localhost:5173 and proxies /api to http://localhost:8000.
Phase 1 Capabilities
- Ingest: Upload photos via
POST /api/ingest; exact duplicate detection by SHA-256; filename and EXIF date evidence extracted automatically - Browse: Photo grid with status filters (pending / needs_review / approved / disputed)
- Review workspace: Large image view with front/back toggle; evidence panel; decision form with optimistic concurrency (409 conflict detection); inline notes editing; comments; history tab; AI/OCR rerun job enqueueing; rescan flag
- Jobs: Background job queue visible in the Jobs page (auto-refreshes)
- Auth: Google OAuth login; first-admin bootstrap via env var
Phase 1 Explicit Non-Goals
- Near-duplicate resolution UI
- Album drag reorder
- Backup/restore/export flows
- Full admin console
- Event anchor UI
Docs
docs/circa-spec.md— product specdocs/circa-implementation-spec.md— implementation guidancedocs/circa-wireframes.md— UI wireframesdocs/circa-api-spec.md— API specdocs/circa-phase1-plan.md— Phase 1 engineering plandocs/circa-phase1-backlog.md— Phase 1 ticket backlog