From 2f546f440d9a7990ca23ef69c2b9a283196eff52 Mon Sep 17 00:00:00 2001 From: Ralksta <16941050+ralksta@users.noreply.github.com> Date: Sat, 15 Aug 2026 09:09:18 +0200 Subject: [PATCH] release: v0.11.0 (#459) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ships `dev` as **v0.11.0**. `main` contains nothing that `dev` does not, so this is a clean sync. ## Headline changes since v0.10.0 - **Journal & Journal Studio** — photo essays at `/journal`, split-screen block editor with live preview, drafts, per-entry passwords, cover images - **First-run setup wizard at `/install`** — configure a fresh deployment from the browser; credentials are verified against Immich before anything is written, and the wizard is gated by a one-time token - **About page editor and toggle** in the admin panel - **Per-album photo order** independent of Immich, with a drag & drop editor - **Custom favicon upload** - **Experimental portfolio features** — justified grid, `cover` hero, unlisted subpages, per-album grid overrides, cover focal points, external nav links - **Security** — asset tokens length-capped before decoding (#423), journal author markdown escaped rather than filtered, journal file paths contained, admin session key derived with scrypt (#432), Next.js 16.3.0 for CVE-2025-13465 - **Fixed** — client proofing honours its own configuration again (#454); journal photo rendering (#432) Full detail in [CHANGELOG.md](CHANGELOG.md#0110--2026-08-15). ## Verified `npx tsc --noEmit` clean · `npx vitest run` 435 tests pass · `npm run build` succeeds · lint 0 errors · `prettier --check` clean · local `docker build` of the release tree. ## After merge Tag `v0.11.0` on `main` and publish the release — that triggers `docker-publish.yml`, which pushes the image and moves `latest`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: ralksta Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com> Co-authored-by: Claude Opus 5 --- CHANGELOG.md | 148 +++ CLAUDE.md | 111 +- README.md | 212 ++-- app/[...path]/AlbumDetailView.tsx | 27 +- app/[...path]/EssayView.tsx | 4 +- app/[...path]/PhotoGrid.tsx | 35 +- app/[...path]/SubpageGridView.tsx | 4 +- app/[...path]/page.tsx | 27 +- app/admin/components/AnalyticsView.tsx | 50 +- app/admin/components/BackupManagerModal.tsx | 30 +- app/admin/components/EssayBlockEditor.tsx | 75 +- app/admin/components/PageBuilder.tsx | 1047 +++++++++-------- app/admin/components/SettingsEditor.tsx | 405 +++++-- app/api/admin/backups/route.ts | 6 +- app/api/admin/journal/[slug]/route.ts | 10 +- app/api/admin/journal/route.ts | 15 +- app/api/admin/settings/route.ts | 5 +- app/api/analytics/track/route.ts | 2 +- app/api/auth/route.ts | 3 +- app/api/install/route.ts | 5 +- app/install/InstallWizard.tsx | 11 +- app/journal/[slug]/page.tsx | 1 - components/AssetProtection.tsx | 8 +- components/Icons.tsx | 853 ++++++++++++-- components/Lightbox.tsx | 4 +- components/ProofingContext.tsx | 7 +- components/ProofingModal.tsx | 1 - content/gallery.yaml.example | 13 +- content/settings.yaml.example | 5 +- docs/README.md | 30 + docs/admin-panel.md | 158 ++- docs/brainstorm-2026-08-05.md | 2 +- docs/brainstorm.md | 22 +- docs/deep-dive-2026-08-05.md | 52 +- docs/deployment.md | 128 ++ docs/gallery-config.md | 353 +++++- docs/journal-studio-design.md | 36 +- docs/journal.md | 244 ++++ docs/screenshots/admin-journal-list.png | Bin 0 -> 202019 bytes docs/screenshots/admin-journal-settings.png | Bin 0 -> 92637 bytes docs/screenshots/admin-journal-studio.png | Bin 0 -> 131066 bytes docs/screenshots/header.png | Bin 0 -> 463745 bytes docs/screenshots/journal-entry.png | Bin 0 -> 202406 bytes docs/screenshots/journal-index.png | Bin 0 -> 143693 bytes .../plans/2026-08-05-resilience-boundaries.md | 74 +- docs/theming.md | 33 +- lib/__tests__/essay.test.ts | 25 +- lib/__tests__/journal.test.ts | 13 +- lib/__tests__/proofing-resolution.test.ts | 50 + lib/__tests__/theme-default.test.ts | 47 + lib/auth.ts | 5 +- lib/config/index.ts | 24 +- lib/config/schema.ts | 8 +- lib/config/theme.ts | 27 +- lib/env.ts | 2 - lib/install.ts | 3 +- lib/proofing.ts | 5 +- package-lock.json | 4 +- package.json | 2 +- scripts/header.ts | 168 +++ scripts/screenshots.ts | 429 ++++++- 61 files changed, 3953 insertions(+), 1115 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/deployment.md create mode 100644 docs/journal.md create mode 100644 docs/screenshots/admin-journal-list.png create mode 100644 docs/screenshots/admin-journal-settings.png create mode 100644 docs/screenshots/admin-journal-studio.png create mode 100644 docs/screenshots/header.png create mode 100644 docs/screenshots/journal-entry.png create mode 100644 docs/screenshots/journal-index.png create mode 100644 lib/__tests__/proofing-resolution.test.ts create mode 100644 lib/__tests__/theme-default.test.ts create mode 100644 scripts/header.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 42e5be2..3216d35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,43 @@ Releases up to and including v0.9.2 are documented in the ## [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 @@ -30,6 +65,50 @@ Releases up to and including v0.9.2 are documented in the ### 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 @@ -46,9 +125,73 @@ Releases up to and including v0.9.2 are documented in the `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 `