|
| 1 | +# Adding New Pages or New Sections |
| 2 | + |
| 3 | +Hugo derives the URL from the content path under the language `contentDir`, and the template from section/kind/`layout`. Content goes under `content/english/` (root, project-setup). |
| 4 | + |
| 5 | +There are three distinct things you'll be asked for — pick the matching recipe: |
| 6 | + |
| 7 | +| Asking for... | It means... | Recipe | |
| 8 | +| --------------------------------------------------------------- | --------------------------------------------------------------------- | -------- | |
| 9 | +| "Add a page like About" (custom layout, image, hero, etc.) | Content + a **dedicated template** selected via `layout:` frontmatter | Recipe 1 | |
| 10 | +| "Add a page like Elements / Privacy Policy" (just text content) | Content only, rendered by the **existing generic template** | Recipe 2 | |
| 11 | +| "Add a section like Call to Action" (homepage block) | A **content block** + **partial** wired into `home.html` | Recipe 3 | |
| 12 | + |
| 13 | +## Where new/overridden layouts go — root `layouts/`, never `themes/<theme>/layouts/` |
| 14 | + |
| 15 | +Hugo's union filesystem makes root take precedence over the theme for the **same relative path**. This is the standard Hugo way to customize a theme without forking it, and it's how this theme stays upgradeable: |
| 16 | + |
| 17 | +- **New templates, template overrides, new sections, new partials/components** → create them under root `layouts/` at the same relative path the theme would use (e.g. `layouts/about.html`, `layouts/_partials/components/my-card.html`). |
| 18 | +- **Never create or edit files directly under `themes/<theme>/layouts/`** — those are vendored and reset/overwritten on theme updates (`<pm> update-theme` etc.). |
| 19 | +- To override an existing theme template/partial, copy it from `themes/<theme>/layouts/...` to the identical path under root `layouts/...`, then edit the copy. |
| 20 | +- To add something brand new (a new partial, a new template, a new shortcode), just create it under root `layouts/...` directly — no theme copy needed. |
| 21 | + |
| 22 | +## Recipe 1 — Custom-templated page with frontmatter (like `about`) |
| 23 | + |
| 24 | +Use when the page needs its own layout (hero image, custom sections) beyond plain content — not just a title + body. |
| 25 | + |
| 26 | +1. **Content** — `content/english/<page-name>/_index.md`. Page info goes in the frontmatter. follow related pages as example |
| 27 | + |
| 28 | +2. **Template** — `layouts/<layout-name>.html` (root, mirroring the theme path — see above). Define `"main"` and read `.Title`, `.Params.*`, `.Content`. |
| 29 | + - The frontmatter `layout: "<name>"` must match the template filename (`layouts/<name>.html`). |
| 30 | + - **Analyze an existing template first** (`about.html`, `contact.html`) for the structure, partials used, and how it reads frontmatter — copy it if needed. |
| 31 | + |
| 32 | +## Recipe 2 — Generic markdown page (like `elements`, `privacy-policy`) |
| 33 | + |
| 34 | +Use when the page is just a title + long-form content — no custom layout needed. |
| 35 | + |
| 36 | +1. **Content only** — `content/english/pages/<page-name>.md`, frontmatter has **no `layout` field**: |
| 37 | +2. **No template needed** — falls through to the existing `single.html`. |
| 38 | + |
| 39 | +## Recipe 3 — New section (like `call-to-action`) |
| 40 | + |
| 41 | +Use when adding a new block to the homepage or any other page that's toggled on/off and editable via content frontmatter. |
| 42 | + |
| 43 | +1. **Content block** — `content/english/sections/<section-name>.md`. Must include `enable: true/false` and `build.render: "never"` (so it doesn't become a standalone page); add whatever params the partial needs: |
| 44 | + |
| 45 | + ```yaml |
| 46 | + --- |
| 47 | + enable: true |
| 48 | + title: "Section title" |
| 49 | + image: "/images/my-section.png" |
| 50 | + description: "Section description" |
| 51 | + button: |
| 52 | + enable: true |
| 53 | + label: "Call to action" |
| 54 | + link: "https://example.com" |
| 55 | + build: |
| 56 | + render: "never" |
| 57 | + --- |
| 58 | + ``` |
| 59 | + |
| 60 | +2. **Partial** — `layouts/_partials/my-section.html` (root, new file — no theme copy needed). Fetch the content via `site.GetPage`, gate on `.Params.enable`, render using `.Title` / `.Params.*`: |
| 61 | + |
| 62 | + ```go-html-template |
| 63 | + <!-- My Section --> |
| 64 | + {{ with site.GetPage "sections/my-section" }} |
| 65 | + {{ if .Params.enable }} |
| 66 | + <section class="section"> |
| 67 | + <div class="container"> |
| 68 | + <h2>{{ .Title | markdownify }}</h2> |
| 69 | + <p>{{ .Params.description | markdownify }}</p> |
| 70 | + {{ with .Params.button }} |
| 71 | + {{ if .enable }} |
| 72 | + <a class="btn btn-primary" href="{{ .link | absURL }}">{{ .label }}</a> |
| 73 | + {{ end }} |
| 74 | + {{ end }} |
| 75 | + </div> |
| 76 | + </section> |
| 77 | + {{ end }} |
| 78 | + {{ end }} |
| 79 | + <!-- /My Section --> |
| 80 | + ``` |
| 81 | + |
| 82 | +3. **Wire into the page layout** — `layouts/home.html` (root override; copy from `themes/<theme>/layouts/home.html` first if not already present), add: |
| 83 | + |
| 84 | + ```go-html-template |
| 85 | + {{ partial "my-section" . }} |
| 86 | + ``` |
| 87 | + |
| 88 | + Place it in the right position relative to the other `{{ partial ... }}` / section blocks already in `home.html`. |
| 89 | + |
| 90 | +## Navigation |
| 91 | + |
| 92 | +Surface a page (Recipes 1 & 2) via `config/_default/menus.en.toml` (don't hardcode links), if not exists find it on other places. |
| 93 | + |
| 94 | +```toml |
| 95 | +[[main]] |
| 96 | +name = "My New Page" url = "/my-new-page" weight = 5 # parent = "Pages" to nest |
| 97 | +``` |
| 98 | + |
| 99 | +## Linking other pages with relative URLs |
| 100 | + |
| 101 | +`<a href="{{ .link | absURL }}">` — Hugo's `absURL` generates the correct URL based on the content path and `[permalinks]` config. Don't hardcode paths. |
| 102 | + |
| 103 | +## DO NOT |
| 104 | + |
| 105 | +- Use legacy paths — `_partials/`, `home.html`, top-level `baseof.html`. |
| 106 | +- Create or edit files directly under `themes/<theme>/layouts/` — add new templates/sections/components or override existing ones under root `layouts/` at the same relative path. |
| 107 | +- Add a `layout:` frontmatter field that doesn't match an existing/new `layouts/<name>.html` (Recipe 1) — Hugo silently falls back to the default template. |
| 108 | +- Omit `{{ define "main" }}` — page renders with no head/header/footer/SEO. |
| 109 | +- Invent frontmatter — copy a same-recipe page (e.g. copy `about` for Recipe 1, `privacy-policy` for Recipe 2, `call-to-action` for Recipe 3). |
| 110 | +- Create a section file (Recipe 3) without `build.render: "never"` (stray page). |
| 111 | +- Hardcode nav links; guess permalink behavior — check `[permalinks]` in `hugo.toml`. |
0 commit comments