Hugo template development for InfluxData docs-v2, enforcing build and runtime testing to catch template errors that build-only validation misses. Use when creating or editing Hugo layouts, partials, or shortcodes, debugging template errors, or accessing site data in templates.
Instalação
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Hugo template development for InfluxData docs-v2, enforcing build and runtime testing to catch template errors that build-only validation misses. Use when creating or editing Hugo layouts, partials, or shortcodes, debugging template errors, or accessing site data in templates.
Hugo Template Development Skill
Purpose
This skill enforces proper Hugo template development practices, including mandatory runtime testing to catch errors that static builds miss.
Critical Testing Requirement
Hugo's npx hugo --quiet only validates template syntax, not runtime execution.
Template errors like accessing undefined fields, nil values, or incorrect type assertions only appear when Hugo actually renders pages. You MUST test templates by running the server.
Mandatory Testing Protocol
For ANY Hugo Template Change
After modifying files in layouts/, layouts/partials/, or layouts/shortcodes/:
Step 1: Start Hugo server in the background and capture output
rm -f /tmp/hugo-1315.log
npx hugo server --port 1315 >/tmp/hugo-1315.log 2>&1 &
sleep 5
head -50 /tmp/hugo-1315.log
This keeps the server running for the next steps while still showing startup
output.
This catches runtime JavaScript errors that template changes may introduce.
Step 4: Stop the test server
pkill -f "hugo server --port 1315"
Quick Test Command
Use this one-liner to test and get immediate feedback:
rm -f /tmp/hugo-1315.log
npx hugo server --port 1315 >/tmp/hugo-1315.log 2>&1 &
sleep 5
grep -E "(error|Error|ERROR|fail|FAIL)" /tmp/hugo-1315.log | head -20
pkill -f "hugo server --port 1315" 2>/dev/null
If output is empty, no errors were detected.
Preparing template changes for PR review
The repo's preview workflow (.github/workflows/pr-preview.yml) deploys only
the pages listed in the PR description to a stable GitHub Pages preview URL —
a targeted hosted preview that replaces "check out my branch and run
npx hugo server" for reviewers.
When you change layouts/, assets/, or data/, list every page the
reviewer should verify in the PR body. The URL extractor
(.github/scripts/parse-pr-urls.js) matches:
Production URLs (https://docs.influxdata.com/<path>)
Localhost URLs (http://localhost:1313/<path>)
Bare paths with a known product namespace from data/products.yml
(/influxdb3/..., /telegraf/..., etc.)
URLs inside fenced code blocks are stripped before extraction — list them
as bare paths or markdown links, not inside backtick fences. Pair each URL
with an "Expected" column (DOM element, attribute value, copy) so the
reviewer knows what to verify rather than guessing.
For wider behavioral coverage (interactive UI, JS errors, navigation), prefer
the cypress-e2e-testing skill. The preview-pages mechanism is the right tool
for visual / structural verification — exactly the cases where Cypress is
overkill or doesn't cover what changed.
If your template change affects <link rel="alternate" type="text/markdown">,
the /sitemap-md.xml layout, the /llms.txt template, or any of the inputs
to scripts/lib/corpus-paths.js (notably data/products.yml), run after the
full build:
check:md-coherence runs two coherence checks: head-link → .md file
existence, and Hugo /llms.txt ↔ getCorpusPaths() agreement. Catches drift
between Hugo template logic and the JS derivation from products.yml.
See DOCS-TESTING.md "Autodiscovery coherence guard" for details.
Validating structured data (JSON-LD)
The layouts/partials/header/*-jsonld.html partials emit schema.org JSON-LD
(Organization, TechArticle, SoftwareApplication, FAQPage). When you add
or change one:
Use the Schema Markup Validator (https://validator.schema.org), NOT the
Google Rich Results Test.
The Rich Results Test only reports types eligible for a visual search
enhancement. Most JSON-LD this repo emits is not eligible, so the Rich
Results Test reports "no items detected" even for valid markup — a false
negative that looks like failure:
Emitted type
Rich Results Test
Why
Organization
Not reported
Feeds the knowledge graph / entity resolution, never a rich result
TechArticle
Not reported
Google's Article rich result fires only for Article/NewsArticle/BlogPosting
SoftwareApplication
Not reported
Google retired the general software-app rich result
FAQPage
Reported
One of the few eligible types here
validator.schema.org validates every schema.org type regardless of
rich-result eligibility — that's what confirms the node is well-formed.
Validation steps:
Structural (local, scriptable): parse the emitted block to prove it's
valid JSON and schema-shaped. The minifier emits type=application/ld+json
(unquoted) — match the attribute loosely:
python3 - <<'EOF'
import re, json
html = open('public/index.html', encoding='utf-8', errors='replace').read()
for b in re.findall(r'<script type=["\']?application/ld\+json["\']?>(.*?)</script>', html, re.S):
j = json.loads(b) # raises on malformed JSON
print('OK', j.get('@type'))
EOF
Schema (manual, reviewer): paste a deployed preview URL into
validator.schema.org; expect 0 errors. Note this in the PR description and
do not ask reviewers to use the Rich Results Test for non-FAQPage nodes.
Regression (Cypress): assertions depend on scope. Page-scoped nodes
(TechArticle/SoftwareApplication) — assert presence where they belong and
absence where they don't (over-emission guard). Global nodes
(Organization, emitted site-wide with a stable @id) — assert exactly
one per page class, which catches both omission and duplicates. See the
cypress-e2e-testing skill, "Testing structured data (JSON-LD)".
Common Hugo Template Errors
1. Accessing Keys with Hyphens or Dynamic Names
Hugo's dot notation only works for keys that are valid Go identifiers
(letters, digits, underscores). This repo's data dir is article_data
(underscore), so .Site.Data.article_data works. But a hyphenated key — or a
key held in a variable — must use index:
Wrong (hyphen breaks dot notation; dataKey is a variable):
{{ index .Site.Data "my-data""influxdb" }}
{{ index .Site.Data "article_data" $dataKey }}
2. Nil Field Access
Wrong:
{{ range $articles }}
{{ .path }} {{/* Fails if item is nil or wrong type */}}
{{ end }}
Correct:
{{ range $articles }}
{{ if . }}
{{ with index . "path" }}
{{ . }}
{{ end }}
{{ end }}
{{ end }}
3. Type Assertion on Interface{}
Wrong:
{{ range $data }}
{{ .fields.menuName }}
{{ end }}
Correct:
{{ range $data }}
{{ if isset . "fields" }}
{{ $fields := index . "fields" }}
{{ if isset $fields "menuName" }}
{{ index $fields "menuName" }}
{{ end }}
{{ end }}
{{ end }}
4. Empty Map vs Nil Check
Problem: Hugo's {{ if . }} passes for empty maps {}:
{{/* This doesn't catch empty maps */}}
{{ if $data }}
{{ .field }} {{/* Still fails if $data is {} */}}
{{ end }}
Solution: Check for specific keys:
{{ if and $data (isset $data "field") }}
{{ index $data "field" }}
{{ end }}
Hugo Data Access Patterns
Safe Nested Access
{{/* Build up access with nil checks at each level */}}
{{ $articleDataRoot := index .Site.Data "article_data" }}
{{ if $articleDataRoot }}
{{ $influxdbData := index $articleDataRoot "influxdb" }}
{{ if $influxdbData }}
{{ $productData := index $influxdbData $dataKey }}
{{ if $productData }}
{{ with $productData.articles }}
{{/* Safe to use . here */}}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
Iterating Over Data Safely
{{ range $idx, $item := $articles }}
{{/* Declare variables with defaults */}}
{{ $path := "" }}
{{ $name := "" }}
{{/* Safely extract values */}}
{{ if isset $item "path" }}
{{ $path = index $item "path" }}
{{ end }}
{{ if $path }}
{{/* Now safe to use $path */}}
{{ end }}
{{ end }}