This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Lynko is a Hugo module (not a standalone theme) that adds a linktree-style /links page to any existing Hugo site. It can also run standalone. The module path is github.com/haydenk/lynko.
Requirements: Hugo v0.121.0+ (standard edition — no Extended needed) and Go 1.22+. Tool versions are pinned in .mise.toml.
All tasks are run via mise. Install mise first, then:
mise run dev # Start Hugo dev server at http://localhost:1313 (example site, with drafts)
mise run test # Build example site then run htmltest for link/HTML validation
mise run build # Build example site (minified) → exampleSite/public/
mise run build-drafts # Same, including draft content
mise run clean # Remove exampleSite/public/ and exampleSite/resources/
mise run deps # hugo mod tidy inside exampleSite/
# Release packaging (requires VERSION env var):
VERSION=0.1.0 mise run package # Creates lynko-0.1.0.tar.gz
VERSION=0.1.0 mise run zip # Creates lynko-0.1.0.zipThe CI pipeline (mise run test then mise run build-drafts) runs on push to master, develop, release/**, and hotfix/**.
The module ships a single named layout:
layouts/lynko.html→ calls{{ partial "lynko/page.html" . }}
This layout is opt-in only — it never activates automatically, so it cannot override an existing theme's section layouts. Pages must declare layout: lynko in their front matter:
- Module mode (
/linkssection): setlayout: lynkoincontent/links/_index.md - Standalone mode (homepage): set
layout: lynkoincontent/_index.md
layouts/partials/lynko/page.html renders a complete <html> document — it does not use a baseof.html. This is intentional: the links page must look distinct regardless of the parent theme (no inherited nav, sidebar, or fonts).
All user-facing config lives under [params.lynko] in hugo.toml. The partial reads from .Site.Params.lynko. Key params: title, handle, bio, avatar, primaryColor, showPoweredBy, metaTitle, metaDesc, plus [[params.lynko.links]] and [[params.lynko.social]] arrays.
primaryColor is injected as an inline <style>:root { --lynko-primary: … }</style> tag after the linked stylesheet — overriding the CSS variable without touching the file.
Single file: assets/css/lynko.css. Loaded via resources.Get | resources.Minify | resources.Fingerprint. Uses CSS @layer for cascade control (layers: lynko.reset, lynko.tokens, lynko.layout, lynko.profile, lynko.links, lynko.social, lynko.footer, lynko.motion). All colours derive from --lynko-primary via color-mix(in srgb, …).
layouts/partials/lynko/icon.html contains 25+ inline SVG icons all using fill="currentColor". Called as {{ partial "lynko/icon.html" (dict "name" $icon) }}. The icon field in config selects the icon; unknown names fall back to the "link" icon.
- Stagger delay:
printf "%.2fs" (add 0.10 (mul $i 0.07))— Hugo coerces int/float automatically, somul $i 0.07works without casting. - Initials:
range first 2 (split $title " ")— pipe order matters;(split …) | first 2does not work.
htmltest validates the built exampleSite/public/ directory. Config in .htmltest.yml: internal links checked, external links skipped (for CI speed), mailto: and tel: URLs ignored.
exampleSite/ is a complete Hugo site that imports the module via a replace directive pointing to ../. It exists for development and CI validation. Its go.mod pins the module locally; exampleSite/hugo.toml mirrors what a real adopter would configure.
Releases are triggered by pushing a semver tag (v*.*.*). The release.yaml workflow packages assets/, layouts/, go.mod, LICENSE, and README.md into both .tar.gz and .zip archives.