refactor: config-driven libraries; drop folder-add UI

The frontend AddSourceFolderDialog let users register source roots
from inside the app, but with the bootstrap auto-creating one for
the /photos mount on first boot, the dialog was redundant in the
common case and confusing in every other (users had to know which
container path corresponded to their host directory). Going
config-driven matches Plex/Photoprism/Immich and matches the
mental model "the docker mount IS the library".

Frontend
- Deleted components/dialogs/AddSourceFolderDialog.tsx entirely.
- LeftSidebar drops the "+ Add Source Folder" button + bottom-bar
  layout, the addFolderMutation, the dead Plus action button on
  the (no-longer-existing) folders/heaps tree headers, and the
  Plus icon import.
- api.ts: removed sourceFolders.add(), library.browse(), and the
  BrowseChild / BrowseResponse types. The remaining sourceFolders
  surface is read-only (list + manual scan).
- LeftSidebar bottom strip is now just the "Scan all folders"
  button when there's at least one source root.

Backend
- Dropped POST /folders (no consumers) along with FolderCreate /
  FolderResponse pydantic models. The folders router header now
  documents the config-driven approach.
- Dropped GET /library/browse (no consumers). Removed the unused
  os/HTTPException/SourceRoot imports it brought in.
- cleanup_data_integrity now also walks the source roots and logs
  a warning for any whose path is missing on disk. Doesn't auto-
  delete (a missing path could be a temporarily unmounted drive)
  but surfaces enough hint to fix it. Returns the count in the
  summary dict alongside merged-duplicates.

Docs
- README "How libraries are managed" section rewritten to spell
  out that mounts ARE source roots, edit .env + restart, no UI for
  managing source roots. New "Changing or adding libraries"
  section walks through the typical edit-restart loop including
  the optional volume-nuke for a clean slate.
- "Adding more libraries" subsection covers multi-mount via
  edited compose with a note that auto-registration is roadmap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-08 00:44:48 +02:00
parent 204d2bf2a8
commit 320107841b
8 changed files with 65 additions and 482 deletions

View File

@@ -70,33 +70,33 @@ docker compose up -d
You don't need to touch `mulita.yml` or the API to get started.
### How "mounted folders" and "source folders" relate
### How libraries are managed
There are two layers, and confusing them is the most common source of
"why doesn't this work" questions:
Mulita is **config-driven**: the host directory you mount via
`PHOTO_DIRS` becomes your library, and the backend automatically
registers it as a source root on startup. There is no UI for adding
or removing source roots — to change what Mulita scans, edit `.env`
(or `docker-compose.yml` for multi-mount setups) and restart the
stack.
| Layer | Lives in | What it controls |
|---|---|---|
| **Mount** | `docker-compose.yml` (`${PHOTO_DIRS}:/photos:rw`) | What's *visible* inside the container |
| **Source root** | Database (managed by the UI) | What the scanner *walks and indexes* |
This keeps the model simple: **the docker mount IS the library**.
No two layers, no confusion about which view to use.
Both are required. A folder that isn't mounted is invisible to the
container regardless of what the database says, and a folder that's
mounted but not registered as a source root won't be scanned.
### Changing or adding libraries
In practice, the default flow handles this for you: you mount one host
directory via `PHOTO_DIRS`, and the bootstrap automatically registers it
as a source root. If you want to add a *subfolder* of your library as a
separate source root (so it shows up as its own item in the sidebar),
use the **Add Source Folder** button — the dialog is a directory browser
restricted to what's mounted, so you can only add things the container
can actually see.
To point at a different library:
1. Edit `PHOTO_DIRS` in `.env`
2. `docker compose down`
3. (Optional, for a clean slate) `docker volume rm muleimage_db_data muleimage_thumbs_data muleimage_proxies_data`
4. `docker compose up -d`
### Adding more libraries
The new library shows up automatically. Without step 3 the old
library's metadata stays in the DB and you'll see a warning at
startup that the old source root's path is missing on disk —
that's a hint to clean up.
Today the compose file mounts a single host directory as `/photos`.
If you want multiple libraries from different host paths, edit
`docker-compose.yml` and add additional mount lines, e.g.:
For multiple libraries, edit `docker-compose.yml` and add additional
mount lines:
```yaml
volumes:
@@ -104,8 +104,9 @@ volumes:
- /Volumes/Archive:/archive:rw # additional library
```
Then in the UI, click **Add Source Folder**, browse to `/archive`, and
add it. (Multi-mount support via env vars is on the roadmap.)
Each mounted directory will need a corresponding source root row in
the DB; today that means `POST /api/v1/folders` via curl, or wait
for the multi-mount auto-registration that's on the roadmap.
### Read-only libraries