Commit Graph
48 Commits
Author SHA1 Message Date
valknarandClaude Sonnet 5 fc3f45fd65 content: drop "Roux Quarterly" from the masthead
Publication isn't on a fixed quarterly schedule.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DZPmxGywFnAhmYJB1eh9fm
2026-08-30 00:15:56 +02:00
valknarandClaude Sonnet 5 0b0fb8d199 fix(lightbox): slideshow navigation writes browser history
goToSlide() was replaceState()-ing, so paging through the viewer left a
single history entry — browser Back skipped every plate you'd looked at.
It now pushState()s on each user-driven slide (guarded to fire only when the
index actually changes), popstate slides the viewer back/forward without
stacking entries, and the first entry on a directly-loaded plate page is
tagged with its slug so Back to it is handled in-place.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DZPmxGywFnAhmYJB1eh9fm
2026-08-29 23:34:51 +02:00
valknarandClaude Sonnet 5 2dc7a0063f 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
2026-08-29 21:11:24 +02:00
valknarandClaude Sonnet 4.6 1480f73a8f perf(nginx): add open_file_cache to reduce overlay2 filesystem overhead
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 10:45:32 +02:00
valknarandClaude Sonnet 4.6 ba9a9dc9c4 Update page title, URL and meta when navigating between lightbox slides
goToSlide() now calls history.replaceState + updates document.title,
description, og:title/description/url and canonical on each slide change.
replaceState is used so swipe/keyboard navigation doesn't pollute history.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:03:08 +02:00
valknarandClaude Sonnet 4.6 9900b193f6 Fix page meta not updating on client-side post navigation
When a card was clicked, history.pushState changed the URL but left
document.title, description, og:*, and canonical pointing at the
overview page. navigate() also only updated document.title, not meta.

Add setMeta/syncHeadMeta helpers; update title+meta from POSTS data on
card open, and sync all head meta from the fetched document in navigate().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:00:45 +02:00
valknarandClaude Sonnet 4.6 9b8f03d4ff Add Pivoine attribution link to footer colophon
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 17:23:40 +02:00
valknarandClaude Sonnet 4.6 9434c9f192 Add favicon PNGs, Apple touch icon, and PWA webmanifest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:57:54 +02:00
valknar 24733bca05 fix: tailwind hover patch 2026-06-10 11:01:06 +02:00
valknarandClaude Sonnet 4.6 c9a30a38d7 Fix lightbox close button squishing to oval on narrow mobile screens
flex-shrink: 0 keeps the button at exactly 36×36 px so border-radius: 50%
stays a circle. lb-brand gets min-width: 0 + overflow: hidden so the
brand text yields space instead of pushing the close button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:55:21 +02:00
valknarandClaude Sonnet 4.6 be24904b78 Add swipe and keyboard navigation to the pure image zoom overlay
Arrow keys and touch swipe now navigate between plates while the
zoom is open, keeping the lightbox in sync underneath. goToZoomSlide
clamps to list bounds and delegates to goToSlide for thumb/index sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:52:05 +02:00
valknarandClaude Sonnet 4.6 3b359d2b37 Add full-image zoom overlay to single post pages
A "View full image" button appears in the single-post hero alongside
the return link. Clicking the lightbox main image also opens the same
overlay from any page. The overlay is pure image on a near-black
backdrop; click backdrop, close button, or Escape to dismiss.

Escape is layered: closes zoom first, then lightbox if zoom is not open.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:46:24 +02:00
valknarandClaude Sonnet 4.6 81e7417a1d Add README.md and CLAUDE.md
README: project overview, stack, dev/build commands, content
import workflow, design tokens, deployment notes.
CLAUDE.md: Claude Code guidance — commands, CSS pipeline, content
model, layout hierarchy, JS architecture, data flow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 07:56:55 +02:00
valknarandClaude Sonnet 4.6 53ff24ef46 Issue 01: title "Devotion", updated description
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:54:16 +02:00
valknarandClaude Sonnet 4.6 ce3f79dd61 Footer: use site params.description instead of hardcoded text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:49:06 +02:00
valknarandClaude Sonnet 4.6 ed1cffef34 Remove all Paris branding references
Journal is online-only; removed "gathered in Paris" from footer and
imprint, "· Paris" from logo tagline and 404 colophon, and the Paris
span from the header nav. Post content (paris-bridge-crimson-dusk)
left untouched as that refers to the photograph subject.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:45:49 +02:00
valknarandClaude Sonnet 4.6 3bfa3fed5c Footer: replace icon with Roux wordmark, remove column title
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:43:20 +02:00
valknarandClaude Sonnet 4.6 7cf9ab5a9b Remove roux.pivoine.art URL from footer brand column
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:40:44 +02:00
valknarandClaude Sonnet 4.6 4267d57c30 Refine footer: mark-only logo, dynamic top categories and tags
Replace oversized Roux wordmark with the 42px SVG flower mark
(no title). Categories and Tags columns now use .ByCount so the
5 most-assigned terms are shown rather than hardcoded names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:39:42 +02:00
valknarandClaude Sonnet 4.6 fd1b0f2d46 Fix text-paper (and all utility colours) being overridden on <a> tags
Global resets (a, button, body, img) were outside any @layer, so
they beat Tailwind's @layer utilities in the cascade. Wrapping them
in @layer base restores the expected order: base < utilities.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:35:03 +02:00
valknarandClaude Sonnet 4.6 e488d45fa3 Add imprint page and header nav link
Editorial prose layout with legal notice, copyright, AI training
exclusion, and analytics disclosure. Valknar / valknar@pivoine.art
as responsible person. Imprint link added to right nav (hidden
below 820 px breakpoint).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:30:11 +02:00
valknarandClaude Sonnet 4.6 b7b11e763c Add 404 page matching editorial design language
Ghost-watermark 404 numeral, italic headline "gone to press",
russet CTA back to archive — same type stack and token system
as the rest of the site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:19:47 +02:00
valknarandClaude Sonnet 4.6 3bdcf7ee60 Fix /categories and /tags overview pages: render term cards with images
For kind=taxonomy pages, .Pages contains term pages (not posts), so
card.html was getting no images. Add a separate branch that renders
each term as a cover card using the first post's image, title, and
plate count.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:05:34 +02:00
valknarandClaude Sonnet 4.6 ab3d80457d Add custom robots.txt template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:00:25 +02:00
valknarandClaude Sonnet 4.6 bf3ccc6b9b Add Umami analytics in production
Script injected via hugo.IsProduction guard so it's absent during
hugo server dev mode. Src and website-id stored in hugo.toml params.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:59:20 +02:00
valknarandClaude Sonnet 4.6 da050dfd3c Style search cancel button to match ink-soft grey
Override the browser-default blue/accent-coloured × with a custom
SVG circle using --ink-soft (#5b4f44) so it blends with the UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:55:34 +02:00
valknarandClaude Sonnet 4.6 50047451d9 Fix lightbox thumb strip not scrolling to current plate on direct load
lbBuildThumbs() was called after goToSlide(), so the scroll in
syncThumbs() ran against an empty container. Reorder so thumbs are
built before goToSlide() positions them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:53:25 +02:00
valknarandClaude Sonnet 4.6 ea54fe949d Remove forthcoming issues 02 and 03
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:50:58 +02:00
valknarandClaude Sonnet 4.6 869e3e00d2 Replace data/issues.json with content/_index.md files per issue
Issue metadata (title, description, season, status) now lives in
content/issues/XX/_index.md. terms.html reads from those pages via
$.Site.GetPage, driven by issueIds param in hugo.toml. Removes the
JSON data file and its generation from import-posts.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:48:27 +02:00
valknarandClaude Sonnet 4.6 c766bba028 Homepage: show 5 featured plates, brand CTA button
Mark five posts (Gothic, Cyberpunk, Dark Fantasy, Urban, Sci-Fi) as
featured: true. Homepage grid now filters by that flag instead of
showing first 8. CTA button changed from plain black to brand russet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:44:49 +02:00
valknarandClaude Sonnet 4.6 39cffeb0bc Add pagination to category, tag, and issue pages (10 per page)
pagerSize set to 10 (5 columns × 2 rows). New pagination partial
renders prev/next links and numbered page buttons. Applied to
_default/list.html (categories + tags) and issues/list.html.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:33:21 +02:00
valknarandClaude Sonnet 4.6 84ff82ac44 Fix doubled border below search bar
The search bar had its own border-b which stacked with the header's
border-b once the category tabs row was removed. Drop the redundant
one from the search bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:30:01 +02:00
valknarandClaude Sonnet 4.6 9c9f420b12 Remove category tabs bar from header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:28:15 +02:00
valknarandClaude Sonnet 4.6 32a46a5a48 Redesign homepage as current-issue landing page
Replace full plate grid with issue identity hero (title, season,
description, logo), 8-plate preview, and CTA strip linking to the
full issue. All data is derived from the issues/01 taxonomy term page
so the page stays in sync when the issue changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:24:54 +02:00
valknarandClaude Sonnet 4.6 8513c1c021 Derive header category tabs from taxonomy instead of hardcoded list
Tabs now reflect only categories that actually have posts, so stale
entries like Noir can't appear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:22:20 +02:00
valknarandClaude Sonnet 4.6 7ca816a3aa Capitalise descriptions and add trailing period
Normalise all post descriptions at import time: first character uppercased,
period appended if missing. Regenerated all 101 page bundles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:13:13 +02:00
valknarandClaude Sonnet 4.6 598e2f0593 Fix search input losing focus on mouse click
The click-outside handler was checking for .subhead (a BEM class removed
in the Tailwind refactor) so every click including on the input itself
triggered closeSearch(). Now checks for the actual search label and popup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:10:55 +02:00
valknarandClaude Sonnet 4.6 54a87dc4ed Refactor: replace all BEM CSS with Tailwind utility classes
Remove all BEM component classes (hero__*, card__*, issue-card__*, foot__*,
masthead__*, searchpop__*, lb__*) from CSS and templates. Replace with
Tailwind v4 utility classes inline in HTML. Create card.html partial to
avoid repeating verbose utility strings across grid templates. Rename
lightbox CSS to flat lb-* and search popup to sp-*.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:06:55 +02:00
valknarandClaude Sonnet 4.6 e3e9cf6742 Fix Issues header link: /issue/ → /issues/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:38:19 +02:00
valknarandClaude Sonnet 4.6 b77fec34de Add issue number to card overlay (bottom-left)
Each card frame now shows № 01 at the bottom-left alongside the
existing plate number (top-left) and category (top-right).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:35:38 +02:00
valknarandClaude Sonnet 4.6 e8226b2e2f Fix tab highlight: exact category URL match instead of substring
/categories/dark-fantasy/ was also activating the Fantasy tab
because path.includes('fantasy') matched. Now compares the full
/categories/{slug}/ path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:33:42 +02:00
valknarandClaude Sonnet 4.6 073c4b804c Restore referrer URL on lightbox close
Save location.href before pushState when opening lightbox from a
grid page, and navigate back to it on close. Direct single-post
page loads still return to the issue page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:31:57 +02:00
valknarandClaude Sonnet 4.6 199883e8c6 Lightbox always scopes to full issue, not visible cards
Previously the lightbox list was built from whichever cards happened
to be in the DOM (e.g. only tagged posts on a /tags/ page). Now all
three open paths — card click, VTA navigation, and direct URL load —
scope the list to all posts sharing the same issue as the opened post.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:29:00 +02:00
valknarandClaude Sonnet 4.6 76f87d5009 One category per post, display in grid without tag
Import script now takes only the first CSV category per post.
All card grid templates simplified to show just that single
category in card__sub — no tag alongside it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:22:20 +02:00
valknarandClaude Sonnet 4.6 0ae8afbf7b Replace posts/001/slug nesting with issue taxonomy
Use Hugo's `issue = "issues"` taxonomy so each post carries
`issues: ["01"]` in frontmatter. Issue pages live at /issues/01/
with a dedicated _index.md holding title, season, and description.
The /issues/ archive page uses data/issues.json for forthcoming
entries that have no posts yet.

Layouts:
- layouts/issues/list.html → plate grid for a single issue term
- layouts/issues/terms.html → issues archive (new)
- _default/single.html → scopes grid to issue term page, back-link to /issues/01/
- baseof.html → ribbon links to /issues/01/, JSON island includes issue field
- partials/header.html → Issues link → /issues/

JS:
- lbClose() navigates to /issues/${issueId}/ on a single-post page
- lightbox meta panel shows linked Issue fact

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:09:39 +02:00
valknarandClaude Sonnet 4.6 a4463f03e3 Close lightbox before navigating on tag/category link click
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:43:19 +02:00
valknarandClaude Sonnet 4.6 e46baf497b Fix lightbox tags: add # prefix and link to tag pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:38:39 +02:00
valknarandClaude Sonnet 4.6 f537f32295 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>
2026-05-18 16:27:47 +02:00