Julian Wiley

Content Authoring Guide

How to create blog posts, documentation pages, and notes with proper frontmatter and formatting.

This guide covers how to author content for the Hugo/Toha portfolio site. You will learn the directory structure, frontmatter schemas, and formatting options for blog posts, documentation pages, and notes.


1. Blog Posts

Blog posts live under content/posts/. Each post uses its own folder with an index.md file.

Directory Structure

Create a folder per post. The folder name becomes the URL slug:

content/posts/
├── my-first-post/
│   ├── index.md
│   └── images/
│       └── hero.jpg
├── machine-learning-basics/
│   ├── index.md
│   └── hero.png
└── _index.md

Example: content/posts/my-first-post/index.md renders at /posts/my-first-post/.

Full Frontmatter Schema

Use this frontmatter for blog posts:

---
title: "Post Title"
date: 2026-01-15T10:00:00+00:00
description: "Brief description for SEO"
tags: ["machine-learning", "python"]
categories: ["Technical"]
hero: images/hero.jpg
menu:
  sidebar:
    name: My Post
    identifier: my-post
    weight: 10
    parent: category-name
---
FieldRequiredDescription
titleYesDisplay title of the post
dateYesPublication date (RFC 3339 format)
descriptionRecommendedUsed for SEO and meta description
tagsOptionalArray of tags; generates /tags/tag-name/ pages
categoriesOptionalArray of categories; generates /categories/category-name/ pages
heroOptionalPath to hero image, relative to the post folder
menu.sidebarOptionalControls appearance in the blog sidebar

Hero Images

Place hero images in the post folder or in an images/ subdirectory. Reference them in frontmatter:

# Image in post folder root
hero: hero.jpg

# Image in images/ subdirectory
hero: images/hero.jpg

The hero image appears at the top of the post and is used for OpenGraph when sharing on social media. Supported formats include JPG, PNG, and WebP.

Tags and Categories

Tags and categories appear on the post and generate taxonomy list pages:

tags: ["machine-learning", "python", "tutorial"]
categories: ["Technical", "Data Science"]
  • Tags: /tags/machine-learning/, /tags/python/, etc.
  • Categories: /categories/Technical/, etc.

Use lowercase, hyphenated values for consistency. Tags are typically more specific; categories are broader groupings.

The menu.sidebar block controls how the post appears in the blog sidebar:

menu:
  sidebar:
    name: My Post          # Label in sidebar (can differ from title)
    identifier: my-post    # Unique ID for this menu item
    weight: 10             # Lower = higher in list
    parent: category-name  # Optional: nest under another menu item
  • weight: Lower numbers appear first. Use increments of 10 (10, 20, 30) to allow insertion between items.
  • parent: Use the identifier of another sidebar item to create nested menus.

2. Documentation Pages

Documentation lives under content/docs/. Use _index.md for section metadata and index.md for leaf pages.

Directory Structure

content/docs/
├── _index.md
├── getting-started/
│   ├── _index.md
│   └── index.md
├── guides/
│   ├── _index.md
│   ├── content-authoring/
│   │   └── index.md
│   └── custom-components/
│       └── index.md
└── tutorials/
    └── _index.md
  • _index.md: Defines a section (title, description, weight). Can include intro content.
  • index.md: A page within that section. The folder name is the URL slug.

Frontmatter

Documentation pages use simpler frontmatter:

---
title: "Content Authoring Guide"
description: "How to create blog posts, documentation pages, and notes."
weight: 2
---
FieldRequiredDescription
titleYesPage title
descriptionRecommendedMeta description and lead text
weightOptionalOrder within parent section; lower = first

Section _index.md files use the same fields. The weight controls ordering in the docs sidebar.

Custom Docs Layout Features

The docs layout provides:

  • Breadcrumbs: Home / Docs / Section / Page
  • Sidebar TOC: Table of contents built from ## and ### headings (when TOC is enabled)
  • Prev/Next navigation: Links to sibling pages in the same section

Breadcrumbs and prev/next are automatic. The sidebar tree is built from the docs section hierarchy.

Nested Sections

Create nested sections by adding subfolders:

content/docs/guides/
├── _index.md
├── content-authoring/
│   └── index.md
├── custom-components/
│   └── index.md
└── configuration/
    └── index.md

Each _index.md defines its section. Leaf pages use index.md in their folder.


3. Notes

Notes are organized as a hierarchical knowledge base under content/notes/. Structure is similar to docs but oriented toward reference material.

Directory Structure

content/notes/
├── _index.md
├── go/
│   ├── _index.md
│   ├── basic/
│   │   ├── _index.md
│   │   ├── introduction/
│   │   │   └── index.md
│   │   ├── types/
│   │   │   └── index.md
│   │   └── flow-control/
│   │       └── index.md
│   └── advanced/
│       ├── _index.md
│       └── files/
│           └── index.md
└── bash/
    ├── _index.md
    └── basic/
        └── index.md

_index.md at Each Level

Each directory should have an _index.md that defines the section:

---
title: Go Notes
menu:
  notes:
    name: Go
    identifier: notes-go
    weight: 10
---

For leaf pages:

---
title: Introduction
weight: 10
menu:
  notes:
    name: Introduction
    identifier: notes-go-basics-intro
    parent: notes-go-basics
    weight: 10
---

The menu.notes block controls the notes sidebar. Use parent to nest items under a section.


4. Writing Content

Standard Markdown

Hugo uses Goldmark for Markdown. You can use:

  • Headings (#, ##, ###)
  • Bold, italic, code
  • Lists (ordered and unordered)
  • Blockquotes (>)
  • Tables
  • Links and images

Hugo Shortcodes

Shortcodes extend Markdown with custom components. See the Custom Components Reference for full details. Common examples:

Alert:



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* alert type="info" */>}}`


This is an informational alert.


> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* /alert */>}}`


Image (theme):



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* img src="/posts/shortcodes/boat.jpg" title="A boat at the sea" */>}}`


Responsive image (rimg):



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* rimg src="images/photo.jpg" alt="Description" */>}}`


The rimg shortcode generates responsive srcset with multiple sizes (500w, 800w, 1200w, 1500w) for better performance. Place images in assets/ or reference them from the page bundle.

Split columns:



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* split 6 6 */>}}`


Left column content.
---
Right column content.


> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* /split */>}}`


Code Blocks

Use fenced code blocks with a language identifier for syntax highlighting (highlight.js):

```python
def greet(name):
    return f"Hello, {name}!"
```
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Hugo's built-in highlight shortcode is also available:



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* highlight python */>}}`


def greet(name):
    return f"Hello, {name}!"


> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* /highlight */>}}`


Math with KaTeX

Enable math per page with math: true in frontmatter. Then use:

  • Inline math: $...$ or \(...\)
  • Display math: $$...$$ or \[...\]

Example:

Inline: $\varphi = \dfrac{1+\sqrt{5}}{2}$

Display:
$$
\varphi = 1 + \frac{1}{1 + \frac{1}{1 + \frac{1}{1 + \cdots}}}
$$

Mermaid Diagrams

Enable Mermaid per page with mermaid: true in frontmatter. Then use the shortcode:



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* mermaid */>}}`


graph LR;
    A[Start] --> B[Process]
    B --> C[End]


> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* /mermaid */>}}`


Supports flowcharts, sequence diagrams, Gantt charts, class diagrams, and more.

Images

Standard Markdown:

![Alt text](images/photo.jpg)

Theme img shortcode (for images in static/ or post bundles):



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* img src="/posts/my-post/hero.jpg" height="400" width="600" title="Caption" */>}}`


Responsive rimg shortcode (for images in assets/):



> WARNING: Unported Hugo shortcode (manual conversion needed): `{{</* rimg src="images/photo.jpg" alt="Description" */>}}`



5. SEO Best Practices

  1. Always set title and description in frontmatter. The description is used for meta tags and search snippets.

  2. Use descriptive titles that reflect the content. Avoid generic titles like "Post 1".

  3. Tag posts appropriately. Tags help with discoverability and taxonomy pages.

  4. Add hero images for blog posts. They improve OpenGraph previews when sharing on social platforms.

  5. Use meaningful URLs. Folder names become URL slugs; choose readable, hyphenated names.

  6. Link internally to related posts and docs to improve navigation and SEO.


6. Creating a New Post Checklist

Follow these steps to add a new blog post:

Step 1: Create the folder

mkdir content/posts/my-new-post

Step 2: Create index.md with frontmatter

# Create content/posts/my-new-post/index.md
---
title: "My New Post"
date: 2026-02-14T10:00:00+00:00
description: "A brief description for SEO and social sharing."
tags: ["tag1", "tag2"]
categories: ["Category"]
hero: images/hero.jpg
menu:
  sidebar:
    name: My New Post
    identifier: my-new-post
    weight: 20
---

Step 3: Add hero image (optional)

Place hero.jpg in content/posts/my-new-post/images/ or directly in the post folder. Update the hero path if needed.

Step 4: Write content

Add your Markdown content below the frontmatter. Use headings, code blocks, shortcodes, and images as needed.

Step 5: Preview locally

hugo server

Visit http://localhost:1313/posts/my-new-post/ to preview. Use hugo server -D to include drafts.

Step 6: Build and deploy

hugo --minify

Commit and push. The GitHub Actions workflow will build and deploy to GitHub Pages.


Next Steps