Skip to content

Roman-inspired redesign with terracotta palette and Cinzel headings - #31

Closed
TomSeestern wants to merge 1 commit into
mainfrom
roman-redesign
Closed

Roman-inspired redesign with terracotta palette and Cinzel headings#31
TomSeestern wants to merge 1 commit into
mainfrom
roman-redesign

Conversation

@TomSeestern

Copy link
Copy Markdown
Owner

Full redesign: Flowbite→custom components, Next 15 + React 19, ESLint 9 flat config, Roman design system (drop caps, gold hairlines, sharp edges), CSS-first motion, a11y + Lighthouse QA. 22/22 tasks complete, all CI checks green.

…dings (#30)

* style: roman-inspired redesign with terracotta palette and Cinzel headings

Transform the portfolio visual identity from modern blue/Inter to a warm
Roman-inspired theme. The semantic token architecture means most changes
cascade from tailwind.config.js — components reference semantic tokens
rather than raw colors, so updating token values repaints the site.

Palette: terracotta (#C2410C) primary replacing blue, warm marble whites
for surfaces, warm charcoal text. Gold/amber accents preserved via accent
hierarchy. Dark mode parity maintained — every semantic token has a -dark
variant.

Typography: Cinzel (classical serif) for h1-h4 via CSS variable
--font-heading applied in layout. Inter retained for body text readability.

Scope:
- tailwind.config.js: new primary scale, recolored semantic tokens, added
  fontFamily.heading token, prose config auto-updates via theme() refs.
- app/layout.tsx: load Cinzel alongside Inter, expose --font-heading
  variable, apply via <style> to all headings.
- components/Tooltip: replace neutral-700 with surface-dark for warm
  dark-theme consistency, swap font-open-sans for font-body.
- app/contact/page.tsx: strip undefined dark:shadow-sm-light variant that
  was silently dropped by Tailwind JIT.

Verification:
- pnpm lint, prettier, build, test all pass
- WCAG AA contrast verified on 7 key foreground/background pairs
- All semantic tokens resolve; no missing references
- Dark mode parity confirmed across 8 components and 7 pages
- Visual smoke via Playwright confirms Cinzel loads and terracotta renders

Final Wave: F1 APPROVE | F2 APPROVE | F3 APPROVE | F4 APPROVE

* fix(canonical): align canonical URL with metadataBase

Canonical URLs in blog and project detail pages used the old tomsegbers.de domain, mismatching metadataBase (https://tom.segbers.de). Updated to match.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor: wire Button component into homepage and remove dead ProjectTeaser.imageUrl

Replaced two inline hero CTAs with existing Button component (primary/secondary lg variants). Removed unused imageUrl prop from ProjectTeaser's interface, destructure, JSDoc, test fixture, and Storybook story, plus 5 production callers. Applied readonly to re-touched ProjectProps. Deleted duplicate JPEG of hero portrait.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(peak): content depth, reading UX, motion polish, a11y/performance baseline

- Add rehype-pretty-code + remark-gfm for syntax-highlighted code blocks and GFM
- Add reading time pill and TOC sidebar (IntersectionObserver scroll-spy) to blog detail
- Add reading time pill to project detail
- Add tags Zod schema + tag pills on blog/project detail pages
- Add PageTransition (motion fade-in), HeroStagger (staggered hero), CardMotionWrapper (hover/tap)
- All motion components respect prefers-reduced-motion via useReducedMotion()
- Add /now, /uses pages with content/pages/ data layer
- Add RSS feed (app/feed.xml/route.ts)
- Add og-image routes (site-wide + per-blog-post)
- Add BlogPosting/CreativeWork JSON-LD structured data on detail pages
- Add per-post opengraph-image and canonical URL alignment
- Add loading.tsx, error.tsx, global-error.tsx (App Router hygiene)
- Add motion component smoke tests (CardMotionWrapper, HeroStagger, PageTransition)
- Add Lighthouse CI workflow (.github/workflows/lighthouse.yml)
- Add axe-playwright check to e2e static-routes spec
- Rewrite DESIGN.md for Roman palette + Cinzel + Motion
- Author peak-website blog post content
- Wire Button component to homepage, remove dead imageUrl prop
- Fix canonical URL to tom.segbers.de
- Remove boilerplate TODO comment from homepage

* chore: mark Final Wave F1-F4 complete — all APPROVE

* chore: remove dead deps (@vercel/otel, @opentelemetry/*, prop-types, tsc, patch-package)

Remove unused dependencies with zero imports across the codebase:

Dependencies removed:
- @vercel/otel — 3 production vulns, zero imports
- prop-types — zero imports

DevDependencies removed:
- @opentelemetry/api, @opentelemetry/resources, @opentelemetry/sdk-node,
  @opentelemetry/sdk-trace-node, @opentelemetry/semantic-conventions —
  5 packages, zero imports
- @storybook/testing-library — deprecated package
- @types/prop-types — companion to prop-types
- patch-package — no patches/ directory exists, dead overhead
- postinstall-postinstall — companion to patch-package
- tsc@2.0.4 — wrong package shadows typescript compiler (typescript@5.3.2 kept)

Scripts removed:
- postinstall: npx patch-package -y (patch-package is dead)

88 transitive packages pruned. pnpm-lock.yaml regenerated.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: drop Storybook (39 of 67 vulns, zero prod value)

Storybook 7 (EOL) contributed 39 of 67 Dependabot advisories:
tar 11 critical, axios 23 high, esbuild 1 moderate, sharp 1 high,
uuid 1 moderate, elliptic 1 low. Zero production value — 3 story
files existed but no stories/ directory was ever consumed.

Removed:
- devDependencies: storybook, @storybook/addon-essentials,
  @storybook/addon-interactions, @storybook/addon-links,
  @storybook/blocks, @storybook/nextjs, @storybook/react,
  @storybook/test-runner, eslint-plugin-storybook (9 packages)
- scripts: storybook, test-storybook, build-storybook
- .storybook/ directory (main.ts, preview.ts)
- 3 .stories.tsx files (Button, ArticleTeaser, ProjectTeaser)

Config changes:
- .eslintrc.js: removed plugin:storybook/recommended from extends
- check.yml: replaced Storybook smoke tests with Playwright e2e
- coupling-graph script: removed .storybook/ from --exclude pattern

583 transitive packages pruned. pnpm-lock.yaml regenerated.

Verification: build (47 pages), test (91 tests), lint (warnings only),
prettier (4 pre-existing issues on unmodified files).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* style: format pre-existing TSX files

Restore repository-wide Prettier compliance without behavioral changes.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: remove stale Storybook references

* chore: add pnpm audit overrides

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record pnpm override evidence

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* build: upgrade Next and React

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: await Next 15 request APIs

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: prevent reduced-motion hydration mismatch

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record Next 15 migration

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: restore CTA contrast

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): align Roman token assertions

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): serialize Chromium runner

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record E2E contrast repair

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): restore deterministic blog coverage

* chore: migrate ESLint 8 to 9 flat config

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document ESLint 9 migration

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: tighten ESLint flat config

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: clean lint warnings in app pages

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: clean route metadata lint warnings

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: order listing page imports

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: resolve remaining app lint warnings

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* style: use Tailwind size utilities

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* style: order motion component imports

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: use Next links in site chrome

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: update project teaser lint rules

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): order accessibility imports

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* style: order library imports

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record ESLint review correction

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): capture test inventory

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): capture full browser runs

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: add Roman font and color tokens

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: apply Garamond to long-form prose

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: keep tooltip text in UI font

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: add homepage Roman typography checks

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: align Roman color browser assertions

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record Roman font verification

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: repair semantic button contrast

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: restore article teaser dark text

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): wait for settled motion before Axe

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record Task 7 contrast verification

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: guard homepage marquee edges

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(e2e): harden Task 7 production audit

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: protect marquee edge text

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record Task 7 marquee verification

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: replace marquee with responsive project collection

Remove animated duplicate-track marquee and opaque edge guards. Mobile uses native scroll-snap (snap-x snap-mandatory, w-screen cards); desktop uses responsive grid (md:grid-cols-2 xl:grid-cols-3). All project cards render whole within collection bounds. Dead Tailwind theme entries (spacing.112, zIndex.marquee, animation.marquee/marquee2, keyframes) removed.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: update homepage tests for collection behavior

Replace marquee assertions with collection geometry checks: scroll-snap-type at mobile, display:grid at desktop, visible card bounds within collection, keyboard Tab+Enter project link navigation. Reduced-motion test asserts native scroll-snap at mobile viewport.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document project collection primitive

Add project collection section to DESIGN.md §5: ordered semantic list, mobile snap-x snap-mandatory, desktop responsive grid. Remove marquee animation references from §6. Update motion table to reflect native scroll-snap pattern.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: add card geometry assertions to production audit

Extend Axe audit script to verify visible project cards do not cross collection edges. Assert fullyInside for all visible cards at 375/1280 light/dark. Require TASK_7_AUDIT_URL env var (remove default port fallback).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: record Task 7 collection replacement verification

Add plan, evidence ledger, boulder status, and four production screenshots (375/1280 light/dark). All gates green: Prettier, ESLint, 91/91 Jest, 47/47 build, 0 Axe contrast violations, 43/43 E2E twice, two visual QA oracles PASS.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: replace Flowbite Alert with custom InlineAlert

Create components/InlineAlert/InlineAlert.tsx — semantic <div role="alert">
with success/failure variants via CVA, dismissible button using lucide-react
X icon. Replace Flowbite Alert in app/contact/page.tsx. Preserve fixed
positioning for success alert, mb-6 for failure alert, and dismiss behavior.

lucide-react added as dependency for X dismiss icon.

* feat: replace Flowbite Breadcrumb with custom Breadcrumbs

Create components/Breadcrumbs/Breadcrumbs.tsx — semantic <nav aria-label>
with <ol>/<li> structure per WCAG breadcrumb pattern. CSS pseudo-element
separator (/, hidden on last item). Replace HiHome from react-icons/hi
with lucide-react Home icon in all 4 pages. Preserve href links, truncate
className, and aria-current="page" semantics on current page item.

* feat: replace Flowbite Card with custom SurfaceCard

Create SurfaceCard component using CVA + tailwind-merge pattern,
matching the Flowbite Card two-layer structure (root article + inner
content div with p-6 padding). Replaces Card imports in ProjectTeaser
and ArticleTeaser with zero flowbite-react Card references remaining.

* feat: replace Flowbite DarkThemeToggle with custom ThemeToggle

Create ThemeToggle component using lucide-react Sun/Moon icons with
CSS-driven icon visibility (no hydration mismatch). Uses same
flowbite-theme-mode localStorage key as layout.tsx theme script.
Updates dark-mode E2E test selector and test name to match new
component. Navbar imports remain for task 12.

* feat: replace Flowbite Navbar with custom SiteHeader

* chore: remove flowbite-react, flowbite, react-icons, and 14 unused @radix-ui/* deps

* feat: apply Roman design system — sharp edges, drop caps, gold hairlines, letter-spacing

* refactor: replace Motion library with CSS-first animations

* refactor: enforce Tailwind token usage — replace hardcoded sizes and colors

* feat: craft pass — focus rings, empty states, microstate polish

* test: Phase 4 a11y + Lighthouse + visual acceptance verification

* chore: mark all 22/22 plan tasks complete

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: pnpm 9 compat — add packages field to workspace + mirror overrides in package.json

* fix: lighthouse CI uses next start instead of http-server out

* fix: cache playwright browsers in CI to prevent download hangs

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tomsegbers-de Ready Ready Preview, Comment Jul 23, 2026 9:51pm

Request Review

@github-actions

Copy link
Copy Markdown

📦 Next.js Bundle Analysis for tomsegbers-de

This analysis was generated by the Next.js Bundle Analysis action. 🤖

⚠️ Global Bundle Size Increased

Page Size (compressed)
global 100.35 KB (🟢 15.15 KB)
Details

The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!

New Pages Added

The following pages were added to the bundle from the code in this PR:

Page Size (compressed) First Load
/global-error 530 B 100.86 KB
/error 576 B 100.91 KB
/loading 143 B 100.49 KB
/api/health/route 143 B 100.49 KB
/feed.xml/route 143 B 100.49 KB
/robots.txt/route 143 B 100.49 KB
/sitemap.xml/route 143 B 100.49 KB
/blog/entry/[slug]/opengraph-image/route 143 B 100.49 KB
/opengraph-image/route 143 B 100.49 KB
/now/page 4.11 KB 104.46 KB
/uses/page 4.11 KB 104.46 KB

Ten Pages Changed Size

The following pages changed size from the code in this PR compared to its base branch:

Page Size (compressed) First Load
/_not-found/page 143 B (🟢 3 B) 100.49 KB
/not-found 3.47 KB (🟢 3.33 KB) 103.82 KB
/layout 27.2 KB (🟢 -60.44 KB) 127.55 KB
/contact/page 9.82 KB (🟢 -54.31 KB) 110.16 KB
/about/page 5.53 KB (🟢 325 B) 105.88 KB
/blog/page 8.72 KB (🟢 -63.37 KB) 109.07 KB
/blog/entry/[slug]/page 5.06 KB (🟢 -53.52 KB) 105.4 KB
/projects/page 25.22 KB (🟢 -55.86 KB) 125.57 KB
/projects/entry/[slug]/page 4.11 KB (🟢 -54.47 KB) 104.45 KB
/page 25.36 KB (🟢 -55.73 KB) 125.7 KB
Details

Only the gzipped size is provided here based on an expert tip.

First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

Next to the size is how much the size has increased or decreased compared with the base branch of this PR. If this percentage has increased by undefined% or more, there will be a red status indicator applied, indicating that special attention should be given to this.

@TomSeestern

Copy link
Copy Markdown
Owner Author

Not good enough.

@TomSeestern
TomSeestern deleted the roman-redesign branch July 24, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant