# Changelog All notable changes to this project are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases up to and including v0.9.2 are documented in the [GitHub releases](https://github.com/ralksta/immich-folio/releases). ## [Unreleased] ## [0.11.0] — 2026-08-15 ### Added - **Journal** ([#432](https://github.com/ralksta/immich-folio/pull/432)). A section for photo essays and travel stories at `/journal`, with its own index, cover images, reading times and drafts. Entries are plain Markdown in `content/journal/`, written either by hand or in the new **Journal Studio** — a split-screen block editor with a resizable divider and a live preview of the real page. Photos are inserted through the asset picker rather than by typing UUIDs. A `/journal` link appears in the navigation as soon as one published entry exists; drafts stay visible to a logged-in admin only. Entries can carry their own password. See [docs/journal.md](docs/journal.md). - **About page editor and toggle** ([#446](https://github.com/ralksta/immich-folio/pull/446)). Portrait, name, location, gear list and biography are edited under admin Settings › About, which writes `content/about.md`. `about.enabled: false` in `settings.yaml` takes the page offline without deleting it. - **Per-album photo order, independent of Immich** ([#414](https://github.com/ralksta/immich-folio/pull/414)). A `sort` key per album — `immich`, `newest`, `oldest`, `filename` or `manual` — so a curated series can have a narrative order without changing the archive. `manual` is a pinned prefix: only the photos you place by hand are listed, everything else follows in the Immich order, and the admin panel has a drag & drop editor for it. - **Experimental portfolio features** ([#431](https://github.com/ralksta/immich-folio/pull/431)). Marked experimental in the schema and the UI: - `justified` grid layout — every row fills the width at one shared height, aspect ratios intact - `cover` hero style — a fullscreen splash with the site title and a single **Enter** link - `hidden: true` subpages — reachable by direct link, absent from the navigation (unlisting, not access control) - per-album `grid` overrides, merged over the subpage and global grid - per-album `coverPosition` — the focal point for the cover crop - `navLinks` — external `http(s)` links appended to the header navigation - **First-run setup wizard at `/install`** ([#419](https://github.com/ralksta/immich-folio/pull/419)). A fresh deployment can now be configured from the browser: connect to Immich, optionally pick albums, name the site. Credentials are verified against the Immich server before anything is written, so a typo cannot produce an "installed" site that loads no photos. The wizard is gated by a one-time token printed to the server log — a deployment is reachable before it has any configuration, and without the gate whoever found the URL first could configure it. Credentials land in `content/install.json` (mode `0600`, admin password stored as an scrypt hash); environment variables continue to take precedence, so rotation still works by setting a variable. Configuring everything by hand remains fully supported. - **Custom favicon upload** in admin Settings › General ([#422](https://github.com/ralksta/immich-folio/pull/422)). SVG, PNG, ICO or JPEG, stored in the writable `content/` volume and served through `/api/favicon` with a policy that stops an uploaded SVG executing script. A Reset button restores the bundled default. ### Changed - **`studio-modern` is the default theme preset**, replacing `studio`. It is now listed first in the docs, the setup wizard and the admin preset cards, and it is what a site renders with when no preset is configured. **This changes the appearance of an existing site only if it never picked a theme** — that is, no `content/settings.yaml`, or one without a `theme.preset` key. Anything with an explicit preset is untouched. To keep the previous look, set it explicitly: ```yaml # content/settings.yaml theme: preset: studio ``` Three code paths fell back to a hard-coded `'studio'` (no settings file at all, a settings file without a `theme` key, and a `theme` object that overrides properties without naming a preset). They now share one `DEFAULT_PRESET` constant, with a test covering all three so they cannot drift apart again. - **Every admin area has its own URL** ([#432](https://github.com/ralksta/immich-folio/pull/432)) — `/admin/pages`, `/admin/journal`, `/admin/settings/
`, `/admin/analytics` — so a section can be bookmarked and the back button behaves. The auth gate and the panel chrome moved into the layout, and no longer re-run on every tab switch. A floating save bar keeps Save reachable without scrolling ([#426](https://github.com/ralksta/immich-folio/pull/426)). - **Design system gaps in the admin panel are closed** ([#432](https://github.com/ralksta/immich-folio/pull/432)). Several classes were referenced but never defined — every input used a class no stylesheet had, the Analytics bars had no fill, and all grid previews collapsed to the same height. The album sort dropdown is now a themed listbox rendered in a portal, so it no longer clips inside modals. - **The last emojis in the public frontend are SVG icons** ([#445](https://github.com/ralksta/immich-folio/pull/445)), matching the admin panel ([#415](https://github.com/ralksta/immich-folio/pull/415), [#416](https://github.com/ralksta/immich-folio/pull/416), [#418](https://github.com/ralksta/immich-folio/pull/418)). - **The sample journal story ships as a template, not a live entry** ([#443](https://github.com/ralksta/immich-folio/pull/443)). It is `content/journal/sample-story.md.example`, so a fresh install does not publish someone else's story — and since the asset IDs in it belong to no server, the template ships without any. - **A gallery with no albums is now a valid, rendered state** ([#421](https://github.com/ralksta/immich-folio/pull/421)) instead of an error — the setup wizard can finish without picking one, and albums can be added later in `/admin`. - **The Immich URL may end in `/api`** without breaking every request ([#421](https://github.com/ralksta/immich-folio/pull/421)). The suffix was appended unconditionally, producing `.../api/api`. ### Documentation - **README documents the setup wizard**, what it writes, and that `content/install.json` holds credentials — so a backup of `content/` is understood to include your Immich API key. The Docker examples no longer mount `content/` read-only: the wizard, the admin panel and the backup rotation all write into it, and `:ro` silently breaks all three. - **Contributors are credited in the README.** - **The documentation was brought back in line with `dev`** ([#452](https://github.com/ralksta/immich-folio/pull/452), [#453](https://github.com/ralksta/immich-folio/pull/453)). The README is restructured and `studio-modern` is documented as the default preset, which it had already become in the code. - **The journal guide has screenshots** ([#455](https://github.com/ralksta/immich-folio/pull/455), [#456](https://github.com/ralksta/immich-folio/pull/456), [#457](https://github.com/ralksta/immich-folio/pull/457)). The one guide describing a visual editor had no picture of it. `scripts/screenshots.ts` gained a `journal` section that writes throwaway entries from real albums, shoots the index, a rendered entry, the entry list and the studio — including its draft and password states and the Story Settings form — and deletes them again, so a run never leaves a demo story on a live site. ### Fixed - **Client proofing ignored its own configuration** ([#454](https://github.com/ralksta/immich-folio/pull/454)). The photo grid mounted the proofing provider unconditionally, so the favourite hearts, the selection bar and the export modal appeared on every album on every site. `proofing.enabled` in `settings.yaml`, a subpage's own `proofing:` flag and `allowMailto` were all parsed, validated — and never read. They are honoured now, with precedence subpage → global: a subpage's flag wins in either direction, and a page reached without one follows `proofing.enabled`. **What changes for an existing site.** `proofing.enabled` defaults to `true`, so albums keep their proofing controls and most sites see no difference. Two cases do change: a site that set `proofing.enabled: false` finally gets what it asked for, and **photo essays no longer show the controls unless their subpage sets `proofing: true` explicitly** — a published story is not an album handover, so the global default deliberately does not reach into essays. Journal entries never show them. - **Journal photos did not render** ([#432](https://github.com/ralksta/immich-folio/pull/432)). Photo blocks resolved to nothing, headings sat further left than the body text, fullbleed photos bled only to the left, photo pairs forced both images to equal width regardless of their real shapes, the preview claimed 3:2 for every photo, and the lightbox had neither keyboard control nor navigation inside a journal entry. ### Security - **Journal author markdown is escaped, not filtered** ([#432](https://github.com/ralksta/immich-folio/pull/432)). The previous pass stripped `