Component & Styling Structure Plan What's wrong today Three problems, in order of severity: Tokens are duplicated — --parchment, --ink, --red, etc. are defined twice, once on .page in homepage.module.css and once in article.module.css. Any colour change requires two edits. The masthead JSX block is copy-pasted across 5 pages — page.tsx, about/page.tsx, issues/page.tsx, issues/[number]/page.tsx, [slug]/page.tsx. Same HTML, different active nav link each time. Utility functions are duplicated — formatDate, firstTag, and padCount are defined in 3–4 files each. formatDate has inconsistent signatures (Date vs. Date | null | undefined). Secondary: the archive page (issues/page.tsx) uses raw style={{...}} objects instead of CSS Module classes. The plan Move design tokens to :root in globals.css (single source of truth) Remove them from both module files. Both Tailwind and CSS Modules can still access them via var(--ink) etc. Admin pages can also pick them up if ever needed. Route group src/app/(public)/ with a shared layout The parentheses mean the URL is unchanged. The layout provides the page shell — parchment background, .sheet max-width wrapper, and the token definitions if we want them layout-scoped. All public pages move inside the group; admin stays out. This eliminates the wrapper duplicated in every page. Extract component with two variants The homepage and issue-detail page use a cover masthead (58px logo, 52px title, subtitle line). Interior pages (article, about, archive) use a compact masthead (52px logo, 38px title, no subtitle). This is intentional design — the plan preserves it via variant="cover" | "compact" and activeNav props, rather than silently merging the sizes. Extract component with two variants Homepage/issue pages use the full colophon (logo + tagline + three link columns + meta). Article/about/archive use a minimal colophon (logo + one-liner meta). Same variant="full" | "compact" approach. Shared CSS module for extracted components src/components/Masthead.module.css and src/components/SiteFooter.module.css replace the duplicated .topbar, .masthead, .nav, .colophon blocks in both module files. The page-specific modules keep only what's genuinely page-specific. Utility functions → src/lib/format.ts formatDate(date: Date | null | undefined) (permissive signature wins), firstTag(tagsJson: string), padCount(n: number). Fix inline styles in the archive page Add the two missing classes to article.module.css and replace the style={{...}} objects. Two explicit decisions Admin styling — keep the split, formally. Admin is Tailwind + plain gray/blue. It's an internal tool, not the publication. Moving the newspaper tokens there would be noise. The plan keeps the two worlds separate and documents it: admin = Tailwind, public = CSS Modules + tokens. Unify on CSS Modules for the public side, Tailwind for admin. No attempt to consolidate to one system. They serve different purposes and mixing Tailwind utilities into the carefully art-directed public pages would add complexity for no gain. Files changed ┌────────┬─────────────────────────────────────────────────────────────────────────────────────────────┐ │ Action │ Files │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Edit │ src/app/globals.css — add :root tokens │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Move │ src/app/page.tsx, about/, issues/, [slug]/ → src/app/(public)/ │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ formatDate(date: Date | null | undefined) (permissive signature wins), firstTag(tagsJson: string), padCount(n: number). Fix inline styles in the archive page Add the two missing classes to article.module.css and replace the style={{...}} objects. Two explicit decisions Admin styling — keep the split, formally. Admin is Tailwind + plain gray/blue. It's an internal tool, not the publication. Moving the newspaper tokens there would be noise. The plan keeps the two worlds separate and documents it: admin = Tailwind, public = CSS Modules + tokens. Unify on CSS Modules for the public side, Tailwind for admin. No attempt to consolidate to one system. They serve different purposes and mixing Tailwind utilities into the carefully art-directed public pages would add complexity for no gain. Files changed ┌────────┬─────────────────────────────────────────────────────────────────────────────────────────────┐ │ Action │ Files │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Edit │ src/app/globals.css — add :root tokens │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Move │ src/app/page.tsx, about/, issues/, [slug]/ → src/app/(public)/ │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Create │ src/app/(public)/layout.tsx — page shell │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Create │ src/components/Masthead.tsx + Masthead.module.css │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Create │ src/components/SiteFooter.tsx + SiteFooter.module.css │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Create │ src/lib/format.ts │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Edit │ homepage.module.css, article.module.css — remove duplicated tokens + masthead/footer blocks │ ├────────┼─────────────────────────────────────────────────────────────────────────────────────────────┤ │ Edit │ src/app/issues/page.tsx — replace inline styles │ └────────┴─────────────────────────────────────────────────────────────────────────────────────────────┘ Want me to proceed with this, or would you like to redirect on anything (admin styling, the route group structure, or the masthead variant split)?