Today’s goal
As the Resources list grows, every entry should carry the same information: a title, an address, a short explanation, and a few topics.
- Store the repeated details in JSON
- Let a Hugo partial display them
- Keep the introduction and notebook links in Markdown
Add a resource by editing data; the template supplies the HTML.
By the end of today you can
- Read and edit a small JSON array of consistent records
- Connect a local JSON file to a Hugo template, and inspect the output
- Distinguish a parsing error from wrong or missing information
- Choose a format for writing, configuration, records, or spreadsheets
Start from Chapter 11 with a clean tree (companion branch chapter-11). No database, package, or data service.
Two resources as JSON
Create assets/data/resource_links.json, an array of two records:
[
{
"title": "Hugo documentation",
"url": "https://gohugo.io/documentation/",
"description": "The official reference for Hugo configuration, content, and templates.",
"topics": ["Hugo", "Reference"],
"start_here": true
},The second, for page bundles, follows; the chapter gives the complete file.
Arrays, objects, and one flag
[ ]encloses an array: an ordered list{ }encloses an object: the named values of one resource recordstart_hereis our editorial flag, not a rating from Hugo- Plain UTF-8 text ending in
.json: no code fences, no front matter
assets/ holds sources Hugo processes during the build; static/ files are copied as they are.
The directory partial, part 2
<li>
<a href="{{ .url }}">{{ .title }}</a>
{{ if .start_here }}<strong>Start here</strong>{{ end }}
<p>{{ .description }}</p>
{{ with .topics }}
<p><strong>Topics:</strong> {{ delimit . ", " }}</p>
{{ end }}
</li>An empty array shows an else message; a missing file stops the build with errorf.
Remove the old list, keep the rest
Build and preview: the generated list appears below the old manual one. Compare them first.
In content/resources/index.md, delete only the old ## Website publishing heading and its two bullets. Keep:
- The front matter and opening paragraph
- How to use these resources, from Chapter 8
- Examples from this notebook, with its internal links
Check #website-publishing still reaches the right section.
JSON syntax
"title": "Hugo documentation",
"topics": ["Hugo", "Reference"],
"description": "An explanation of Hugo's \"page bundles\" feature."- Quoted key, colon, value; double quotes only
- Commas between members and between records, never after the last
- Indentation is for reading: braces, brackets, commas, and colons carry the structure
- Escape a quote inside a string as
\"; no comments allowed
From file to HTML
resources.Get "data/resource_links.json"looks insideassets/transform.Unmarshalparses the file into values the template can userangevisits each record.titleand.urlare keys in the data, not page methods like.Titledelimit . ", "joins the topics intoHugo, Reference
It all happens at build time: visitors receive HTML, not the JSON file.
Three sources, three roles
| Source | What you edit there |
|---|---|
content/resources/index.md | Introduction, writing, notebook links |
assets/data/resource_links.json | The repeated resource records |
layouts/_partials/resource-directory.html | How each record looks |
Change a description in JSON: no template edit needed.
Pushed to a public repository, the JSON source is still visible.
Add a resource with data alone
After the second record’s }, add a comma and a third record, inside the array:
{
"title": "Hugo template introduction",
"url": "https://gohugo.io/templates/introduction/",
"description": "An introduction to template expressions, functions, and context in Hugo.",
"topics": ["Hugo", "Templates"],
"start_here": false
}Open the link and check the description matches it.
Choose the order yourself
Move the template-introduction record before the page-bundles record, keeping the general documentation first.
- Move the whole object; check the commas on both sides
- Build and preview: a new order, no template edit
urlholds complete external addresses: never add the repository path
You added and reordered records through JSON alone.
Break the syntax on purpose
Remove the comma after the first record’s title:
"title": "Hugo documentation"
"url": "https://gohugo.io/documentation/",hugo --minify --panicOnWarning fails while parsing. The reported position may be later than the missing comma.
Restore the comma. Never change a working template to compensate for broken data.
Three separate questions
- Can Hugo parse the JSON and render the template?
- Do the records follow our field names and types?
- Are the descriptions accurate and the destinations useful?
The build catches the first. It does not enforce the model, check remote links, or judge the truth. A misspelled key leaves a blank; a wrong URL still renders as a link.
CSV needs decisions
title,url,description
Hugo documentation,https://gohugo.io/documentation/,"Configuration, content, and templates."- Quotes keep a comma inside a cell from splitting it
- The rows have no
topicsorstart_here: those need decisions, not invention - Compare row and record counts; check first and last records
- Renaming
.csvto.jsondoes not convert it
Keep the directory manageable
- Use data for repeated shapes; keep explanations and narratives in Markdown
- Before adding a field, ask who uses it
- Update
AGENTS.mdwith the three new file locations, and this agreement:
- Resource records use title, url, description, topics (an array
of strings), and start_here (a Boolean). Preserve these types and
do not invent descriptions or destinations.Save the checkpoint
git add assets/data/resource_links.json layouts/resources/page.html
git add layouts/_partials/resource-directory.html
git add content/resources/index.md AGENTS.md
git diff --cached
git commit -m "Build the Resources directory from local JSON records"Five files. Only the old Website publishing section left the Markdown; check Projects still has its own layout.
When something goes wrong
| What you see | What to check |
|---|---|
| The missing-data message | The path; the lookup omits assets/ |
| A JSON parsing error | Commas, double quotes, brackets, comments |
| An entry has blank text | Its keys against the model |
Start here on "false" | Use the Boolean false |
| No generated directory | layouts/resources/page.html and its call |
Completion check
- I can tell an object, an array, a string, and a Boolean apart
- All records follow the five-field agreement, accurately
- I know which file holds records, writing, and presentation
- I added and reordered a resource without a template edit
- I repaired the missing comma and checked more than the build
- I know why CSV conversion needs decisions
- Resources keeps its Markdown sections and links
- I committed the five intended files