Forty-one commits since v0.11.0. See CHANGELOG.md for the full list and the upgrade notes.
397 lines
19 KiB
Markdown
397 lines
19 KiB
Markdown
# Feature-Brainstorm: Kundengeschäft, Handwerk, Vertrauen
|
||
|
||
_Stand: 2026-08-15 · Basis: v0.11.0 (dev, nach #431 und #460) · Fokus: was ein
|
||
Fotograf im Alltag mit dieser Software tut_
|
||
|
||
Dieses Dokument ergänzt [`ideas.md`](ideas.md) (Präsentation),
|
||
[`brainstorm.md`](brainstorm.md) (Mai 2026) und
|
||
[`brainstorm-2026-08-05.md`](brainstorm-2026-08-05.md) (Verbreitung & Betrieb).
|
||
Es wiederholt deren Ideen **nicht**. Wo es einen bereits gelisteten Punkt aufgreift,
|
||
steht es ausdrücklich dabei (Abschnitt D).
|
||
|
||
Die Perspektive hier ist eine andere als in den Vorgängern: nicht „was fehlt der
|
||
Software", sondern **„was tut ein Fotograf, das Folio heute nicht begleitet"** —
|
||
Bilder an Kunden übergeben, eine Serie sequenzieren, entscheiden, was die Welt über
|
||
den Aufnahmeort erfahren darf.
|
||
|
||
Alle Befunde sind gegen den Code-Stand geprüft; Aufwand: XS (Stunden), S (1 Tag),
|
||
M (2–5 Tage), L (Wochen).
|
||
|
||
---
|
||
|
||
## Was seit den alten Listen dazugekommen ist
|
||
|
||
Damit klar ist, warum die folgenden Ideen neu sind: seit #431 und #460 leben bereits
|
||
Fokuspunkt fürs Cover, Bildunterschriften aus der Immich-Description,
|
||
`justified`-Layout, unlisted Subpages, externe Nav-Links, Cover-Splash-Hero und
|
||
per-Album-Grid. Früher kamen Wasserzeichen, Rechtsklick-Schutz, Client-Proofing
|
||
inklusive Share-Link und Mailto-Export, Map, Video, Journal/Essays, Setup-Assistent,
|
||
Error-Boundaries und der Stale-Cache dazu.
|
||
|
||
Weiterhin offen aus den alten Listen und hier bewusst _nicht_ nochmal ausgeführt:
|
||
Slideshow, Fullscreen, Download-Button, Copy-Link, Photo of the Day, ISR,
|
||
EXIF-Statistikseite, Before/After-Slider, i18n, Timeline, Smart Search, PWA,
|
||
Demo-Modus, Config-Doctor, Platten-Cache, Metriken, Multi-Site.
|
||
|
||
---
|
||
|
||
## A. Kundengeschäft
|
||
|
||
Folio kann Kunden heute Bilder _zeigen_ (Passwort, Proofing) — aber der Weg
|
||
davor und danach fehlt: wie der Kunde hereinkommt und wie er sich zurückmeldet.
|
||
|
||
### A1. Ablaufende, widerrufbare Client-Links — **M, hoher Impact**
|
||
|
||
**Befund:** Kundenzugang ist heute ein statisches Passwort in `gallery.yaml`, geprüft
|
||
gegen ein HMAC-Cookie (`lib/auth.ts:44-46`, `lb_auth_album_<slug>`). Daraus folgt
|
||
dreierlei: Das Passwort läuft nie ab. Es lässt sich nicht für _einen_ Empfänger
|
||
zurückziehen, sondern nur für alle gleichzeitig ändern. Und der Kunde muss es tippen —
|
||
in der Praxis steht es deshalb ohnehin in derselben Mail wie der Link, was die
|
||
Zugangskontrolle auf ein Feigenblatt reduziert.
|
||
|
||
**Idee:** Zugangs-Links, die im Admin erzeugt werden:
|
||
|
||
```
|
||
https://folio.example/hochzeit-mueller?k=<signiertes-token>
|
||
```
|
||
|
||
Das Token trägt Slug, Ablaufdatum und eine Link-ID; signiert mit derselben Mechanik
|
||
wie die Admin-Session (`lib/admin/auth.ts`). Beim ersten Aufruf wird es gegen genau
|
||
das Cookie eingetauscht, das heute schon existiert — der gesamte Rest der
|
||
Zugangsprüfung bleibt unangetastet. Im Admin: eine Liste mit Label („Brautpaar",
|
||
„Location"), Ablaufdatum und einem Widerrufen-Knopf.
|
||
|
||
**Warum das zieht:** Es ist der Unterschied zwischen „hier ist ein Passwort" und dem,
|
||
was Kunden von Pixieset oder Pic-Time kennen. Für Hochzeits- und Auftragsfotografen
|
||
ist die Galerie-Übergabe der eigentliche Arbeitsschritt, nicht das Portfolio.
|
||
|
||
**Zwei Trade-offs, die benannt gehören:**
|
||
|
||
- **Widerruf braucht Zustand.** Ein rein signiertes Token kann man nicht
|
||
zurücknehmen, nur ablaufen lassen. Echter Widerruf verlangt eine Liste ausgegebener
|
||
Link-IDs in `content/` — sonst ist das Wort „widerrufbar" gelogen. Das ist der
|
||
erste Fall, in dem Folio Besucher-bezogenen Zustand speichert; die Liste sollte
|
||
entsprechend klein und selbstaufräumend sein.
|
||
- **Bild-URLs bleiben unberührt.** Asset-Tokens sind bewusst deterministisch, damit
|
||
Browser cachen können. Ein widerrufener Zugang macht bereits ausgelieferte
|
||
Bild-URLs also nicht ungültig — derselbe Trade-off, der in
|
||
[`deep-dive-2026-08-05.md`](deep-dive-2026-08-05.md) für die Allowlist notiert ist.
|
||
Er muss hier _dokumentiert_ werden, sonst erwartet jemand mehr, als das Feature hält.
|
||
|
||
---
|
||
|
||
### A2. Anfrage-Formular statt `mailto:` — **S–M**
|
||
|
||
**Befund:** Es gibt kein Formular. Kontakt läuft über `mailto:` im Footer
|
||
(`components/Footer.tsx:60`) und im Proofing-Modal
|
||
(`components/ProofingModal.tsx:43`). Das hat zwei Kosten, die Fotografen real treffen:
|
||
Die Adresse steht im Klartext im HTML und wird abgegrast, und auf Geräten ohne
|
||
konfigurierten Mail-Client passiert beim Klick schlicht nichts — der Kunde denkt, der
|
||
Link sei kaputt.
|
||
|
||
**Idee:** Eine rate-limitierte Route (`lib/rate-limit.ts` ist da, eigener Namensraum
|
||
`contact:`, niedriges Limit in der Größenordnung der Auth-Routen) plus Honeypot-Feld.
|
||
Zustellung wahlweise per SMTP oder per Webhook. Und — das ist der eigentliche Wert —
|
||
ein **„Zu diesem Bild anfragen"** direkt im Lightbox: Print-Anfrage, Lizenzanfrage,
|
||
Buchung, mit Bildreferenz vorausgefüllt. Aus einer Galerie wird damit ein
|
||
Verkaufskanal, ohne dass ein Shop dranhängt.
|
||
|
||
**Ehrlich zu benennen:** SMTP wäre die erste ausgehende Verbindung des Projekts
|
||
überhaupt und die erste ernsthafte neue Dependency (das Projekt hat heute sieben
|
||
Runtime-Dependencies und keine Mail-Bibliothek). Der Webhook-Weg vermeidet beides und
|
||
passt besser zur bestehenden Linie — `POST /api/webhook` zeigt, dass das Muster im
|
||
Haus schon verstanden ist. **Empfehlung: mit Webhook anfangen, SMTP optional
|
||
nachziehen.**
|
||
|
||
---
|
||
|
||
### A3. Proofing v2 — Notizen statt nur Herzen — **S**
|
||
|
||
**Befund:** Die Auswahl ist eine Bitmaske von Indizes (`lib/proofing.ts`), exportiert
|
||
als Link, als nummerierte Liste oder per Mailto. Sie transportiert also genau ein Bit
|
||
pro Foto: gewählt oder nicht.
|
||
|
||
**Idee:** Ein kurzes Notizfeld pro ausgewähltem Foto. Kunden sagen selten nur „dieses",
|
||
sondern „dieses, aber enger geschnitten" oder „das für die Danksagung". Heute landet
|
||
das in einer separaten Mail mit Bildnummern, die der Fotograf von Hand zuordnet — der
|
||
unangenehmste Teil des ganzen Ablaufs.
|
||
|
||
**Der Trade-off ist hier die eigentliche Designfrage:** Freitext passt nicht in eine
|
||
Bitmaske im URL-Parameter. Zwei saubere Auswege:
|
||
|
||
- **Klein:** Notizen bleiben in `localStorage` und wandern nur in den Export-Text.
|
||
Der Share-Link trägt weiterhin nur die Auswahl. Kein Server, kein neuer Zustand —
|
||
passt exakt zur heutigen Architektur („nichts wird serverseitig gespeichert").
|
||
- **Groß:** Ein Endpunkt, der die Auswahl entgegennimmt. Das wäre der erste
|
||
Schreibzugriff durch Besucher — mit allem, was daran hängt: Rate-Limiting,
|
||
Größenbegrenzung, Spam, Aufbewahrung. Nur sinnvoll zusammen mit A1, weil erst ein
|
||
identifizierbarer Client-Link die Rückmeldung zuordenbar macht.
|
||
|
||
**Empfehlung:** die kleine Variante. Sie kostet einen Tag und löst 90 % des Problems.
|
||
|
||
---
|
||
|
||
## B. Handwerk & Präsentation
|
||
|
||
Die Zielgruppe sind laut den bisherigen Doks „Fotografen mit Gestaltungsanspruch".
|
||
Die drei folgenden Punkte zielen genau darauf — und einer davon ist ein Befund, der
|
||
mich beim Lesen überrascht hat.
|
||
|
||
### B1. Sequenzierung wie im Fotobuch — **M, der stärkste Differenzierer hier**
|
||
|
||
**Befund:** Ein Layout gilt für ein ganzes Album (`grid.layout`, seit #431 auch pro
|
||
Album überschreibbar). Die Reihenfolge ist frei wählbar (`assetOrder`,
|
||
`lib/config/schema.ts:224`, mit Drag & Drop im Admin) — aber jedes Foto bekommt
|
||
dieselbe Behandlung wie sein Nachbar.
|
||
|
||
Ein Fotobuch funktioniert anders. Es lebt von **Paaren**, die sich auf einer
|
||
Doppelseite antworten, von **einem Bild, das allein über die volle Breite geht**, und
|
||
von **Pausen**. Genau diese Mittel besitzt die Essay-Ansicht bereits — die
|
||
Journal-Syntax kennt `fullbleed`, `wide` und Foto-Paare (`lib/journal.ts`). Das Album
|
||
kennt sie nicht.
|
||
|
||
**Idee:** Optionale Layout-Hinweise entlang des vorhandenen `assetOrder`:
|
||
|
||
```yaml
|
||
- 'album-uuid':
|
||
sort: manual
|
||
assetOrder:
|
||
- 'asset-opening': fullbleed # allein, volle Breite
|
||
- 'asset-a': pair # diese beiden nebeneinander,
|
||
- 'asset-b': pair # in gleicher Höhe
|
||
- 'asset-c'
|
||
- break # bewusste Lücke, dann geht es weiter
|
||
```
|
||
|
||
Renderer-seitig ist das kein neues Layout-System, sondern eine Segmentierung des
|
||
bestehenden Grids: `PhotoGrid` gruppiert die Assets vor dem Rendern in Blöcke und
|
||
rendert je Block das passende Muster. Die Bausteine — Aspect-Ratio pro Asset
|
||
(`assetAspectRatio`), Zeilenmathematik aus `justified` — liegen schon da.
|
||
|
||
**Warum das zieht:** Es ist das einzige Feature auf dieser Liste, das kein anderes
|
||
Immich-Portfolio-Tool hat, und es spricht die Zielgruppe an ihrer empfindlichsten
|
||
Stelle an: Reihenfolge ist Handwerk. Eine Serie, die als gleichförmiges Raster
|
||
ausgespielt wird, ist eine Serie, deren Rhythmus verloren geht.
|
||
|
||
**Trade-off:** Das Feature ist im Admin nur so gut wie seine Vorschau. Layout-Hinweise
|
||
in einer Liste zu setzen, ohne das Ergebnis zu sehen, ist frustrierend — der
|
||
`AssetOrderEditor` müsste die Blöcke andeuten. Das ist die halbe Arbeit an dieser
|
||
Idee, nicht das YAML-Schema.
|
||
|
||
---
|
||
|
||
### B2. 1:1-Zoom im Lightbox — **S** _(mit einem Nebenbefund)_
|
||
|
||
**Befund — und der ist präziser, als er zunächst aussieht:** Der Lightbox hat keinerlei
|
||
Zoom; die einzige Transformation ist eine Mount-Transition von `scale(0.96)` auf `1`
|
||
(`components/Lightbox.module.css`). So weit erwartbar.
|
||
|
||
Interessanter ist, _was_ er anzeigt. Der Dateikopf verspricht
|
||
„Full-resolution image display" (`components/Lightbox.tsx:5`), gerendert wird aber
|
||
`current.previewUrl` (`components/Lightbox.tsx:237`). Und `imageUrl()` steht per
|
||
Default auf `'preview'` (`lib/urls.ts:29`) — eine Suche über `app/`, `components/`
|
||
und `lib/urls.ts` findet **keine einzige Stelle, die `'original'` anfordert**. Die
|
||
oberste Größenstufe aus `lib/imageSize.ts` ist im gesamten Frontend unerreichbar.
|
||
|
||
Das ist als Default vollkommen richtig — Originale an jeden Besucher auszuliefern wäre
|
||
verschwenderisch, und `resolveImageSize()` verhindert das aus gutem Grund. Aber es
|
||
heißt: Der Lightbox zeigt heute Immichs Preview, nicht die Aufnahme. Wer Schärfe
|
||
beurteilen will — der Fotograf selbst, und jeder Kunde, der bei der Auswahl auf den
|
||
Fokus schaut — kann das nicht.
|
||
|
||
**Idee:** Klick oder Pinch schaltet auf `original` um und erlaubt Pan. Erst bei dieser
|
||
Geste wird die große Datei geholt, nie vorher. Bewusst getrennt von den bereits
|
||
gelisteten Punkten Fullscreen und Download: Zoom ist Beurteilung, nicht Präsentation
|
||
und nicht Übergabe.
|
||
|
||
**Nebenbei zu korrigieren:** der Kommentar in `Lightbox.tsx:5`. Er beschreibt eine
|
||
Absicht, nicht das Verhalten.
|
||
|
||
---
|
||
|
||
### B3. Farbmanagement — **eine offene Frage, keine Behauptung, S für die Messung**
|
||
|
||
Aus B2 folgt eine Frage, die ich mit Codelesen allein nicht beantworten kann und die
|
||
deshalb hier als **Messaufgabe** steht, nicht als Befund:
|
||
|
||
Fotografen arbeiten in AdobeRGB oder Display-P3. Wenn Folio ausschließlich Immichs
|
||
Preview-Tier ausliefert (siehe B2), dann hängt die Farbtreue des gesamten Portfolios
|
||
daran, was Immich beim Erzeugen dieser Previews mit dem Farbprofil macht — und ob
|
||
`streamAsset()` das Profil mit durchreicht. Fehlt es, rendert der Browser die Bytes
|
||
als sRGB: Wide-Gamut-Material wirkt dann flau oder, umgekehrt eingebettet,
|
||
übersättigt. Und zwar ausgerechnet auf dem guten Display, an dem der Fotograf sitzt.
|
||
|
||
**Testweg:** Eine Datei mit sichtbar breitem Gamut (gesättigtes Rot/Cyan) in AdobeRGB
|
||
nach Immich laden, in Folio öffnen, die ausgelieferten Bytes auf ein eingebettetes
|
||
ICC-Profil prüfen und gegen dieselbe Datei lokal im Browser vergleichen.
|
||
|
||
**Wenn sich ein Verlust zeigt,** sind die Antworten der Reihe nach: Profil im Proxy
|
||
mit durchreichen (Header und Bytes bleiben unangetastet — `streamAsset()` streamt
|
||
ohnehin unverändert); und für die Zoom-Ansicht aus B2 gleich das Original nehmen, das
|
||
sein Profil mitbringt.
|
||
|
||
**Wenn sich keiner zeigt,** ist der Abschnitt einen Satz in der Doku wert — „Folio
|
||
liefert Immichs Previews unverändert aus, inklusive Farbprofil" — und damit erledigt.
|
||
Auch das ist ein Ergebnis: Farbtreue ist bei dieser Zielgruppe ein
|
||
Vertrauensargument, und ein belegter Satz dazu ist mehr wert als ein Feature.
|
||
|
||
---
|
||
|
||
## C. Vertrauen & Privatsphäre
|
||
|
||
### C1. Ortsangaben pro Album steuern — **S**
|
||
|
||
**Befund, sorgfältig gelesen:** Die Map ist datenschutzseitig deutlich besser gebaut,
|
||
als man befürchten würde. Passwortgeschützte Alben werden vor der Aggregation
|
||
herausgefiltert (`app/api/map/route.ts:63-66`), und `lib/mapService.ts:5-11` hält
|
||
Alben ausdrücklich getrennt, damit genau das möglich ist. Die öffentliche EXIF-Route
|
||
gibt Koordinaten gar nicht erst heraus.
|
||
|
||
Die Lücke ist eine andere und feiner: Für **öffentliche** Alben wird ein Marker aus
|
||
dem **Mittelwert der tatsächlichen Koordinaten** aller Fotos an diesem Ort gebildet.
|
||
Bei einem Reisealbum über eine ganze Stadt ist das unkritisch. Bei einem Album, das an
|
||
_einem_ Ort entstanden ist — der eigene Garten, das Wohnzimmer eines Kunden, das
|
||
Studio, ein empfindlicher Naturstandort —, ist der Mittelwert genau dieser eine Ort.
|
||
Der Marker heißt zwar nach der Stadt, steht aber auf dem Grundstück.
|
||
|
||
Niemand trifft diese Entscheidung heute bewusst; sie ergibt sich daraus, dass die
|
||
Kamera GPS mitschreibt.
|
||
|
||
**Idee:** Eine Granularität pro Album und pro Subpage:
|
||
|
||
```yaml
|
||
location: exact # heutiges Verhalten
|
||
location: city # auf das Stadtzentrum runden, nicht mitteln
|
||
location: country # nur im Land verorten
|
||
location: hidden # gar nicht auf der Karte
|
||
```
|
||
|
||
Der Eingriff sitzt in `lib/mapService.ts`, wo bereits pro Album aggregiert wird — die
|
||
Stelle, an der man die Auflösung reduziert, existiert also schon.
|
||
|
||
**Warum das zieht:** Es macht aus einer stillschweigenden Preisgabe eine bewusste
|
||
Entscheidung. Für ein Projekt, dessen Verkaufsargument „dein Immich bleibt privat"
|
||
lautet, ist das kein Nebenfeature, sondern eine Konsequenz derselben Haltung.
|
||
|
||
---
|
||
|
||
### C2. Terminierte Veröffentlichung — **S**
|
||
|
||
**Befund:** `draft: true` gibt es nur für Journal-Einträge (`app/journal/page.tsx:33`,
|
||
Drafts bleiben für den eingeloggten Admin sichtbar — ein gutes Muster). Alben und
|
||
Subpages sind live, sobald sie in der YAML stehen. Wer eine Seite vorbereiten will,
|
||
muss sie entweder verstecken (`hidden: true`, seit #431) und im richtigen Moment von
|
||
Hand umstellen, oder sie erst im letzten Moment anlegen.
|
||
|
||
**Idee:** Ein `publishAt`-Datum für Alben, Subpages und Journal-Einträge. Vor dem
|
||
Termin verhält sich der Eintrag wie ein Draft: für den Admin sichtbar, für alle
|
||
anderen nicht vorhanden.
|
||
|
||
**Warum das billig ist:** Alle Seiten sind `force-dynamic`. Es braucht keinen
|
||
Scheduler, keinen Cron, keinen Hintergrundjob — nur einen Datumsvergleich beim
|
||
Ableiten der Galerie, an derselben Stelle, an der heute schon `enabled` und `hidden`
|
||
ausgewertet werden.
|
||
|
||
**Warum es trifft:** Es ist ein realer Ablauf, kein hypothetischer. Die
|
||
Hochzeitsgalerie geht Freitag um 18 Uhr auf, wenn das Paar aus den Flitterwochen
|
||
zurück ist. Die Serie erscheint zum Ausstellungstermin. Das Journal zum Buchstart.
|
||
Heute heißt das: Wecker stellen und selbst am Rechner sitzen.
|
||
|
||
**Ein Detail, das mitgedacht gehört:** Der RSS-Feed aus D darf einen terminierten
|
||
Eintrag nicht vorab ausliefern — dieselbe Prüfung, dieselbe Stelle.
|
||
|
||
---
|
||
|
||
## D. RSS/Atom-Feed — konkretisiert
|
||
|
||
Steht seit Mai als Einzeiler in [`brainstorm.md`](brainstorm.md) („`/feed.xml` mit
|
||
neuen Alben", Zeile 23) und dort auf Platz 1 der Reihenfolge. Verifiziert: eine
|
||
Feed-Route existiert nicht. Hier zum ersten Mal durchdacht — und der interessante
|
||
Teil ist nicht das XML.
|
||
|
||
**Der eigentliche Inhalt dieses Features ist die Ausschlussliste.** Ein Feed sammelt
|
||
genau das ein, was die Zugangskontrolle sonst verbirgt: Titel, Beschreibungen,
|
||
Cover-Bilder, Veröffentlichungsdaten. Er ist damit die perfekte Leak-Fläche, und
|
||
zwar eine, die niemandem auffällt, weil sie im Browser nie sichtbar wird. Draußen
|
||
bleiben müssen:
|
||
|
||
- passwortgeschützte Subpages und Alben (`password:` auf beiden Ebenen)
|
||
- `hidden: true`-Subpages — sie sind bewusst nur per Direktlink erreichbar, und ein
|
||
Feed ist das Gegenteil eines Direktlinks
|
||
- Journal-Drafts (`draft: true`)
|
||
- alles mit einem `publishAt` in der Zukunft, falls C2 kommt
|
||
- Alben, die per Client-Link aus A1 zugänglich sind
|
||
|
||
**Zwei Quellen, ein Feed:** Journal-Einträge (haben Datum, Titel, Excerpt und Cover —
|
||
alles schon da) und neu hinzugekommene Alben. Cover-Bilder über den bestehenden
|
||
`/api/og`-Weg, damit kein neuer Bildpfad entsteht.
|
||
|
||
**Was es absichert:** ein Test, der die Ausschlussregel festschreibt — analog zu
|
||
`app/api/admin/__tests__/admin-guards.test.ts`, also **tabellengetrieben über die
|
||
Kategorien**, nicht als Sammlung von Einzelfällen. Dann schlägt er auch bei einer
|
||
künftig hinzugefügten Sichtbarkeitsregel an, die jemand im Feed zu berücksichtigen
|
||
vergisst.
|
||
|
||
**Aufwand:** S für den Feed. Die Sorgfalt steckt komplett in der Sichtbarkeitsprüfung —
|
||
und die ist der Grund, warum dieser Punkt hier nochmal auftaucht, statt als Einzeiler
|
||
stehenzubleiben.
|
||
|
||
---
|
||
|
||
## Anhang: zwei Kleinigkeiten zur Auffindbarkeit
|
||
|
||
Kurz gehalten, weil Auffindbarkeit diesmal nicht der Schwerpunkt war — aber beide sind
|
||
XS und stehen in keiner der alten Listen:
|
||
|
||
- **Es gibt weder `app/sitemap.ts` noch `app/robots.ts`.** Robots-Direktiven existieren
|
||
nur auf Meta-Ebene (`app/layout.tsx:37-48`). Next.js erzeugt beide Dateien aus je
|
||
einer Funktion; die Album- und Subpage-Liste liegt in `getConfig()` bereit. Dieselbe
|
||
Ausschlussliste wie beim Feed gilt auch hier.
|
||
- **Kein JSON-LD.** Für ein Fotografie-Portfolio ist `ImageObject` mit `creator` und
|
||
`license` die eine strukturierte Angabe, die sich wirklich auszahlt — Google Bilder
|
||
zeigt Lizenzhinweise an, und es ist die einzige Stelle, an der ein Fotograf seine
|
||
Urheberschaft maschinenlesbar an die Bilder heftet. Passt inhaltlich zu A2: wer
|
||
Lizenzanfragen will, sollte auffindbar machen, dass Lizenzen zu haben sind.
|
||
|
||
---
|
||
|
||
## Empfohlene Reihenfolge
|
||
|
||
**Erst — klein, sofort spürbar:**
|
||
|
||
1. **C2** Terminierte Veröffentlichung · _S_ — ein Datumsvergleich, ein echter Ablauf
|
||
2. **C1** Ortsangaben pro Album · _S_ — die Stelle im Code existiert bereits
|
||
3. **B2** 1:1-Zoom · _S_ — und der falsche Kommentar in `Lightbox.tsx:5` fällt mit weg
|
||
|
||
**Dann — die zwei mit dem größten Hebel:**
|
||
|
||
4. **B1** Sequenzierung wie im Fotobuch · _M_ — das Alleinstellungsmerkmal
|
||
5. **A1** Ablaufende Client-Links · _M_ — das Feature, das aus dem Portfolio ein
|
||
Arbeitswerkzeug macht
|
||
|
||
**Danach:**
|
||
|
||
6. **D** RSS-Feed · _S_ — mit der Ausschlussliste als eigentlicher Arbeit
|
||
7. **A2** Anfrage-Formular · _S–M_ — mit Webhook beginnen, SMTP später
|
||
8. **A3** Proofing-Notizen · _S_ — kleine Variante
|
||
9. **B3** Farbmanagement messen · _S_ — Ergebnis offen, Erkenntnis in jedem Fall wertvoll
|
||
10. Anhang: Sitemap, `robots.ts`, JSON-LD · _XS_
|
||
|
||
---
|
||
|
||
## Roter Faden
|
||
|
||
Drei Sätze halten die Auswahl zusammen.
|
||
|
||
**Ein Portfolio ist Arbeit, nicht nur Ausstellung.** A1–A3 begleiten den Weg, den ein
|
||
Auftragsbild ohnehin nimmt — Übergabe, Rückmeldung, Anfrage. Folio zeigt heute nur
|
||
den mittleren Teil davon.
|
||
|
||
**Reihenfolge ist Handwerk.** B1 ist der einzige Punkt hier, den kein vergleichbares
|
||
Werkzeug bietet, und er trifft die Zielgruppe genau dort, wo sie anspruchsvoll ist.
|
||
|
||
**Privatsphäre gilt nach außen genauso wie nach innen.** Das Versprechen lautet „dein
|
||
Immich bleibt privat". C1 und C2 ziehen dieselbe Linie für das, was die
|
||
veröffentlichte Seite über Orte und Zeitpunkte verrät — und D stellt sicher, dass ein
|
||
Feed sie nicht hintenherum wieder aufmacht.
|