How maxbrc/photo-portfolio works
1. Overall shape
- This repo is a three-part application: a Go backend, a TypeScript/React frontend, and a MariaDB database.
- In production, everything is containerized with Docker Compose; the backend is the main externally exposed service, while the frontend is a separate Node-based runtime/build target.
2. Backend entrypoint and responsibilities
- The backend starts from backend/cmd/main.go.
- It wires configuration, database access, HTTP routes, authentication, album/image services, and filesystem-backed site data.
- The backend is responsible for all business logic and all privileged admin operations.
3. HTTP API layer
- backend/api/routes.go and backend/api/handlers/* define the REST surface.
- The handlers are split by resource and action: albums, images, users, login/refresh, site content, photo serving, and cleanup.
- This suggests a classic request flow: HTTP handler parses request → internal service package executes logic → DB/filesystem response is returned.
4. Domain/service boundaries in the backend
- backend/internal/albums, backend/internal/images, and backend/internal/auth hold the core application logic.
- These packages keep HTTP concerns separate from persistence and domain behavior.
- backend/internal/models provides shared data shapes used across handlers, DB, and services.
5. Persistence layer
- backend/internal/db/* is the database access layer for users, albums, and images.
- The app uses MariaDB/MySQL for structured data such as users, album metadata, image metadata, and assignments.
- db/init.go indicates the backend likely initializes or verifies schema on startup rather than relying on a separate migration system.
6. Authentication and authorization
- Authentication is handled in backend/internal/auth.
- Password hashing and JWT support are explicit, and the README says JWTs are signed with an Ed25519 private key seed stored in the mounted data/secrets directory.
- The API includes login and refresh-token endpoints, so auth is token-based and likely protects admin routes.
7. Filesystem-backed application state
- Not all state lives in the database. The README and code structure show a mounted data directory containing:
- config.json for site/homepage content
- photos/ for actual image files
- secrets/ for JWT signing material
- backend/api/handlers/get_site_content.go and patch_site_content.go indicate the homepage/config data is edited through the API but stored on disk, not in MariaDB.
8. Image pipeline
- Images are managed through backend/internal/images and the related handlers.
- The storage layout distinguishes between photos/originals and photos/derivatives.
- The README describes derivative filenames as resized/cached WebP variants, so image requests likely flow through backend logic that serves originals or generated derivatives and may create/update cached versions.
9. Album and gallery model
- Albums appear to be a first-class domain with CRUD plus image assignment endpoints.
- The presence of get_albums_assignments.go and put_albums_assignments.go indicates a separate relationship between albums and images, not just flat metadata.
- Public gallery browsing likely consumes album/image metadata from the backend and image URLs from the photo subsystem.
10. Frontend structure
- The frontend is a React + TypeScript app under frontend/client/src.
- It is split into public pages/components (Home, Gallery, Albums, ImageBrowser, Header, Footer, Login, Impressum) and admin screens (Admin* components).
- This suggests one frontend codebase with two major navigation areas: visitor-facing portfolio and authenticated administration.
11. Frontend build/runtime split
- frontend/webpack.*.js handles the client bundle build.
- frontend/server/src/index.tsx and build-server.mjs indicate there is also a server-side Node build path, likely used to serve or render the frontend in production.
- The frontend therefore has both a browser bundle and a server runtime, even though the backend remains the primary API/data authority.
12. Deployment and runtime topology
- Docker Compose wires three services: db, backend, and frontend.
- The backend container gets DB_HOST=db and NODE_URL=http://frontend:3010, while the frontend depends on the backend.
- Persistent state is split across a MariaDB volume and a mounted application-data directory for config, photos, and secrets.
13. Key architectural boundary
- The most important boundary in this repository is between structured data in MariaDB and unstructured/media/site state on disk.
- The backend bridges both worlds: it reads/writes DB entities, manages authentication, and also serves/manipulates files under the mounted data directory.
Main entry points: main.go Main · handlers Handlers · db DB layer · images Images
Components 17
Backend
Go API, auth, domain logic, and persistence bridge.
- Main · Starts the backend and wires configuration, routes, services, and storage.
backend/cmd/main.go - Routes · Defines the API surface and connects handlers to endpoints.
backend/api/routes.go - Handlers · REST handlers for albums, images, users, login/refresh, site content, photo serving, and cleanup.
backend/api/handlers - Albums · Album CRUD and album-image assignment workflows.
backend/internal/albums - Images · Image upload, retrieval, update, delete, and cleanup logic including derivatives.
backend/internal/images - Auth · Password hashing, JWT creation/verification, and user auth flows.
backend/internal/auth - DB layer · MariaDB/MySQL persistence for users, albums, and images.
backend/internal/db - Models · Shared application data shapes used across handlers, services, and persistence.
backend/internal/models - Config · Loads backend configuration and defaults.
backend/config/config.go
Frontend
React/TypeScript app with browser and server build targets.
- App · Top-level client application shell and routing.
frontend/client/src/components/App.tsx - Public UI · Home, gallery, albums, image browser, header/footer, impressum, and login screens.
frontend/client/src/components - Admin UI · Authenticated administration dashboard and resource management views.
frontend/client/src/components/Admin.tsx - Client types · Frontend request/response and view-model type definitions.
frontend/client/src/types - Browser build · Client bundle compilation for the browser runtime.
frontend/client/webpack.prod.js - SSR server · Server-side frontend runtime entry used in production packaging.
frontend/server/src/index.tsx
Runtime
Container composition and external data services.
- Compose · Defines the backend, frontend, and database containers and their wiring.
docker/docker-compose.dev.yml - MariaDB · Persistent relational store for structured application data.
Connections 27
- Main → Config: loads · Initializes configuration before starting the server.
- Main → Routes: mounts · Wires the HTTP router and handlers into the backend process.
- Main → DB layer: initializes · Connects to and verifies the database layer on startup.
- Main → Auth: uses · Configures authentication and token handling.
- Main → Albums: uses · Registers album business logic.
- Main → Images: uses · Registers image business logic.
- Routes → Handlers: dispatches to · Routes requests to resource-specific handlers.
- Handlers → Albums: calls · Album endpoints delegate to album domain logic.
- Handlers → Images: calls · Image and photo endpoints delegate to media logic.
- Handlers → Auth: calls · Login, refresh, and user protection rely on auth logic.
- Handlers → DB layer: reads/writes · Admin endpoints persist structured data through the DB layer.
- Handlers → Models: marshals · Handlers exchange shared payload shapes with clients.
- Albums → DB layer: persists via · Album state and assignments are stored in MariaDB.
- Images → DB layer: persists via · Image metadata is stored in MariaDB.
- Images → Models: uses · Image operations use shared model types.
- Auth → DB layer: loads users · Authentication resolves user records from persistence.
- App → Public UI: navigates to · Main app exposes the visitor-facing pages.
- App → Admin UI: navigates to · Main app exposes the authenticated admin area.
- Public UI → Client types: uses · Public views consume typed API data and site content shapes.
- Admin UI → Client types: uses · Admin screens consume typed resources and action payloads.
- Browser build → App: builds · Produces the browser client bundle.
- SSR server → App: serves · Uses the app as the server-side frontend entry.
- Compose → Main: runs · Starts the Go backend container.
- Compose → SSR server: runs · Starts the frontend container/runtime.
- Compose → MariaDB: provides · Supplies the database service to the backend.
- DB layer → MariaDB: connects to · Database access layer talks to MariaDB.
- SSR server → Routes: API client · Frontend runtime depends on the backend API surface.