Executive summary
Home Cloud is a self-hosted personal cloud for photos and videos. The core goal is simple: keep media on a local drive, but still get a browser-based experience for login, uploads, browsing, previews, and streaming.
The project is split into three apps. apps/cms is Payload CMS running inside Next.js. It owns auth, metadata, access control, and control-plane APIs. apps/frontend is a Vite + React client for login, uploads, asset browsing, and media viewing. apps/fileserver is a Go storage worker and media server for chunked uploads, file assembly, thumbnails, and streaming.
This is an active private build, not a public product launch. The repo shows a real implementation foundation, but the phase audit is clear that the media processing stage is still missing, which blocks newly uploaded assets from becoming fully viewable end to end.
The problem
A normal folder on a hard drive is good storage, but it is not a cloud. It does not give you browser upload, resumable large-file handling, authentication, asset browsing, thumbnails, tags, folders, or video seeking.
Third-party clouds solve those problems, but with tradeoffs. Files live somewhere else, storage becomes a subscription, and the system is shaped around the provider’s product decisions. For a personal archive of photos and videos, especially large video files, that can be the wrong bargain.
The difficult part is that media storage has two different jobs. Metadata and permissions want a structured application backend. Binary uploads and video streaming want a lower-level file server. Trying to make one system do both usually creates pain.
The thesis
Home Cloud uses a control-plane / storage-plane split.
Payload CMS is the control plane. It owns identity, permissions, assets, folders, tags, albums, shares, and custom REST endpoints. It creates upload sessions, stores asset records, protects server-managed fields, and issues short-lived signed URLs for media display.
The Go fileserver is the storage plane. It receives chunks, writes them to temporary storage, assembles final files, stores them on the local drive, serves files by asset ID, validates signed URLs, and supports HTTP range requests for video seeking.
The frontend does not decide storage paths or process media. It logs users in, uploads chunks to Go, reads metadata from Payload, and renders images or videos from signed URLs.
What I built
Monorepo structure
The repository is split into three applications:
apps/cms
Payload CMS v3 inside Next.js 16
apps/frontend
Vite + React client
apps/fileserver
Go storage worker and media server
Payload CMS control plane (apps/cms)
- User auth and role-based access
- Asset records with owner-scoped visibility rules
- Folders, tags, and albums for organisation
- Custom REST endpoints for upload session creation and signed URL issuance
- Server-managed fields protected from client tampering
- Short-lived signed URLs for media display without exposing raw disk paths
React frontend (apps/frontend)
- Login and session handling against Payload
- Chunked upload UI with resume support for large files
- Asset grid with folder navigation and tag filtering
- Media viewer for images and video with seeking via signed URLs
- Thin client: no direct disk access, no storage path decisions in the browser
Go fileserver (apps/fileserver)
- Chunk receipt and temporary staging
- File assembly and write to local disk
- Serve media by asset ID with signed URL validation
- HTTP range requests for video seeking
- Thumbnail generation (processing pipeline integration planned)
Architecture
Browser
→ Vite + React frontend
→ Payload CMS (auth, metadata, signed URLs)
→ Go fileserver (chunks, assembly, streaming)
→ Local disk storage
Postgres
→ Payload collections (users, assets, folders, tags, shares)
Binary files never live in Postgres. Payload owns metadata and permissions; Go owns bytes on disk. The frontend talks to both: Payload for structure and auth, Go for upload chunks and media delivery.
Current status
Active private build. Payload auth, asset records, chunked uploads, upload resume, signed media URLs, owner-scoped access, folder navigation, and tag filtering are implemented. Frontend lint/build, CMS build, and Go compile validation pass.
Blocked on Phase 4 processing: newly uploaded assets do not become fully viewable end-to-end because the processing stage that moves assets to a ready state is not complete. This is an honest gap — the control plane and upload path work; the media-ready pipeline does not.
No public deployment URL or demo link is documented in the repository.