How to create a list of frequently asked questions (FAQ)

Hi!

I am begining my journey with Hugo and I wenth through the documentation and Giraffe Academy’s tutorial.

It is unclear to me how Hugo parses the markdown content (i.e. what is after the front matter) of a single page. For example, let’s say I have an FAQ in content/faq.md:

---
title: FAQ
---

# What is Hugo?

A static site generator.

# Is it good?

Oh yeah!

that I want to be rendered as (for example):

<body>
  <div class='question-answer'>
    <h1 class='question'>
      What is Hugo?

    </h1>
    <p class='answer'>
      A static site generator.
    </p>
  </div>
  <div class='question-answer'>
    <h1 class='question'>
       Is it good?
    </h1>
    <p class='answer'>
      Oh yeah!
    </p>
  </div>
</body>

Then the template should look like something like this:

<body>
  {{ range .Content.Sections }}
    <div class='question-answer'>
      <h1 class='question'>
        {{ .h1 }}
      </h1>
      <p class='answer'>
        {{ .p }}
      </p>
    </div>
  {{ end }}
</body>

I have found no way of doing this (I mainly looked into variables and functions), yet this seems crucial for building a theme. What am I missing? What would be the most idiomatic way to do this?

1 Like

Hugo renders markdown to HTML via yuin/goldmark. Goldmark adheres to the CommonMark specification, with additional functionality provided by Goldmarks’s built-in extensions.

There are severals ways to create a FAQ list…

Store the questions and answers in front matter

content/faq.md
+++
title = 'FAQ'
date = 2021-01-01T00:00:00-00:00
draft = false
layout = "faq"
[[faq]]
q = "What color is the sky?"
a = "Blue/black"
[[faq]]
q = "What color is the sea?"
a = "Blue/green"
+++

layouts/_default/faq.html
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Params.faq }}
    <h2>{{ .q }}</h2>
    <p>{{ .a }}</p>
  {{ end }}
{{ end }}

Store the questions and answers in a data file (json, toml, xml, or yaml)

content/faq.md
+++
title = 'FAQ'
date = 2021-01-01T00:00:00-00:00
draft = false
layout = "faq"
+++

data/faq.json
[
  {
    "q": "What color is the sky?",
    "a": "Blue/black"
  },
  {
    "q": "What color is the sea?",
    "a": "Blue/green"
  }
]

layouts/_default/faq.html
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range site.Data.faq }}
    <h2>{{ .q }}</h2>
    <p>{{ .a }}</p>
  {{ end }}
{{ end }}

Create a FAQ content type

content/
└── faq/
    ├── what-color-is-the-ocean.md
    └── what-color-is-the-sky.md
content/faq/what-color-is-the-sky.md
+++
title = 'What color is the sky?'
date = 2022-04-09T09:41:34-07:00
draft = false
weight = 1
+++
Blue/black

layouts/faq/list.html
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
    {{ .Content }}
  {{ end }}
{{ end }}

The last option is the most flexible, allowing you to easily include images, complex markdown, code blocks, etc. in your answer.

6 Likes

Thanks a lot! Your answer is very clear and detailed.

The data option looks the cleanest. Putting everything in the front matter would bloat it. For the content option, morally you do not want to have a page for each question.

However, if I understand correctly, what you mean is that the content ({{ .Content }}) of a single page will always be parsed as a raw block, and that, in fine, it is impossible to have a control on the output of the HTML that is produced. It seems to be a really hard constraint to have!

There are two exceptions:

1) Markdown attributes

config.toml

[markup.goldmark.parser.attribute]
block = true   # default false
title = true   # default true

markdown

## Section One {id=foo class=bar}

## Section Two {#wibble .wobble}

Some paragraph.
{.my-class}

2) Markdown render hooks

Customize rendering of headings, links, images, and fenced code blocks.
https://gohugo.io/templates/render-hooks

Think of a parser as a black box with two inputs: markdown and rules (the formal specification).

2 Likes

I disagree. To me, from a content modeling perspective, this makes the most sense. And you can control whether or not the pages are rendered with build options.

2 Likes

Ok, thanks. I guess what I am looking for is a different parser then; probably even multiple parsers (e.g. one for my FAQ and one for my blog entries). Pandoc is mentioned on this page. It is probably the kind of tool I would need, is it possible to use it as a parser? Or maybe I am creating problems that do not exist and I should stick with standard Goldmark.

For the layout of the FAQ, I will definitely give your proposal a thought.

No. But you will probably want to use different layouts for each content type.

Yeah, that one.

Yeah you’re probably right…
Thanks a lot for your time and your expertise, I’ll definitely try Hugo!

I simply use HTML <details> tag.

  <details>
  <summary>Can I asked a question?</summary>

  <p>Yes, you can. </p>
  </details>

Thanks. Not found of <details> for this use case but good suggestion nonetheless.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.