Architecture
How the Go server, embedded SvelteKit app, services, jobs, and storage paths fit together.
Architecture
BoxBox is a single-server web app: a Go HTTP server exposes the API and serves an embedded SvelteKit static build.
Browser
|
| REST, streaming, WebSocket
v
Go server
|-- auth, security headers, rate limits
|-- file, stream, search, job, system, settings handlers
|-- services for filesystem, jobs, auth, search, disk stats
|-- embedded SvelteKit frontend
v
Configured host/container mount points
Runtime Model
The production Dockerfile has three stages:
- Build the SvelteKit frontend with Bun.
- Copy the static frontend into
backend/internal/static/distand compile the Go server. - Run the resulting binary in a small Alpine image.
At runtime there is one HTTP process. API routes are matched first; all other routes fall through to the embedded SPA frontend.
Backend Packages
backend/
cmd/server/ entrypoint, router, service wiring
internal/config/ config loading and runtime constants
internal/handler/ HTTP handlers
internal/middleware/ auth, rate limit, security, mount guards
internal/model/ config, file, job, error, drive models
internal/pkg/ filesystem, file utility, path validation helpers
internal/service/ auth, file, search, job, system, settings services
internal/static/ embedded frontend assets
internal/websocket/ hub, client, message protocol
Request Flow
File listing:
GET /api/v1/files/home/projects
-> JWT middleware
-> mount point guard
-> FileHandler.GetPath
-> FileService.List or FileService.GetInfo
-> filesystem abstraction
Chunked upload:
POST /api/v1/stream/upload/home/file.zip
-> JWT middleware
-> mount point guard
-> StreamHandler.Upload
-> UploadManager temp chunk storage
-> checksum verification
-> atomic final rename
Background copy or move:
POST /api/v1/jobs
-> JobHandler.Create
-> JobService queue
-> worker pool
-> filesystem copy/move/delete
-> WebSocket progress updates
Frontend App
frontend/src/
routes/ SvelteKit routes
lib/api/ typed API functions
lib/components/ app UI and preview components
lib/components/ui/ reusable base UI primitives
lib/stores/ auth, files, jobs, upload, websocket state
lib/types/ shared TypeScript types
lib/utils/ upload, file type, formatting, storage helpers
The frontend uses a same-origin API base of /api/v1. In production the browser talks to the same Go server that served the app.
State and Persistence
Most server state is intentionally lightweight:
- Auth refresh-token revocations are in memory.
- Jobs are in memory and cleaned after a retention period.
- Upload sessions are in memory with temporary chunks on disk.
- Custom drive names are persisted under
/data/drive-names.json. - Files themselves remain on mounted host paths.
Security Boundaries
The important boundaries are:
- JWT authentication for API access.
- Mount point resolution and traversal prevention.
- Read-only mount point enforcement.
- Container volume boundaries.
- Reverse proxy and network exposure.
Because BoxBox can modify host files, mount scope and credentials matter more than traditional database permissions.