Media Gallery
Photo galleries — local disk or a cloud bucket by default, real Adhara Media Gallery folders when configured.
/gallery is new in this port — not in the Python original. Photo galleries, one page with
client-side category tabs. It’s the one feature whose “local” mode has two genuinely
different sub-sources, chosen automatically rather than by a second env var.
Three sources
- Local disk (the zero-config default) — drop image files into
public/gallery/<name>/; each subfolder becomes a gallery, named from its folder name. No database, no upload step, no CLI command — Astro serves the files directly as static assets. This is build-time content like theme CSS, not runtime-written storage: commit the images (or add them beforenpm run build) so they end up in the deployed build. - Cloud bucket (automatic once this site’s
ContentStorebackend is a cloud one rather than local disk — see Storage) — galleries are read fromupload/gallery/<name>/in that same bucket instead, reusing the exact pluggable storage mechanism already proven by the block editor’s image uploads. - Adhara (
GRAVITY_GALLERY_BACKEND=adhara, or auto-detected once bothADHARA_API_KEYandADHARA_WORKSPACE_IDare set — unlike events/links/shop, a workspace slug alone isn’t enough) — every root-level folder in the workspace’s real Media Gallery becomes a gallery, auto-discovered via alistFolders()call. No per-folder env var to hand-maintain.
Why Adhara mode needs the API key
Confirmed against the real backend: there is no public, no-API-key, multi-folder
gallery-browsing endpoint. The one anonymous route that exists
(/public/gallery/{share_token}) is scoped to a single admin-shared folder for one-off
client delivery — a different feature entirely, not general marketing-page gallery browsing.
Real, site-wide gallery browsing always needs ADHARA_API_KEY server-side. Recommend scoping
the key to the media:public permission — the backend then silently restricts results to
files explicitly marked public, the safe default for anything embedded on a public page.
A resource the SDK didn’t have
The SDK had zero coverage of Adhara’s Media Gallery system before this feature — not a
wrong-shaped method, a fully missing resource (its pre-existing AssetsResource/
DigitalAsset is a different system: gated downloadable files like PDFs/ebooks, zero
overlap). A MediaResource was added at the SDK’s source — see
The Adhara SDK for the full “layer on top, fix at the source” pattern this
followed.
Architecture
sdk/node/src/resources/media.ts (SDK) → src/lib/adharaMedia.ts (thin wrapper) →
src/services/galleryStore.ts (three-source resolution) → src/pages/gallery.astro. The
cloud-bucket path adds a listMedia(prefix) method to every ContentStore backend
(src/stores/*.ts) — the read-back counterpart to the writeMedia() every backend already
had.