Initial Roux Hugo site — fashion journal for roux.pivoine.art

100-post fashion journal generated from ~/projects/ginger content:
- Hugo Extended static site with TailwindCSS v4
- WebP image pipeline (thumb/card/og/full sizes via Hugo image processing)
- Full SEO: sitemap (501 URLs), OpenGraph with per-post images, Twitter cards
- Async page transitions via View Transitions API
- Deep-linked URLs: /posts/[slug]/, /categories/[cat]/, /tags/[tag]/, /issues/
- Lightbox with keyboard/swipe nav, thumbnail strip, inverted search index
- Issues archive with quarterly release structure
- Multi-stage Dockerfile (Tailwind → Hugo → nginx:alpine)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 16:27:47 +02:00
commit f537f32295
229 changed files with 4888 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
<footer class="foot">
<div>
<h4>Roux</h4>
<h2 class="foot__roux">R<em>o</em>ux<sup style="font-family:var(--mono);font-size:11px;letter-spacing:.14em;color:var(--ink-soft);vertical-align:top;margin-left:8px;">№{{ .Site.Params.issueNumber }}</sup></h2>
<p>A slow-publishing fashion journal, gathered in Paris. One hundred photographs at a time, printed and unprinted.<br/>roux.pivoine.art</p>
</div>
<div>
<h4>Categories</h4>
<p><a href="/categories/gothic/">Gothic</a></p>
<p><a href="/categories/cyberpunk/">Cyberpunk</a></p>
<p><a href="/categories/dark-fantasy/">Dark Fantasy</a></p>
<p><a href="/categories/sci-fi/">Sci-Fi</a></p>
<p><a href="/categories/cultural/">Cultural</a></p>
</div>
<div>
<h4>Index</h4>
<p><a href="/tags/cape/">Cape</a></p>
<p><a href="/tags/neon/">Neon</a></p>
<p><a href="/tags/rain/">Rain</a></p>
<p><a href="/tags/gothic/">Gothic</a></p>
<p><a href="/tags/warrior/">Warrior</a></p>
</div>
<div>
<h4>Colophon</h4>
<p>Set in Italiana &amp; Cormorant Garamond, with Outfit for typographic furniture. © Roux MMXXVI.</p>
<p style="margin-top:14px;color:var(--ink)">Press <span style="border:1px solid var(--rule);padding:3px 6px;border-radius:3px;font-family:var(--mono);font-size:10px">⌘K</span> from anywhere to search.</p>
</div>
</footer>
+30
View File
@@ -0,0 +1,30 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>{{ if .IsHome }}{{ .Site.Title }} — {{ .Site.Params.description | truncate 60 }}{{ else }}{{ .Title }} — {{ .Site.Title }}{{ end }}</title>
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}" />
<link rel="canonical" href="{{ .Permalink }}" />
{{- template "_internal/opengraph.html" . }}
{{- template "_internal/twitter_cards.html" . }}
{{- template "_internal/schema.html" . }}
{{/* Add og:image from page resource */}}
{{- $img := .Resources.GetMatch "*.png" }}
{{- if $img }}
{{- $og := $img.Resize "1200x630 webp q80" }}
<meta property="og:image" content="{{ $og.Permalink }}" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="{{ $og.Permalink }}" />
{{- end }}
<link rel="icon" type="image/svg+xml" href="/assets/roux-mark.svg" />
<link rel="apple-touch-icon" href="/assets/roux-mark.svg" />
<link rel="mask-icon" href="/assets/roux-mark.svg" color="#8a3322" />
<meta name="theme-color" content="#f1ebe0" />
<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 .OutputFormats.Get "RSS" }}<link rel="alternate" type="{{ .MediaType.Type }}" title="{{ $.Site.Title }}" href="{{ .Permalink }}" />{{ end }}
+38
View File
@@ -0,0 +1,38 @@
{{- $cats := slice "Gothic" "Cyberpunk" "Dark Fantasy" "Urban" "Noir" "Fantasy" "Cultural" "Sci-Fi" "Boudoir" "Steampunk" "Luxury" "Action" "Lifestyle" "Nature" "Romantic" "Nightlife" "Elegant" "Adventure" "Mythology" }}
<header class="masthead" id="masthead">
<div class="masthead__inner">
<div class="masthead__left">
<span class="masthead__date" id="mhDate"></span>
<span class="mh-issue">№ {{ .Site.Params.issueNumber }}</span>
<span class="mh-sep" style="opacity:.5">·</span>
<span class="mh-pub">Roux Quarterly</span>
</div>
<a class="masthead__logo" href="/" aria-label="Roux — home">
{{- partial "logo.html" . }}
</a>
<div class="masthead__right">
<a href="/issues/" class="mh-link">Issues</a>
<span class="mh-sep" style="opacity:.5">·</span>
<span class="mh-city">Paris</span>
</div>
</div>
<div class="subhead" style="position:relative">
<label class="subhead__search" for="searchInput">
<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"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input id="searchInput" type="search" autocomplete="off" placeholder="Search the archive — silk, nocturne, atelier…" />
<span class="subhead__kbd">⌘ K</span>
</label>
<div class="subhead__count" id="count"></div>
<div class="searchpop" id="searchpop"></div>
</div>
<div class="tabs" id="tabs">
<button data-cat="All" aria-pressed="true">All</button>
{{- range $cats }}
<button data-cat="{{ . }}" aria-pressed="false">{{ . }}</button>
{{- end }}
</div>
</header>
+31
View File
@@ -0,0 +1,31 @@
<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">
<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>
<g fill="url(#lbBloom)" transform="translate(32 32) rotate(30)"><ellipse cx="0" cy="-11" rx="8" ry="11"/><ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(60)"/><ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(120)"/><ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(180)"/><ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(240)"/><ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(300)"/></g>
<g fill="#9a3a26" transform="translate(32 32)"><ellipse cx="0" cy="-6" rx="5" ry="7.5"/><ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(72)"/><ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(144)"/><ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(216)"/><ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(288)"/></g>
<circle cx="32" cy="32" r="3.2" fill="#3a120c"/>
<circle cx="32" cy="31.4" r="1.2" fill="#c0573c" opacity=".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>
<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>
</button>
</div>
<div class="lb__stage">
<button class="lb__nav lb__nav--prev" data-act="prev" aria-label="Previous">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg>
</button>
<div class="lb__track" id="lbTrack"></div>
<button class="lb__nav lb__nav--next" data-act="next" aria-label="Next">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg>
</button>
</div>
<aside class="lb__meta" id="lbMeta"></aside>
<div class="lb__thumbs" id="lbThumbs"></div>
</div>
+38
View File
@@ -0,0 +1,38 @@
<span class="logo">
<svg class="logo__mark" viewBox="0 0 64 64" aria-hidden="true">
<defs>
<radialGradient id="mhBloom" 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>
<g fill="url(#mhBloom)" transform="translate(32 32) rotate(30)">
<ellipse cx="0" cy="-11" rx="8" ry="11"/>
<ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(60)"/>
<ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(120)"/>
<ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(180)"/>
<ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(240)"/>
<ellipse cx="0" cy="-11" rx="8" ry="11" transform="rotate(300)"/>
</g>
<g fill="#9a3a26" transform="translate(32 32)">
<ellipse cx="0" cy="-6" rx="5" ry="7.5"/>
<ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(72)"/>
<ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(144)"/>
<ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(216)"/>
<ellipse cx="0" cy="-6" rx="5" ry="7.5" transform="rotate(288)"/>
</g>
<circle cx="32" cy="32" r="3.2" fill="#3a120c"/>
<circle cx="32" cy="31.4" r="1.2" fill="#c0573c" opacity=".7"/>
</svg>
<span class="logo__word">Roux</span>
<span class="logo__tag">Le Journal · Paris</span>
</span>