Files
web_server/CLAUDE.md
Adam French d3d3269d49
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m58s
Extract Vue frontend into separate container and add stp_wasm crate
Move Vue app from nginx/vue/ to top-level vue/ with its own Dockerfile,
update docker-compose configs and nginx proxy to serve from the new
container, and add initial Rust WASM crate (stp_wasm). Also fix .gitignore
to exclude Rust target/ directories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:40:45 +00:00

71 lines
3.5 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Run Commands
### Full stack (dev mode, HTTP only)
```
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
```
Dev mode seeds the database with test data (`SEED_DB=true`) and disables certbot/SSL. Visit `http://localhost`.
### Full stack (production, HTTPS)
```
docker compose up --build
```
### Frontend only (hot reload)
```
cd vue && npm run dev
```
Vite dev server proxies `/api` to `localhost:8080`, `/gitea` to `localhost:3000`, `/radio` to `localhost:8000`.
### Frontend build
```
cd vue && npm run build
```
### Regenerate GraphQL (after editing schema files)
```
cd backend && go run github.com/99designs/gqlgen generate
```
This regenerates `graph/generated.go` and `graph/model/models_gen.go`. Resolver implementations in `*.resolvers.go` files are preserved.
## Architecture
Dockerized multi-service personal website self-hosted on a Raspberry Pi.
**Backend** (`backend/`): Go with Gin router. GraphQL API via gqlgen at `POST /api/graphql`. REST endpoints for auth, file uploads, Spotify OAuth, and WebSockets. GORM for PostgreSQL with auto-migrations (no separate migration files). JWT auth stored in HTTP-only cookies.
**Frontend** (`vue/`): Vue 3 SPA with Vite, Tailwind CSS v4, Pinia stores, Vue Router. Built in a separate container; assets served through Nginx (production) or proxied to Vite dev server (dev mode).
**Nginx** (`nginx/`): Reverse proxy + SPA server. Config is templated (`nginx.conf.template`) and selected at runtime by `entrypoint.sh` based on `DEV_MODE` and certificate presence. Rate limiting on login (5/min), API (30/sec), uploads (5/min).
## Backend Structure
- `main.go` — entry point: wires up DB, services, router
- `handlers/store.go``Store` struct holds DB, SpotifyAuth, ClaudeClient, Auth, etc. Passed to all handlers
- `handlers/handle_*.go` — REST handlers grouped by domain
- `graph/schema/*.graphql` — GraphQL schema files (source of truth)
- `graph/*.resolvers.go` — resolver implementations (one per schema file, `follow-schema` layout)
- `graph/generated.go` — auto-generated by gqlgen, do not edit
- `graph/model/models_gen.go` — auto-generated GraphQL models, do not edit
- `models/models.go` — GORM database models (User, Post, Message, Activity, Favorite, Rowing)
- `services/` — database init, JWT auth, WebSocket server, Spotify OAuth, Gitea feed, Claude client, DB seeding
## Frontend Structure
- `src/graphql.js` — thin axios-based GraphQL client (`POST /api/graphql`)
- `src/stores/` — Pinia stores for auth, posts, favorites, activities, songs, messages, homeData
- `src/views/` — page components (Home, Admin, CV, Notes, Bookmarks, shrines)
- `src/components/` — reusable UI components
## Key Patterns
- **GraphQL models vs GORM models**: `gqlgen.yml` maps GraphQL types directly to GORM models in `backend/models`. The `graph/model/` package has only generated input/payload types.
- **Auth flow**: Login sets `access_token` (24h) and `refresh_token` (365h) as HTTP-only cookies. `AuthMiddleware` validates tokens and injects user into Gin context. `AuthContextMiddleware` passes Gin context into GraphQL resolver context.
- **Spotify tokens**: Persisted to `/backend/token/spotify_token.json` inside the container, surviving restarts.
- **Gitea feed**: Backend proxies and caches (1 min TTL) the Gitea activity feed API.
- **All GORM models use soft delete** (`gorm.DeletedAt` field).