2026-02-14 00:59:57 +01:00
|
|
|
/**
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
* Homepage — renders different hero layouts based on theme config.
|
|
|
|
|
*
|
|
|
|
|
* Styles: split, fullbleed, minimal, stacked, typographic, mosaic.
|
2026-02-14 00:59:57 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import Link from 'next/link';
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
import Image from 'next/image';
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
import { immich, type ImmichAsset } from '@/lib/immich';
|
2026-02-14 00:59:57 +01:00
|
|
|
import { getConfig } from '@/lib/config';
|
2026-02-14 10:30:27 +01:00
|
|
|
import { imageUrl, assetPlaceholder } from '@/lib/urls';
|
|
|
|
|
import { HeroCarousel } from '@/components/HeroCarousel';
|
2026-02-14 11:47:26 +01:00
|
|
|
import { FadeIn } from '@/components/FadeIn';
|
2026-08-23 23:18:14 +02:00
|
|
|
import { getServerDictionary } from '@/lib/i18n/server';
|
|
|
|
|
import type { Dictionary } from '@/lib/i18n';
|
2026-02-14 00:59:57 +01:00
|
|
|
|
|
|
|
|
// Render at request time — requires live Immich connection
|
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
|
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
type HeroSubpage = { slug: string; name: string; albumCount: number };
|
|
|
|
|
type HeroAlbum = { id: string; slug: string; albumName: string; assetCount: number };
|
|
|
|
|
|
|
|
|
|
const pad2 = (n: number) => String(n).padStart(2, '0');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Flatten subpages + standalone albums into one indexed nav list.
|
|
|
|
|
* Every entry carries an index and a count; presets decide what to show.
|
|
|
|
|
*/
|
2026-08-23 23:18:14 +02:00
|
|
|
function heroNavEntries(subpages: HeroSubpage[], albums: HeroAlbum[], t: Dictionary) {
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
return [
|
|
|
|
|
...subpages.map((sp) => ({
|
|
|
|
|
key: `sp-${sp.slug}`,
|
|
|
|
|
href: `/${sp.slug}`,
|
|
|
|
|
label: sp.name,
|
2026-08-23 23:18:14 +02:00
|
|
|
count: t.common.albums(sp.albumCount),
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
})),
|
|
|
|
|
...albums.map((a) => ({
|
|
|
|
|
key: `al-${a.id}`,
|
|
|
|
|
href: `/${a.slug}`,
|
|
|
|
|
label: a.albumName,
|
2026-08-23 23:18:14 +02:00
|
|
|
count: t.common.photos(a.assetCount),
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
})),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Camera line for the hero chip: "Q3 · 28MM · ƒ/5.6 · 1/250 · ISO 200".
|
|
|
|
|
* Returns undefined when the asset carries no usable EXIF.
|
|
|
|
|
*/
|
|
|
|
|
function heroExifLine(asset: ImmichAsset): string | undefined {
|
|
|
|
|
const e = asset.exifInfo;
|
|
|
|
|
if (!e) return undefined;
|
|
|
|
|
const parts = [
|
|
|
|
|
e.city || e.model || undefined,
|
|
|
|
|
e.focalLength ? `${Math.round(e.focalLength)}mm` : undefined,
|
|
|
|
|
e.fNumber ? `ƒ/${e.fNumber}` : undefined,
|
|
|
|
|
e.exposureTime ? `${e.exposureTime}s` : undefined,
|
|
|
|
|
e.iso ? `ISO ${e.iso}` : undefined,
|
|
|
|
|
].filter(Boolean);
|
|
|
|
|
return parts.length > 0 ? parts.join(' · ') : undefined;
|
|
|
|
|
}
|
|
|
|
|
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
/** Shared nav links for hero sections. */
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
function HeroNavLinks({ subpages, albums }: { subpages: HeroSubpage[]; albums: HeroAlbum[] }) {
|
2026-08-23 23:18:14 +02:00
|
|
|
const t = getServerDictionary();
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
return (
|
|
|
|
|
<>
|
2026-08-23 23:18:14 +02:00
|
|
|
{heroNavEntries(subpages, albums, t).map((entry, i) => (
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
<Link key={entry.key} href={entry.href} className="hero__nav-link">
|
|
|
|
|
<span className="hero__nav-index" aria-hidden="true">
|
|
|
|
|
{pad2(i + 1)}
|
|
|
|
|
</span>
|
|
|
|
|
<span className="hero__nav-label">{entry.label}</span>
|
|
|
|
|
<span className="hero__nav-count" aria-hidden="true">
|
|
|
|
|
{entry.count}
|
|
|
|
|
</span>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
</Link>
|
|
|
|
|
))}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-13 12:52:09 +01:00
|
|
|
/** Title + optional subtitle + nav — shared by mosaic, minimal, fullbleed, split. */
|
|
|
|
|
function HeroTextContent({
|
|
|
|
|
title,
|
|
|
|
|
subtitle,
|
|
|
|
|
subpages,
|
|
|
|
|
albums,
|
|
|
|
|
}: {
|
|
|
|
|
title: string;
|
|
|
|
|
subtitle?: string;
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
subpages: HeroSubpage[];
|
|
|
|
|
albums: HeroAlbum[];
|
2026-03-13 12:52:09 +01:00
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<FadeIn delay={0}>
|
|
|
|
|
<h1 className="hero__title">{title}</h1>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
{subtitle && (
|
|
|
|
|
<FadeIn delay={100}>
|
|
|
|
|
<p className="hero__subtitle">{subtitle}</p>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
)}
|
|
|
|
|
<FadeIn delay={200}>
|
|
|
|
|
<nav className="hero__nav">
|
|
|
|
|
<HeroNavLinks subpages={subpages} albums={albums} />
|
|
|
|
|
</nav>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 00:59:57 +01:00
|
|
|
export default async function HomePage() {
|
|
|
|
|
const config = getConfig();
|
2026-08-23 23:18:14 +02:00
|
|
|
const t = getServerDictionary();
|
2026-03-08 21:38:44 +01:00
|
|
|
|
|
|
|
|
if (config.needsSetup) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 00:59:57 +01:00
|
|
|
const [subpages, albums] = await Promise.all([
|
|
|
|
|
immich.getSubpages(),
|
|
|
|
|
immich.getStandaloneAlbums(),
|
|
|
|
|
]);
|
2026-02-13 23:26:37 +01:00
|
|
|
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
// Fetch ThumbHash + camera line for all hero images
|
2026-02-14 10:30:27 +01:00
|
|
|
const heroData = await Promise.all(
|
|
|
|
|
config.heroImages.map(async (id) => {
|
|
|
|
|
const asset = await immich.getAssetInfo(id);
|
|
|
|
|
const ph = asset ? assetPlaceholder(asset) : null;
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
const exif = asset ? heroExifLine(asset) : undefined;
|
2026-02-14 10:30:27 +01:00
|
|
|
return {
|
|
|
|
|
src: imageUrl(id, 'preview'),
|
|
|
|
|
...(ph ? { blurDataURL: ph.blurDataURL } : {}),
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
...(exif ? { exif } : {}),
|
2026-02-14 10:30:27 +01:00
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
const heroStyle = config.theme.heroStyle;
|
|
|
|
|
|
experimental: portfolio features (justified layout, unlisted pages, captions, per-album grid, focal point, nav links, cover hero) (#431)
## Was ist das?
Sieben neue Portfolio-Features, alle als **experimental** gekennzeichnet
— in YAML-Kommentaren, Admin-Panel-Labels und Commit-Scopes, damit sie
einzeln nachvollziehbar und revertierbar bleiben.
## Features (je ein Commit)
| Commit | Feature |
| --- | --- |
| `justified rows gallery layout` | Neues Grid-Layout `justified`:
zeilenbasiert, gleiche Höhen, volle Breite — Flexbox ohne JS-Messung,
letzte Zeile bleibt natürlich klein |
| `hide subpages from navigation` | `hidden: true`: Seite aus
Nav/Homepage raus, per Direktlink erreichbar — im Gegensatz zu `enabled:
false` (404) |
| `lightbox captions` | Immich-Asset-Description als Bildunterschrift im
Info-Panel; EXIF-Route liefert bei `exifOnHover: false` jetzt nur noch
die Caption statt 403 |
| `per-album grid overrides` | `grid:` pro Album-Eintrag, Präzedenz
global < Subpage < Album |
| `per-album cover focal point` | `coverPosition:` → `object-position`
auf Cover-Karten, strikt validiert |
| `external links in header navigation` | `navLinks:` in settings.yaml,
nur http(s), sanitisiert |
| `cover splash hero style` | `heroStyle: cover`: Fullscreen-Splash mit
Enter-Link ins Portfolio |
Alle Optionen sind im Admin-Panel editierbar (PageBuilder /
SettingsEditor).
## Tests
- 356 Unit-Tests grün (13 neue: deriveGallery hidden/grid/coverPosition,
sanitizeNavLinks, EXIF-Route-Captions, justified-Layout-Validierung)
- `npx tsc --noEmit`: 0 Fehler
- `npm run build`: sauber
- Justified-Zeilenmathematik und Cover-Splash per Browser-Harness
visuell/numerisch verifiziert (volle Zeilen enden exakt an der
Containerkante, letzte Zeile bleibt natürlich)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: ralksta <ralksta@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com>
2026-08-14 17:56:22 +02:00
|
|
|
// ── Cover (EXPERIMENTAL): fullscreen splash + single "Enter" link ─
|
|
|
|
|
// Welcome-page splash: one fullbleed image, the site
|
|
|
|
|
// title, and one link into the portfolio (the first nav entry).
|
|
|
|
|
if (heroStyle === 'cover') {
|
2026-08-23 23:18:14 +02:00
|
|
|
const entries = heroNavEntries(subpages, albums, t);
|
experimental: portfolio features (justified layout, unlisted pages, captions, per-album grid, focal point, nav links, cover hero) (#431)
## Was ist das?
Sieben neue Portfolio-Features, alle als **experimental** gekennzeichnet
— in YAML-Kommentaren, Admin-Panel-Labels und Commit-Scopes, damit sie
einzeln nachvollziehbar und revertierbar bleiben.
## Features (je ein Commit)
| Commit | Feature |
| --- | --- |
| `justified rows gallery layout` | Neues Grid-Layout `justified`:
zeilenbasiert, gleiche Höhen, volle Breite — Flexbox ohne JS-Messung,
letzte Zeile bleibt natürlich klein |
| `hide subpages from navigation` | `hidden: true`: Seite aus
Nav/Homepage raus, per Direktlink erreichbar — im Gegensatz zu `enabled:
false` (404) |
| `lightbox captions` | Immich-Asset-Description als Bildunterschrift im
Info-Panel; EXIF-Route liefert bei `exifOnHover: false` jetzt nur noch
die Caption statt 403 |
| `per-album grid overrides` | `grid:` pro Album-Eintrag, Präzedenz
global < Subpage < Album |
| `per-album cover focal point` | `coverPosition:` → `object-position`
auf Cover-Karten, strikt validiert |
| `external links in header navigation` | `navLinks:` in settings.yaml,
nur http(s), sanitisiert |
| `cover splash hero style` | `heroStyle: cover`: Fullscreen-Splash mit
Enter-Link ins Portfolio |
Alle Optionen sind im Admin-Panel editierbar (PageBuilder /
SettingsEditor).
## Tests
- 356 Unit-Tests grün (13 neue: deriveGallery hidden/grid/coverPosition,
sanitizeNavLinks, EXIF-Route-Captions, justified-Layout-Validierung)
- `npx tsc --noEmit`: 0 Fehler
- `npm run build`: sauber
- Justified-Zeilenmathematik und Cover-Splash per Browser-Harness
visuell/numerisch verifiziert (volle Zeilen enden exakt an der
Containerkante, letzte Zeile bleibt natürlich)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: ralksta <ralksta@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com>
2026-08-14 17:56:22 +02:00
|
|
|
const enterHref = entries[0]?.href ?? '/about';
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--cover">
|
|
|
|
|
<HeroCarousel images={heroData} />
|
|
|
|
|
<div className="hero__cover-overlay">
|
|
|
|
|
<FadeIn delay={0}>
|
|
|
|
|
<h1 className="hero__title">{config.siteTitle}</h1>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
{config.siteSubtitle && (
|
|
|
|
|
<FadeIn delay={100}>
|
|
|
|
|
<p className="hero__subtitle">{config.siteSubtitle}</p>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
)}
|
|
|
|
|
<FadeIn delay={250}>
|
|
|
|
|
<Link href={enterHref} className="hero__cover-enter">
|
2026-08-23 23:18:14 +02:00
|
|
|
{t.home.enter}
|
experimental: portfolio features (justified layout, unlisted pages, captions, per-album grid, focal point, nav links, cover hero) (#431)
## Was ist das?
Sieben neue Portfolio-Features, alle als **experimental** gekennzeichnet
— in YAML-Kommentaren, Admin-Panel-Labels und Commit-Scopes, damit sie
einzeln nachvollziehbar und revertierbar bleiben.
## Features (je ein Commit)
| Commit | Feature |
| --- | --- |
| `justified rows gallery layout` | Neues Grid-Layout `justified`:
zeilenbasiert, gleiche Höhen, volle Breite — Flexbox ohne JS-Messung,
letzte Zeile bleibt natürlich klein |
| `hide subpages from navigation` | `hidden: true`: Seite aus
Nav/Homepage raus, per Direktlink erreichbar — im Gegensatz zu `enabled:
false` (404) |
| `lightbox captions` | Immich-Asset-Description als Bildunterschrift im
Info-Panel; EXIF-Route liefert bei `exifOnHover: false` jetzt nur noch
die Caption statt 403 |
| `per-album grid overrides` | `grid:` pro Album-Eintrag, Präzedenz
global < Subpage < Album |
| `per-album cover focal point` | `coverPosition:` → `object-position`
auf Cover-Karten, strikt validiert |
| `external links in header navigation` | `navLinks:` in settings.yaml,
nur http(s), sanitisiert |
| `cover splash hero style` | `heroStyle: cover`: Fullscreen-Splash mit
Enter-Link ins Portfolio |
Alle Optionen sind im Admin-Panel editierbar (PageBuilder /
SettingsEditor).
## Tests
- 356 Unit-Tests grün (13 neue: deriveGallery hidden/grid/coverPosition,
sanitizeNavLinks, EXIF-Route-Captions, justified-Layout-Validierung)
- `npx tsc --noEmit`: 0 Fehler
- `npm run build`: sauber
- Justified-Zeilenmathematik und Cover-Splash per Browser-Harness
visuell/numerisch verifiziert (volle Zeilen enden exakt an der
Containerkante, letzte Zeile bleibt natürlich)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: ralksta <ralksta@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com>
2026-08-14 17:56:22 +02:00
|
|
|
<span className="hero__cover-enter-arrow" aria-hidden="true">
|
|
|
|
|
→
|
|
|
|
|
</span>
|
|
|
|
|
</Link>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
// ── Typographic: no image, pure text ───────────────────────────
|
|
|
|
|
if (heroStyle === 'typographic') {
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--typographic">
|
2026-02-14 00:59:57 +01:00
|
|
|
<div className="hero__content">
|
2026-02-14 11:47:26 +01:00
|
|
|
<FadeIn delay={0}>
|
|
|
|
|
<h1 className="hero__title">{config.siteTitle}</h1>
|
|
|
|
|
</FadeIn>
|
2026-02-14 00:59:57 +01:00
|
|
|
{config.siteSubtitle && (
|
2026-02-14 11:47:26 +01:00
|
|
|
<FadeIn delay={100}>
|
|
|
|
|
<p className="hero__subtitle">{config.siteSubtitle}</p>
|
|
|
|
|
</FadeIn>
|
2026-02-14 00:59:57 +01:00
|
|
|
)}
|
2026-02-14 11:47:26 +01:00
|
|
|
<FadeIn delay={200}>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
<div className="hero__divider" />
|
|
|
|
|
</FadeIn>
|
|
|
|
|
<FadeIn delay={300}>
|
|
|
|
|
<nav className="hero__nav hero__nav--indexed">
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
<HeroNavLinks subpages={subpages} albums={albums} />
|
2026-02-14 11:47:26 +01:00
|
|
|
</nav>
|
|
|
|
|
</FadeIn>
|
2026-02-13 23:26:37 +01:00
|
|
|
</div>
|
2026-02-14 00:59:57 +01:00
|
|
|
</div>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Stacked: fullbleed image + text at bottom + thumbnail strip ─
|
|
|
|
|
if (heroStyle === 'stacked') {
|
2026-08-23 23:18:14 +02:00
|
|
|
const allEntries = heroNavEntries(subpages, albums, t);
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--stacked">
|
|
|
|
|
<div className="hero__stacked-image">
|
|
|
|
|
<HeroCarousel images={heroData} />
|
|
|
|
|
<div className="hero__stacked-overlay">
|
|
|
|
|
<FadeIn delay={0}>
|
|
|
|
|
<h1 className="hero__title">{config.siteTitle}</h1>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
{config.siteSubtitle && (
|
|
|
|
|
<FadeIn delay={100}>
|
|
|
|
|
<p className="hero__subtitle">{config.siteSubtitle}</p>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<FadeIn delay={200}>
|
|
|
|
|
<nav className="hero__thumbnail-strip">
|
chore(release): v0.10.0 (#400)
Photo Essay mode, client proofing, studio-modern preset, admin panel overhaul, watermark, cookieless analytics, subpage toggle, SEO title templates. Analytics API now admin-only, Trivy scan on publish. Album order mirrors the Immich timeline; map theme, admin status panel, lightbox counter and Docker health check fixed.
See CHANGELOG.md for the full list and the health-check upgrade note.
2026-08-10 09:56:20 +02:00
|
|
|
{allEntries.map((entry, i) => (
|
|
|
|
|
<Link key={entry.key} href={entry.href} className="hero__thumbnail-item">
|
|
|
|
|
<span className="hero__thumbnail-index" aria-hidden="true">
|
|
|
|
|
{pad2(i + 1)}
|
|
|
|
|
</span>
|
|
|
|
|
<span className="hero__thumbnail-label">{entry.label}</span>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
</Link>
|
|
|
|
|
))}
|
|
|
|
|
</nav>
|
|
|
|
|
</FadeIn>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Mosaic: multi-image grid with frosted title overlay ────────
|
|
|
|
|
if (heroStyle === 'mosaic') {
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--mosaic">
|
|
|
|
|
<div className="hero__mosaic-grid">
|
2026-03-13 11:34:16 +01:00
|
|
|
{heroData.slice(0, 4).map((img, i) => (
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
<div key={i} className={`hero__mosaic-cell hero__mosaic-cell--${i + 1}`}>
|
|
|
|
|
<Image
|
|
|
|
|
src={img.src}
|
|
|
|
|
alt=""
|
|
|
|
|
fill
|
|
|
|
|
sizes="(max-width: 640px) 100vw, 50vw"
|
|
|
|
|
priority={i < 2}
|
|
|
|
|
{...(img.blurDataURL
|
|
|
|
|
? { placeholder: 'blur' as const, blurDataURL: img.blurDataURL }
|
|
|
|
|
: {})}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="hero__mosaic-overlay">
|
2026-03-15 07:32:42 +01:00
|
|
|
<HeroTextContent
|
|
|
|
|
title={config.siteTitle}
|
|
|
|
|
subtitle={config.siteSubtitle}
|
|
|
|
|
subpages={subpages}
|
|
|
|
|
albums={albums}
|
|
|
|
|
/>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-08 16:16:15 +01:00
|
|
|
// ── Minimal: pure text, no image, simple centered ──────────────
|
|
|
|
|
if (heroStyle === 'minimal') {
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--minimal">
|
|
|
|
|
<div className="hero__content">
|
2026-03-15 07:32:42 +01:00
|
|
|
<HeroTextContent
|
|
|
|
|
title={config.siteTitle}
|
|
|
|
|
subtitle={config.siteSubtitle}
|
|
|
|
|
subpages={subpages}
|
|
|
|
|
albums={albums}
|
|
|
|
|
/>
|
2026-03-08 16:16:15 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Fullbleed: full-viewport image + centered overlay ───────────
|
|
|
|
|
if (heroStyle === 'fullbleed') {
|
|
|
|
|
return (
|
|
|
|
|
<div className="hero hero--fullbleed">
|
|
|
|
|
<HeroCarousel images={heroData} />
|
|
|
|
|
<div className="hero__fullbleed-overlay">
|
2026-03-15 07:32:42 +01:00
|
|
|
<HeroTextContent
|
|
|
|
|
title={config.siteTitle}
|
|
|
|
|
subtitle={config.siteSubtitle}
|
|
|
|
|
subpages={subpages}
|
|
|
|
|
albums={albums}
|
|
|
|
|
/>
|
2026-03-08 16:16:15 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Split: left text panel, right image (default) ───────────────
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
return (
|
2026-03-08 16:16:15 +01:00
|
|
|
<div className="hero hero--split">
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
{/* ── Left Panel ──────────────────────────────── */}
|
|
|
|
|
<div className="hero__left">
|
|
|
|
|
<div className="hero__content">
|
2026-03-15 07:32:42 +01:00
|
|
|
<HeroTextContent
|
|
|
|
|
title={config.siteTitle}
|
|
|
|
|
subtitle={config.siteSubtitle}
|
|
|
|
|
subpages={subpages}
|
|
|
|
|
albums={albums}
|
|
|
|
|
/>
|
feat: add noir, monograph, botanica presets + stacked/typographic/mosaic hero styles + showcase/filmstrip/editorial-flow gallery layouts
- 3 new theme presets: noir (darkroom analog), monograph (typographic book), botanica (organic nature)
- 3 new hero styles: stacked (fullbleed + thumbnail strip), typographic (text-only), mosaic (multi-image grid)
- 3 new gallery layouts: showcase (featured + grid), filmstrip (horizontal scroll), editorial-flow (alternating pairs)
- Extended config types, validation, and CSS tokens for all new options
- Updated theming docs with new presets table, descriptions, and example configs
2026-02-15 21:58:31 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-02-14 00:59:57 +01:00
|
|
|
|
2026-02-14 10:30:27 +01:00
|
|
|
{/* ── Right Panel (Hero Carousel) ─────────────── */}
|
2026-02-14 00:59:57 +01:00
|
|
|
<div className="hero__right">
|
2026-02-14 10:30:27 +01:00
|
|
|
<HeroCarousel images={heroData} />
|
2026-02-14 00:59:57 +01:00
|
|
|
</div>
|
2026-02-13 23:26:37 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|