How gutslike/image-manager works
Purpose and Entry Points
Image Service is a self-hosted Go binary for converting uploads to WebP, storing objects in cloud storage, and tracking image/folder metadata locally. Its primary entry point is cmd/image-service/main.go; Cobra commands under cmd/image-service/cmd/root.go expose setup, server/UI, provider, and image-management workflows.
CLI Orchestration
The CLI is the operational control plane: setup creates configuration and provider profiles; start launches headless HTTP serving; ui additionally opens the dashboard; upload/list/delete operate against the same service layers. Key paths: cmd/image-service/cmd/setup.go, cmd/image-service/cmd/start.go, cmd/image-service/cmd/upload.go.
HTTP API and Dashboard Surface
The server exposes JSON APIs for uploads, images, folders, health, and stats, plus HTML partial endpoints for HTMX-driven dashboard updates. Routing and request/response handling are separated in internal/api/router.go and internal/api/handlers.go. Embedded templates ensure the binary carries its UI: web/embed.go, web/templates/layout.html, and web/templates/partials/.
Upload Processing Pipeline
Uploads from CLI or multipart HTTP flow through service logic: MIME/size validation, decode/orientation handling, WebP conversion at configured quality, UUID/date-path generation, remote object upload, then local metadata persistence. The main boundaries are orchestration in internal/services/upload.go, image transformation in internal/compression/processor.go, and shared image/folder types in internal/models/image.go. If metadata persistence fails after storage succeeds, the object is deleted to avoid drift.
Metadata and Folder Model
SQLite is the local system of record for image metadata and folder membership, including schema migration. Folder operations only change database relationships; they never alter provider object paths or public URLs. Metadata is isolated in internal/metadata/db.go; higher-level image/folder operations are in internal/services/image.go. Loss of the local database affects organization and history, not cloud-hosted objects.
Storage Provider Boundary
internal/storage/adapter.go defines the provider abstraction used by service code for upload, deletion, and connectivity operations. Cloudflare R2 is implemented in internal/storage/cloudflare.go; configuration also supports Supabase Storage and Cloudinary profiles. Objects live remotely under date-based YYYY/MM/DD/UUID.webp keys and are served directly by provider/CDN URLs, so the application need not remain online for existing images.
Runtime, Configuration, and Infrastructure
The application requires Go with CGO/libwebp and a C compiler when built from source; SQLite uses the pure-Go modernc.org/sqlite runtime. YAML configuration selects active provider, server bind/port, local database path, upload limits, and WebP quality via internal/config/config.go. Core external infrastructure is Cloudflare R2/S3-compatible object storage, Supabase Storage, or Cloudinary; GitHub Actions builds releases through .github/workflows/build.yml.
Main entry points: upload.go Upload orchestration · root.go Cobra commands · start.go Start command · router.go HTTP router
Components 18
CLI Control Plane
- Go binary entry · Builds the CLI application.
cmd/image-service/main.go - Cobra commands · Setup, server/UI, provider, and image workflows.
cmd/image-service/cmd/root.go - Setup command · Creates configuration and provider profiles.
cmd/image-service/cmd/setup.go - Start command · Launches headless HTTP serving.
cmd/image-service/cmd/start.go - Upload command · Sends uploads through shared service logic.
cmd/image-service/cmd/upload.go
Application Runtime
- YAML configuration · Selects provider, server, database, limits, and WebP quality.
internal/config/config.go - HTTP router · Maps JSON and HTMX dashboard endpoints.
internal/api/router.go - API handlers · Handles uploads, images, folders, health, and stats.
internal/api/handlers.go - Embedded dashboard · Templates are compiled into the binary.
web/embed.go - Upload orchestration · Validates, transforms, stores, persists metadata, and compensates on failure.
internal/services/upload.go - WebP processor · Decodes, applies orientation, and converts images.
internal/compression/processor.go - Image and folder service · Manages metadata and folder relationships without moving objects.
internal/services/image.go - Image/folder models
internal/models/image.go
Data and Storage
- SQLite metadata · System of record for metadata, folders, and migrations.
internal/metadata/db.go - Storage adapter · Defines upload, deletion, and connectivity operations.
internal/storage/adapter.go - Cloudflare R2 provider · S3-compatible remote object storage implementation.
internal/storage/cloudflare.go - Configured cloud provider · R2, Supabase Storage, or Cloudinary serves stored images directly.
Build and Delivery
- Release build · Builds release binaries with Go, CGO/libwebp, and a C compiler.
.github/workflows/build.yml
Connections 22
- Go binary entry → Cobra commands: initializes
- Cobra commands → Setup command: runs
- Cobra commands → Start command: runs
- Cobra commands → Upload command: runs
- Setup command → YAML configuration: writes
- Start command → YAML configuration: loads
- Start command → HTTP router: serves
- HTTP router → API handlers: dispatches
- HTTP router → Embedded dashboard: renders
- Upload command → Upload orchestration: uploads via
- API handlers → Upload orchestration: multipart uploads
- API handlers → Image and folder service: image/folder operations
- Upload orchestration → WebP processor: converts to WebP
- Upload orchestration → Storage adapter: uploads and compensates
- Upload orchestration → SQLite metadata: persists metadata
- Image and folder service → SQLite metadata: manages relationships
- Upload orchestration → Image/folder models: uses
- Image and folder service → Image/folder models: uses
- Storage adapter → Cloudflare R2 provider: implemented by
- Cloudflare R2 provider → Configured cloud provider: stores date/UUID WebP keys
- YAML configuration → Storage adapter: selects provider
- Release build → Go binary entry: builds release