Scaffolding
The .NET 10 solution, the library’s data model, and the API contracts the web app shares with the phone apps to come.
Self-hosted photo library
PhotoBlad is a self-hosted photo library. It runs on a computer you control, reads the folders your photos already live in and shows them in a web gallery, without ever changing a file.
Phases 1–7, editing and storage across drives done. The repository is private for now.
















Låt bladet vara. Let the leaf be.
The name
Blad is Swedish for a leaf, and for a sheet of paper. PhotoBlad keeps each photograph whole, and leaves it where you put it.
What it is
PhotoBlad is an alternative to Google Photos that you host yourself. Point it at your photo folders and it builds a library you browse in your web browser, with thumbnails, photo details and a justified grid. Your family can back up photos and videos to it from their browsers, privately unless they choose to share. Phone apps with automatic backup are in progress.
It’s built with .NET 10 and Microsoft Aspire. The web app is Blazor WebAssembly, the library is a SQLite database in PhotoBlad’s own data folder, and videos are processed by FFmpeg when it’s installed. Run it from source, or as two containers with Docker or Podman Compose, reached through Caddy on your own domain or privately through Tailscale.
Privacy and security in detailPhoto folders are only ever read, and a backup is written once and never changed. What PhotoBlad makes, such as its database and thumbnails, goes into its own data folder: ~/.photoblad unless you choose another.
PhotoBlad runs on your own computer or server. Your library, your family’s backups, the database and the thumbnails stay on that machine.
What you back up is yours alone, hidden even from the owner, until you share it with the family. Anything you can’t see answers exactly as if it didn’t exist.
Each browser and phone signed in has its own session on the server. Settings → Devices lists them, and signing one out ends it at once.
The web app gets everything from your server, fonts included, and shows GPS positions as coordinates instead of calling a map service.
Accounts use a username, and PhotoBlad never sends email. The owner makes a new sign-in link for a member who forgets their password; the owner’s own is reset from the command line on the server.
Features
Read-only scanning
Point PhotoBlad at the folders your photos already live in. It reads them and never moves, renames, re-encodes or deletes a file.
JPEG, PNG, WebP and HEIC
The date, camera, lens, exposure and GPS position are read from each photo’s EXIF data, HEIC included.
Quick rescans
Files that haven’t changed are skipped without being read again. A renamed or moved photo keeps its place, and identical copies are listed once.
Thumbnails, made once
Small WebP thumbnails are made while indexing and kept in PhotoBlad’s data folder. Large previews are made the first time a photo is opened.
The Darkroom gallery
A justified photo grid that only draws the rows on screen, and a lightbox you can step through with the arrow keys. It fits phone screens too.
Photo details
When a photo was taken, with which camera and lens, its exposure, size and file. GPS shows as coordinates, with no call to a map service.
Scans from the browser
Start a scan from the web app and follow its progress live. The gallery reloads when the scan finishes.
Two services, one command
Aspire starts the Server (web app and API) and the Indexer (scanning) together, with a dashboard for logs and health.
Accounts for your household
An owner and family members share one library: the folders the owner scans. The owner invites members with single-use links.
Passwords and passkeys
Sign in with a username and a password or a passkey. There’s no email address to give, and PhotoBlad never sends email.
A setup code on first run
The first start prints a one-time setup code in the Server log. Enter it at /setup to create the owner account, so nobody else can claim a new install.
Backups from the browser
Anyone signed in can back up photos and videos with the Upload button or the drop zone. Each file’s hash is checked first, so nothing you’ve backed up is sent twice.
Written once, in plain folders
Backups are kept byte for byte, under their own names, in plain folders that open without PhotoBlad, ~/PhotoBlad/Uploads to begin with. PhotoBlad never changes or overwrites one.
Sharing, when you choose
Your backups are private, even from the owner, until you share them in Settings → Sharing. The gallery shows Everything, the Family library or My backups.
A session for every device
Each browser and phone signed in has a session of its own. Settings → Devices lists them and signs any one out at once, phones included.
Videos
MP4, M4V, MOV, 3GP, WebM, MKV and AVI, with posters, playback in the browser and seeking. FFmpeg is optional: without it, videos are still backed up and listed.
Playback copies
A video that not every browser can play gets an H.264 copy for playing, made in the background. The copy is disposable, and the original is never changed.
Live Photos
A Live Photo is one tile with a LIVE badge. Open it and press to play the motion; download the photo or its motion clip.
Download original
Every photo and video you can see downloads exactly as it was stored, byte for byte.
Non-destructive editing
Crop, rotate, straighten, light, colour and filters, previewed live as you drag. The edits are stored beside the photo and the edited look is made from the original, which is never modified.
Details you can correct
Fix a date or a place, add a caption and tags, and mark favourites, which stay private to you. The camera’s own values are kept, and nothing is written into the file.
Video trims
Keep just the part of a video you want. Download it as a quick lossless copy, or as an exact, frame-accurate one.
Versions beside the original
Keep a photo you edited in another app, such as Lightroom, next to the original, and compare the two. Deleting a version never touches the original.
Download edited
Download the edited photo at full size, upright and with its date and place, or the original exactly as it was stored.
Storage across drives
Keep backups, imported photos and versions in folders on as many drives as you like, filed by month and person. The owner can dedicate a drive to one person; everything else goes to the first shared location with room. A drive that isn’t plugged in is offline, and nothing is written there.
Verified moves
When someone is given a drive, a drive comes back after being offline, or a location is drained or goes over its cap, files move by a copy that’s checked against its hash before the old one is removed. One at a time, paused during a scan or an import, and the bytes never change.
Import
Copy a folder of photos and videos on the server into PhotoBlad’s storage, for the family or for one person, and follow its progress. What’s already stored is skipped by its content, and the folder is left exactly as it was.
Rebuilt from your folders
After a lost database, storage rebuild reads every storage location, both folder layouts and each location’s manifest, and records the backups, versions and their owners again. It never changes a file.
Docker and Podman Compose
The Server and the Indexer run as two containers with one Compose command. FFmpeg is in the image, the containers run without privileges on a read-only root file system and publish nothing of their own, and you mount your photo folders read-only, so the operating system itself keeps them untouched. Built and tested with Podman; Docker is still to try.
Caddy, with automatic certificates
Reach PhotoBlad at your own domain over HTTPS, with certificates that Caddy gets from Let’s Encrypt and renews itself, HTTP/3, and uploads and videos that stream straight through. A home-network variant makes its own certificates. Tested for real with Caddy’s own certificate authority; a certificate from Let’s Encrypt is still to try.
Tailscale, private to your devices
Reach PhotoBlad at an address such as https://photoblad.<your-tailnet>.ts.net, which only the devices on your own tailnet can open, with certificates Tailscale provides and renews. Nothing is exposed to the internet. Checked against Tailscale’s documentation and source, but not yet run on a real tailnet.
Health checks and backups from the command line
doctor checks the installation: FFmpeg, photo decoding including HEIC, the data folder, every storage location and the proxy settings. db backup copies the database safely while PhotoBlad runs.
iOS and Android apps
Not released yet. The first release is designed to browse the whole library with a photo grid and a date scrubber, play photos and videos, and back up the camera roll automatically, over Wi-Fi by default. The backup API they’ll use is built.
App store releases
TestFlight, App Store and Google Play releases, automated with Fastlane.
Phase 9
On-device AI
Face detection and semantic search that run on your own machine with ONNX Runtime. Not on the roadmap yet.
Not scheduled yet
Screens

Thursday, 24 September 2026
11:57 · from the file’s modification date
← → to browse · Esc to close











Roadmap
Phases 1–7, non-destructive editing and storage across drives are done, self-hosting with Docker or Podman, Caddy and Tailscale included. The phone apps, Phase 8, are in progress and not released; release automation, Phase 9, comes after. Each phase gets its own plan before work starts. There are no target dates yet.
The .NET 10 solution, the library’s data model, and the API contracts the web app shares with the phone apps to come.
EXIF for every supported format, HEIC included; WebP thumbnails; a SQLite database through EF Core.
Scan jobs with exact progress, parallel processing and a single batched database writer, plus the photo and thumbnail API.
Microsoft Aspire runs the Server and a separate Indexer service, with health checks and a dashboard.
The Darkroom web gallery: a justified photo grid, a lightbox with each photo’s details, and scanning from the browser.
Accounts for an owner and family members, who share one library. Sign in with a password or a passkey.
Backups from the browser, written once and private unless you share them; a session for every browser and phone; videos and Live Photos that play in the browser.
Crop, straighten, light, colour and filters; corrected dates, places, captions and tags; video trims; versions edited elsewhere. All stored beside your photos, never in them.
Backups, imported photos and versions kept in folders across several drives, with a drive set aside for anyone who wants one. Files move between drives only by a copy that’s checked first. Import copies a folder in and leaves it as it was.
Docker and Podman Compose files that run PhotoBlad as two containers, FFmpeg included, with a health check and a database backup from the command line. Caddy serves it on your own domain with certificates that renew themselves, or Tailscale keeps it private to your devices. Built and tested with Podman; real Docker and a real Tailscale network are still to try.
iOS and Android apps built with Avalonia, not released yet. The first release is designed to browse the whole library with a date scrubber, and to back up the camera roll automatically through the backup API from Phase 6.
Fastlane and GitHub Actions for TestFlight, App Store and Google Play releases.
You need the .NET 10 SDK and access to the repository. FFmpeg is optional, for video posters and playback. The repository is private for now. [TBD: how to get access while the repository is private]
git clone git@github.com:dustinblad/PhotoBlad.git
cd PhotoBlad
dotnet build PhotoBlad.sln
dotnet run --project src/PhotoBlad.AppHost --launch-profile httpThen open http://localhost:5180. To run it as containers on a server instead, see Self-hosting.