Add issue No. 02 "Obsession" + reusable image pipeline
Content - 100 new plates under content/posts/02/ — one recurring red-haired model across 10 editorial registers (Haute Couture, Film Noir, Boudoir, Avant-Garde, Minimalism, Baroque, Street Style, Surrealism, Monochrome, Nocturne), generated with flux-1.1-pro, face-swapped to a consistent identity (FaceFusion), and upscaled (Upscayl + Remacri, 3328x4992). - content/issues/02/_index.md; issue 01 -> status archived; hugo.toml params (issueIds newest-first, issueNumber/Name/Season/Blurb). Structure - Plate bundles grouped by issue: content/posts/<issue>/<slug>/, with build.render:never stubs so /posts/<issue>/ isn't emitted. nginx 301s the legacy flat /posts/<slug>/ URLs to /posts/01/<slug>/. The /posts/ archive uses .RegularPagesRecursive. Image pipeline (scripts/, data/ gitignored) - generate-images.py — Replicate flux-1.1-pro, 960x1440, idempotent. - faceswap-images.py — FaceFusion batch-run, one consistent face. - upscale-images.py — Upscayl + remacri-4x, long edge clamped to 4992. - build-issue.py — prompts JSON -> content/posts/<issue>/*/index.md. Build - CSS now compiled by Hugo's css.TailwindCSS (partials/css.html + templates.Defer); dropped the standalone Tailwind CLI step, concurrently, and the gitignored static/css/main.css. Requires Hugo >= 0.161; Dockerfile collapsed to a single hugomods/hugo:debian-node build stage. pnpm-workspace.yaml: preferSymlinkedExecutables + allowBuilds. Front end - Pagination 8 per page. - Lightbox: brand mark and category link out; robust SPA back/forward (fetch before startViewTransition, single-flight guard, swallow the transition abort rejection, popstate re-renders / reopens the viewer). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DZPmxGywFnAhmYJB1eh9fm
This commit is contained in:
+1
-1
@@ -32,7 +32,7 @@
|
||||
{{/* Body */}}
|
||||
<p class="font-serif italic text-[clamp(14px,1.1vw,17px)] leading-[1.65] text-ink-2 max-w-[40ch] m-0 mb-10">
|
||||
The photograph you're looking for may have been moved, archived, or perhaps it was never printed.
|
||||
One hundred plates remain in the archive — return and find your frame.
|
||||
Every plate remains in the archive — return and find your frame.
|
||||
</p>
|
||||
|
||||
{{/* CTAs */}}
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
{{- end }}
|
||||
</section>
|
||||
|
||||
{{- $paginator := .Paginate .Pages }}
|
||||
{{- $items := cond (eq .Kind "section") .RegularPagesRecursive .Pages }}
|
||||
{{- $paginator := .Paginate $items }}
|
||||
<section id="grid" data-density="default"
|
||||
data-filter-type="{{ .Kind }}"
|
||||
data-filter-value="{{ .Title }}"
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
{{- end }}
|
||||
</section>
|
||||
|
||||
{{/* Tell JS which slug to open in the lightbox */}}
|
||||
{{/* Tell JS which slug to open in the lightbox (script for first load, data attr for SPA nav) */}}
|
||||
<span data-open-slug="{{ .Params.slug }}" hidden></span>
|
||||
<script>window.__ROUX_OPEN_SLUG = "{{ .Params.slug }}";</script>
|
||||
{{ end }}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
bg-ink text-paper
|
||||
font-sans font-medium text-[11px] leading-none tracking-[.16em] uppercase
|
||||
transition-transform duration-300">
|
||||
<span>Roux № {{ .Site.Params.issueNumber }} — out now. <a href="/issues/01/" class="border-b border-current ml-1">See the plates →</a></span>
|
||||
<span>Roux № {{ .Site.Params.issueNumber }} — out now. <a href="/issues/{{ .Site.Params.issueNumber }}/" class="border-b border-current ml-1">See the plates →</a></span>
|
||||
<button id="ribbonClose" aria-label="Dismiss"
|
||||
class="w-6 h-6 shrink-0 grid place-items-center border border-current/30 rounded-full
|
||||
opacity-60 hover:opacity-100 transition-opacity duration-200">
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
{{- $post := dict
|
||||
"id" .Params.plate
|
||||
"slug" .Params.slug
|
||||
"issue" (index (.Params.issues | default (slice "01")) 0)
|
||||
"title" .Title
|
||||
"description" .Params.description
|
||||
"categories" .Params.categories
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
{{- $issuePage := $.Site.GetPage (printf "/issues/%s" $issueNum) }}
|
||||
{{- $plates := cond (ne $issuePage nil) $issuePage.Pages .Site.RegularPages }}
|
||||
{{- $total := len $plates }}
|
||||
{{- $featured := where .Site.RegularPages ".Params.featured" true }}
|
||||
{{- $featured := where $plates ".Params.featured" true }}
|
||||
|
||||
{{/* ── Hero ── */}}
|
||||
<section id="hero"
|
||||
@@ -60,7 +60,7 @@
|
||||
{{/* ── Plate preview ── */}}
|
||||
<section id="grid"
|
||||
class="grid [grid-template-columns:repeat(auto-fill,minmax(220px,1fr))] gap-[var(--gap)] px-[var(--pad)] pt-[var(--gap)] pb-0">
|
||||
{{- range $i, $p := $featured }}
|
||||
{{- range $i, $p := (first 5 $featured) }}
|
||||
{{- partial "card.html" (dict "Page" $p "Index" $i) }}
|
||||
{{- end }}
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- with resources.Get "css/main.css" }}
|
||||
{{- $opts := dict "minify" (not hugo.IsDevelopment) }}
|
||||
{{- with . | css.TailwindCSS $opts }}
|
||||
{{- if hugo.IsDevelopment }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}">
|
||||
{{- else }}
|
||||
{{- with . | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -27,7 +27,9 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Italiana&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400;1,500&family=Outfit:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="/css/main.css" />
|
||||
{{- with (templates.Defer (dict "key" "global")) }}
|
||||
{{- partial "css.html" . }}
|
||||
{{- end }}
|
||||
{{- if hugo.IsProduction }}
|
||||
<script defer src="{{ .Site.Params.umamiSrc }}" data-website-id="{{ .Site.Params.umamiId }}"></script>
|
||||
{{- end }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="lb" id="lb" data-open="false" role="dialog" aria-modal="true" aria-label="Roux plate viewer">
|
||||
<div class="lb-topbar">
|
||||
<div class="lb-brand">
|
||||
<a class="lb-brand" href="/" aria-label="Roux — home">
|
||||
<svg viewBox="0 0 64 64" aria-hidden="true" style="height:24px;width:24px;flex:0 0 auto">
|
||||
<defs><radialGradient id="lbBloom" cx="50%" cy="46%" r="58%"><stop offset="0" stop-color="#b34a30"/><stop offset=".6" stop-color="#8a3322"/><stop offset="1" stop-color="#5a1d15"/></radialGradient></defs>
|
||||
<g fill="#6e2519" transform="translate(32 32)"><ellipse cx="0" cy="-16" rx="10.5" ry="14"/><ellipse cx="0" cy="-16" rx="10.5" ry="14" transform="rotate(60)"/><ellipse cx="0" cy="-16" rx="10.5" ry="14" transform="rotate(120)"/><ellipse cx="0" cy="-16" rx="10.5" ry="14" transform="rotate(180)"/><ellipse cx="0" cy="-16" rx="10.5" ry="14" transform="rotate(240)"/><ellipse cx="0" cy="-16" rx="10.5" ry="14" transform="rotate(300)"/></g>
|
||||
@@ -11,7 +11,7 @@
|
||||
</svg>
|
||||
<span style="font:400 22px/1 'Italiana',serif;letter-spacing:.04em;color:#f5f0e6">Roux</span>
|
||||
<span style="opacity:.55">№ {{ .Site.Params.issueNumber }} · The Plates</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="lb-index" id="lbIndex">000 / 100</div>
|
||||
<button class="lb-close" data-act="close" aria-label="Close">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
|
||||
|
||||
Reference in New Issue
Block a user