Hugo Artifacts

A public, MIT-licensed monorepo of reusable Hugo modules — style-agnostic content shortcodes alongside site-scale modules for the SEO head, client-side search, responsive images, an accessible carousel, social sharing, the machine-readable layer an AI agent reads, and the Progressive Web App shell — each independently versioned with its own go.mod. Every artifact ships semantic BEM markup, data attributes, and zero CSS, so it drops into any number of unrelated sites and is styled entirely by the consumer.

Details & related links

Overview

Hugo Artifacts is a public, MIT-licensed monorepo of reusable Hugo modules — independently versioned components that drop into any Hugo site. The full source is on GitHub, and every artifact lives in its own subdirectory with an independent go.mod, so a site can import exactly the one piece it needs and pin it on its own release cadence.

The collection spans both ends of a site. At one end are content components an author reaches for inside a page — a repository card, a paper reference, an admonition, a carousel. At the other are site-scale modules that own whole surfaces: the SEO head, site search, the image pipeline, the sharing bar, the Progressive Web App shell, and the machine-readable layer an AI agent reads instead of the page. Between them they cover most of the reusable half of a website.

All of it is built around a single, deliberate principle: an artifact ships structure, data, and behavior — never design decisions. Everything that renders on the page emits semantic BEM markup and exposes its objective values as data-* attributes, and not one artifact in the collection ships a line of CSS — no stylesheet, no hardcoded colors, no dark-mode rule. The consuming site owns all visual presentation. That is what lets one component live on many unrelated sites and look at home on every one of them.

The Problem

Across the sites I build, I kept rewriting the same handful of components — a GitHub repository card, a privacy-respecting video embed, an admonition box — and each rewrite was a small compromise. The reusable Hugo modules I could find on the shelf were the opposite of reusable in the way that mattered: they shipped their own opinionated CSS, their own colors, sometimes their own baked-in dark-mode rule. Dropping one into a site with its own design system meant fighting it — overriding styles, untangling specificity wars, or forking the module outright just to restyle it. A component that imposes a look is not really reusable; it is a theme fragment wearing a module's clothes.

The larger pieces asked for worse trade-offs still. Adding a search box meant either handing every visitor's query to a third-party service or bolting a post-build indexer onto the toolchain. Adding a share bar meant embedding vendor widgets that contact their origin before anyone clicks anything — the exact pre-click transmission that turned embedded social buttons into a consent liability in the first place. Adding responsive images meant hand-rolling srcsets in every template or accepting somebody else's markup and their stylesheet along with it. Each of those is a decision a static site should not have to make.

What I actually wanted, at either scale, was an artifact that crosses the styling boundary with data, not styles — that hands my site the facts (this is a danger callout, this video is id=abc, this repo has this many stars) and the semantic hooks to render them, and then gets out of the way so my own tokens and dark-mode rules flow straight through, without ever reaching for a stranger's server on the reader's behalf.

The Solution

Hugo Artifacts is that idea, applied consistently across a family of independently versioned modules. Two kinds of artifact are importable, and each carries its own README.md, installation path, and parameter surface.

Shortcodes — style-agnostic content components an author places inside a page:

  • github-repo renders a GitHub repository reference in one of five display variants — inline, card, stats, lang, and hero — with live API-driven metadata, header-aware retries, and graceful degradation to a compact chip when the API is unreachable or rate-limited.
  • github-profile assembles the activity evidence GitHub itself never presents in one place: all-time contribution totals, per-organization rollups, the split between work on an account's own repositories and work on other people's, code review as a first-class number, and a language breakdown that names the repository set it counted — the account's own repositories by default, optionally widened to every repository the person has actually written code in — and relabels its own heading to match. It works that way because GitHub reports language bytes per repository and never per contributor, so the only claim the widget can truthfully make is which repositories went into the total. All of it comes from one GraphQL request by default, offered as anything from a one-line metric strip to a full dossier, and the composite activity score is off unless asked for and shows its own arithmetic when switched on, because a number nobody can recompute is a vanity metric, not evidence.
  • hf-space does the same for a Hugging Face Space, with five variants of its own and live Hub metadata (emoji, SDK, hardware, likes, running status, gradient colors). It is the sibling of github-repo and follows the identical contract.
  • arxiv-paper extends that data-provider family to academic references, rendering an arXiv paper in one of six variants — inline, card, wide, stats, hero, and cite — from the arXiv Atom API, with optional Semantic Scholar and Hugging Face Papers enrichment layered on top and the same header-aware retries and graceful degradation. The subject is objective data it never colors: it ships the archive code as a data-* hook and lets the consuming site map it to a hue.
  • youtube-embed is a privacy-first YouTube facade: it renders only a same-origin, build-time-fetched poster plus a real play button, and injects the youtube-nocookie.com player only on click, so the page makes zero third-party contact before the visitor opts in.
  • callout is a universal admonition box — fifteen first-class types, true-synonym aliases, arbitrary custom types, native <details> collapsibility, opt-in ARIA, and overridable icons. It also ships a blockquote render hook, so GitHub-style > [!NOTE] alerts render as the same markup without touching an ordinary blockquote.

Modules — consumer-facing capabilities that own an entire site surface, where the same principle reappears at a larger scale:

  • seo owns a site's entire SEO head from a single {{ partial "seo/head.html" . }} call — title, meta description, canonical, robots, hreflang, Open Graph, Twitter Cards, and every applicable Google-eligible JSON-LD entity (WebSite, Organization or Person, WebPage, BreadcrumbList, Article, Product, ProfilePage, and more), each self-gating against Google's placement rules and cross-linked into one @id entity graph. It ships zero CSS for the most literal reason of all: SEO metadata is invisible head content, so there is nothing to style. The same complete static markup is also what AI crawlers read, which makes a rigorous structured-data surface pay twice.
  • search is site search that never leaves the visitor's browser. Hugo emits a per-language index at build time, and a vendored search engine queries it client-side — no external service, no post-build indexer, no telemetry, and nothing for the consuming site to install from npm. English and Russian stemming, typo tolerance, and field-weighted ranking come standard, across three surfaces built on one core, including a results page that is a real GET form and works with JavaScript switched off.
  • images puts one processing pipeline behind three authoring surfaces — a partial, a pair of shortcodes, and a site-wide render hook that upgrades every plain ![alt](src) — so identical inputs emit identical markup no matter how the image was written. Width-descriptor srcsets that never upscale, modern formats with fallbacks, intrinsic dimensions on every image for zero layout shift, alt text required rather than suggested, and light/dark variant pairs — all of it with zero CSS and zero JavaScript, down to a lightbox that is a plain anchor carrying the dimensions any lightbox library needs.
  • carousel is an accessible image carousel that is a plain stack of visible, labeled slides before any JavaScript runs, and follows the W3C authoring practices' grouped, buttons-only carousel pattern once it does. It ships no autoplay at all — not even as an option — because a slideshow that moves on its own is the thing the accessibility guidance asks you not to build. Import it alongside images and it notices at build time, with no dependency declared between them, so every slide comes through the responsive pipeline — srcsets, modern formats, light/dark pairs, the lightbox — with nothing extra to author.
  • social-share builds a sharing bar out of plain intent links across more than two dozen networks, so the page makes no third-party contact until a visitor deliberately clicks. The whole bar works with JavaScript off; scripting only adds what genuinely needs it — the native share sheet, copy link, print — plus a tracker-free browser event a site can wire to its own analytics if it wants numbers.
  • agent-readiness generates a site's entire machine-readable representation from one page walk: a robots.txt that answers crawler tokens and states a content signal, a Markdown twin of every page, a compact link index beside a complete one, an aggregated facts document, and a discovery index for the agent skills a site republishes. The single walk is the design: surfaces derived independently drift, and two of them disagreeing is worse for the agent reading them than either being absent.
  • copy-page puts a "use this page with an agent" control in the page's own chrome — one button that copies the page's Markdown twin to the clipboard, and a short menu that hands the page, the twin, or the site index to an assistant. Every row is an ordinary link carrying a prompt, so nothing reaches an AI vendor until the reader picks one.
  • pwa is the production-grade Progressive Web App shell: a templated web app manifest, a modern RealFaviconGenerator icon set, a TypeScript service worker compiled at build time and powered by Workbox, an install prompt, and push-subscription wiring. It composes from two vendor-mount companions (workbox and idb) that expose their upstream JavaScript sources as Hugo assets for js.Build — a clean resolution recipe that needs no upstream replacement or vendoring.

That founding principle turns out to be one of three commitments running through the collection, each a promise to a different party. Ship no design decisions is the promise to the developer, and it is why an artifact crosses the boundary with a data-* attribute or a custom-property name rather than a color. Make no request the visitor did not ask for is the promise to the reader: the video facade, the share bar, and the search index all hold to it, and none of them needs a consent banner to do so. Never break the consumer's build is the promise to the site owner — every misconfiguration degrades to one deduplicated warning and a safe fallback, and every live API call is wrapped in classified, header-aware retries that end in a compact fallback rather than a failed build. That last promise is exercised rather than trusted: one fixture site points a fetch at an address the DNS standard guarantees can never resolve, so the degradation path runs on every test run instead of on the day someone's API key expires. A broken schema declaration costs you one rich result, never the site.

The one visual thing every artifact does ship — its icons — renders as inline SVG using currentColor and 1em sizing, so even the icons inherit the consumer's text color and font size and stay fully restyleable. The payoff is that you can build a design of any complexity on top of these artifacts without fighting styles they impose, because they impose none.

GITHUB / REPOSITORY

alex-feel / hugo-artifacts

Reusable, style-agnostic Hugo modules — shortcodes, asset & utility modules that ship semantic BEM markup and zero CSS, so they drop into any number of sites and you style them to fit.

#bem #go-modules #gohugo #hugo #hugo-modules #hugo-shortcodes #reusable-components #static-site-generator #style-agnostic #unstyled
HTML 1 star MIT updated 3 days ago View on GitHub

Why a Monorepo of Independent Modules

Hugo's module system resolves each go.mod independently, which let me make a deliberate structural choice: one repository, many modules, each independently importable and versionable. A site that only wants the callout shortcode imports github.com/alex-feel/hugo-artifacts/shortcodes/callout and nothing else; it never pulls the PWA module or its Workbox dependency. That keeps each consumer's dependency graph minimal while letting the whole family share one set of conventions, one validation pipeline, and one place to evolve the style-agnostic contract.

Sharing a pipeline is only worth something if the pipeline actually holds the line. Every change parses each leaf go.mod, resolves each standalone module's dependency graph, and runs the lint, format, and file-conformance gates over the repository's JavaScript, Markdown, and YAML. Behavior is covered by fixture-site test suites — each one builds its own minimal Hugo site and then asserts against the result — around a dozen of them, running hundreds of cases between them: browser-driven where there is something to interact with, such as the service worker's update flow, the search palette, and the share bar's progressive enhancement, and build-output assertions where a module deliberately ships no JavaScript at all and there is nothing in the browser to drive. The run scripts fail on a single deprecation line in the Hugo build log, which is how a family of modules that promises to work with current Hugo keeps that promise instead of discovering the breakage in someone else's site.

This very website is the proving ground. Every consumer-facing artifact in the monorepo runs here, straight from the public repository — the repository and Hugging Face Space cards on my project pages, the profile widget across my home, contact, and skill pages, the arXiv card and the video facade in my writing, the carousel on an article and a project page, the callout admonitions throughout, the entire SEO head and structured-data graph, the image pipeline behind every picture I publish, the search page and its command palette, the share bar under each article, the whole agent-readable layer this site publishes beside its pages, the copy-page control in every page header, and the PWA shell (the manifest, icons, and Workbox service worker; this site deliberately leaves the module's offline page and install prompt switched off) — every one styled solely by this site's own design tokens. Dogfooding the modules on a real, design-heavy site is what puts the universality promise to the test: if an artifact ever leaked a style, I would feel it here first.

My Role

I designed, built, and maintain Hugo Artifacts end-to-end as a solo open-source project: the monorepo structure and per-module go.mod layout, the style-agnostic output contract, and the BEM markup and data-* attribute design behind every artifact. Artifact by artifact, that means the live-API integrations with their classified retries and graceful degradation (the GitHub REST and GraphQL APIs, the Hugging Face Hub, and the arXiv Atom API with its optional Semantic Scholar and Hugging Face Papers enrichment), the privacy-first video facade, the universal callout type system and its blockquote render hook, the SEO module that owns the head surface and the cross-linked, Google-eligible JSON-LD entity graph, the client-side search engine with its build-time index and bilingual stemming, the image pipeline and its three authoring surfaces, the share bar, the carousel and its build-time composition with that pipeline, the agent-readiness module that derives a site's whole machine-readable representation from a single page walk with the copy-page control that hands any of it to an assistant, and the PWA module with its Workbox service worker and the vendor-mount resolution recipe for its non-Go upstreams — along with the documentation, the CI validation pipeline, and the release conventions for the whole family. It lives on my personal GitHub under an MIT license, and I accept issues and contributions from the wider Hugo community.

Accessibility and internationalization are part of the contract rather than a pass at the end. Interactive artifacts follow the published ARIA authoring patterns where one applies and lean on platform behavior — a native dialog for focus containment, a real form for search — instead of reimplementing it in JavaScript that will be subtly wrong. The search surfaces name every control with real visible text rather than a label only a screen reader can reach, result counts are announced with the correct plural form for the language they are announced in, and the search UI, the share bar, the app shell, the video facade, and the GitHub and Hugging Face cards all ship English and Russian catalogs with English as the fallback on every lookup.

The PWA module goes one step past the Hugo boundary for the same reason. Push notifications are useless without a server that signs and encrypts them, so the module ships with deployable reference backends — Cloudflare Workers, Express, and Firebase Functions — each implementing the same VAPID and payload-encryption contract against the published RFCs. A client-side module that stops at the edge of the feature it advertises is only half a feature.

It grows directly out of the same open-source instinct behind my st-copy component and my Terraform Cloudflare Zone Module: build the missing primitive once, build it to be genuinely reusable, and give it back to the community rather than rewriting it in every project. If a style-agnostic Hugo component sounds useful for your own site — or if you simply want to talk through the design — the contact page is the best way to reach me.

Related Posts

Agent Experience: Preparing Your Site for Its Second Reader

Agent Experience: Preparing Your Site for Its Second Reader

Every page on your site is two documents: the one a browser renders for people and the one a parser reads. AI agents read the second one. Here is what I learned making this site legible to them -- and what a machine reader finds on the personal sites of eight of the best-known people in AI, from a hidden Order of the Unicorn to a robots.txt that redirects into itself forever.