Personal site built with Hugo and Tailwind CSS v4.
npm ci npm run serve
Hugo serves the site at http://localhost:1313 and rebuilds templates and Tailwind styles as files change. Restart the server after changing the build configuration or installing dependencies.
npm run build
Deploy dist/. Hugo compiles and minifies Tailwind and fingerprints the resulting stylesheet. No separate CSS watcher or Tailwind CDN is needed.
Run npm run check before deployment. It builds the site and checks metadata, local links/assets, image attributes, RSS, and redirect mappings. Run npm run check:a11y for browser accessibility checks, or npm run check:all for both. See ACCESSIBILITY.md for browser setup, coverage, and the manual assistive-technology checklist.
assets/css/site.cssimports Tailwind and its Typography plugin and defines the site tokens with@theme.- Add utility classes directly in
layouts/. Thedesktop:breakpoint begins at 781px to match the original design. layouts/partials/css.htmlruns Hugo's nativecss.TailwindCSSpipeline. The deferred call in the base template waits for rendered class statistics before compiling styles.hugo_stats.jsonis generated by Hugo and ignored by Git. Explicit@sourcedirectives also scan templates and client scripts.- State Shift uses
group-data-*variants; filters usearia-pressed:*variants. JavaScript selects elements through data attributes, independently of styling. - Blog content uses Tailwind Typography (
prose) with utility overrides in the article layout. - Fonts are self-hosted in
static/fonts/and declared inassets/css/fonts.css. The image render hook optimizes archived blog images without changing their original URLs or Markdown. - Sharing cards and structured data are generated in
layouts/partials/social-image.htmlandseo.html. Case studies can setseoTitleindependently of their visible heading. - Dark mode follows the system preference automatically, including live changes. Adaptive color tokens are overridden inside
@media (prefers-color-scheme: dark)inassets/css/site.css; usetext-accentfor adaptive purple text andbg-nightfor permanently dark surfaces. Artwork keeps its fixed palette, and archived articles usedark:prose-invert.
Use complete class names in templates or JavaScript so Tailwind can detect them. Keep reusable markup in Hugo partials.
The archive lives in content/blog/. Preserve dates and slugs when editing historical posts. Static blog originals and redirects live in static/; case-study images live in assets/images/.
- The InVision case study lives at
/work/invision/, with its copy and image captions incontent/work/invision/index.mdand its layout inlayouts/work/single.html. - The Cape case study lives at
/work/cape/, with copy incontent/work/cape/index.mdand its layout inlayouts/work/cape.html. Both pages uselayouts/partials/case-study-header.htmlfor their headline and project facts. - Case-study screenshots live in
assets/images/invision/,assets/images/cape/, andassets/images/warranties/. layouts/partials/case-study-image.htmlgenerates responsive WebP images and links to the full-size originals.layouts/rss.xmlkeeps the RSS feed limited to historical blog posts while case studies remain discoverable in the sitemap.