Markdown

Format with Markdown

Written by oxypteros

What is Markdown

When you write something on a device, an email, a blog comment, or a Word document, you’ve probably used headings to break up sections, bullet points to list things, or made text bold or italic to emphasize it.

Normally, you achieve this by clicking formatting buttons in the editor. With Markdown, you achieve the same results using simple symbols, like asterisks, dashes, and brackets, directly in the text.

In essence, Markdown is a lightweight and widely used markup language. Even if you didn’t know the name, chances are you’ve already used it in some form.

Markdown is so simple and easy to learn that initially, I wasn’t even planning to dedicate a full step to it in the From Zero with Zero guide.
So in this step, we’re skipping the basics and diving straight into the deep end. We will focus on the subtle details of semantically correct Markdown, some common mistakes to avoid, and handy tips you need to know.

By the end of this step, you will know the “trickiest” parts of Markdown. Everything else? You’ll be able to pick up in five minutes on your own.

Markdown Instructions

Right now, you should have the Hugo server running, your recently with --kind created article open in a browser tab, and VS Code showing the /content/articles/full-page/index.en.md file.

Let’s leave the frontmatter for now and below the second +++ write:

<h2>A HTML heading</h2>

This is plain HTML. In HTML (the markup language websites are written in), there are six heading levels (<h1> to <h6>), each with decreasing importance. What you just wrote is a level 2 heading.

Now, add a blank line and write the same thing in Markdown:

## A HTML heading (in Markdown)

Preview the page in your browser, you’ll see that both headings look exactly the same.

In fact, Markdown instructions are transformed into HTML elements. And although you can format your content directly using HTML (Hugo is flexible that way), you can see that Markdown is much simpler and faster for writing content.

I’m telling you all this not to confuse you, but to make it clear: Even though Markdown is easier to write, the end result is still HTML. You don’t need to learn HTML to write Markdown, but understanding a few HTML rules will help you structure your content correctly and semantically.

Table of Content

Headings

When writing content for Alpha, you can use five heading levels:

## H2 Heading
### H3 Heading
#### H4 Heading
##### H5 Heading
###### H6 Heading

If you count the # symbols, you’ll notice they aren’t random. They correspond to the heading level. ## is a level 2 heading, ### is level 3, and so on.

But… you might wonder: What about # H1 Heading?

We don’t use # H1 Heading in Alpha, and that’s on purpose.

Remember the HTML rules I mentioned? Here’s a quick summary:

  1. Every page must have a single H1 heading representing the main title of the page.
  2. Headings should follow a logical order from H1 to H6.
  3. You can’t skip levels, you shouldn’t use an H3 before you’ve used an H2.

Let’s try this for clarity. Replace your content with:

# H1 Heading
## H2 Heading
### H3 Heading
#### H4 Heading
##### H5 Heading
###### H6 Heading

Now preview the page in your browser. You’ll see that the visual styling follows the expected hierarchy.

But, look closely.

You’ll notice no difference between the # H1 Heading and the ## H2 Heading. Why?

Because even though you wrote # H1 Heading, Alpha automatically transforms it into an H2 behind the scenes. The real H1 is already taken by the page title, Alpha handles that for you. Since each page must only have one H1, Alpha prevents duplicate H1s to keep your site semantically correct.

So, in practice: with Alpha, your headings should always start at H2 (##). That’s why #is skipped.

Let’s continue and change the H1 to a H3:

### H3 Heading
## H2 Heading
### H3 Heading
#### H4 Heading
##### H5 Heading
###### H6 Heading

Even though this renders without any visual error and your average visitor might not notice, this is incorrect.

Remember the third rule?

“You can’t skip levels, you shouldn’t use an H3 before you’ve used an H2.”

These rules aren’t arbitrary or made to make simple things harder just because.

A ## H2 heading defines a section, while a ### H3 defines a subsection (and #### a sub-subsection, and so on). So, if you use a ### H3 before a ## H2, you’re essentially defining a subsection that doesn’t belong to any section.

Some might say: Big whoop, I prefer how H3 looks better.

But headings aren’t about style, they’re about structure.

Headings are used by:

  • Screen readers (for visually impaired users) to navigate your content logically.
  • Search engines to understand the hierarchy and topics of your page.

Skipping levels or using headings out of order breaks that structure, making your content:

  • Less accessible,
  • Less logical, and
  • Potentially harder for search engines to understand.

Let’s Practice
Try spotting the mistakes in this example:

## H2 Heading
### H3 Heading
####H4 Heading
### H3 Heading
##### H4 Heading

Let’s walk through it:

  • We start with a ## H2 headingCorrect.
  • Followed by a ### H3 headingCorrect.
  • Then a ####H4 headingWrong, technically correct in hierarchy, but there’s no space between the #### and the text, so Markdown won’t recognize it as a heading and it will render as plain text and we wanted a #### H4 heading.
  • Next comes another ### H3 — Also Correct, since we already have a ## H2.
  • Lastly, ##### H4 HeadingWrong, there are actually five # symbols, so it’s a H5 heading, not H4.

Correct version:

## H2 Heading
### H3 Heading
#### H4 Heading
### H3 Heading
#### H4 Heading

Now the structure is valid and semantic.

Alpha is built to be semantically correct and accessibility friendly, and I hope I’ve managed to show you why that matters and maybe even infect you with this obsession to keep writing semantic, accessible, and well-structured content.

In you content you can use two types of links:

  1. Internal links — Links to a page within your website.
  2. External links — Links to a page on another website.

Go to your article tab in the browser and copy the page URL.
Now in VS Code, delete the content after the frontmatter and paste the URL.
It should look like this:

http://localhost:1313/articles/full-page/

If you preview the page, you’ll see the URL is just plain text. You can’t click it.
Let’s turn it into a clickable link:

[External link](http://localhost:1313/articles/full-page/)

Now it’s clickable and will open in a new tab. Test it!

Notice how the description (External link) is the text between the brackets [], and the actual URL is between parentheses (). That’s the Markdown format for a link:

[Text description](http://[url-of-a-page])

Simple? Yes. But…

Let’s see the but in practice. Publish the page.
(Do you remember how? If not go back to Step 6)

Once it’s live, visit your public article URL:
https://[YOUR-PROJECT-NAME].pages.dev/articles/full-page

Click the link we created.

It works! But… check the address bar of the new tab:
http://localhost:1313/articles/full-page/ that’s your local server, only accessible on your own computer.
If you stop the Hugo server or someone else visits your site, that link won’t work.

Let’s fix it.
In VS Code, change the link to this:

[Internal link](/articles/full-page/)

We just removed the http://localhost:1313 part. This is called a relative URL.
And now it works both locally and when published.

In fact, you can link to any page on your site by simply omitting the domain and starting with a /.

Let’s add another link now:

[Mystery link](/ "Where will it go?")

Can you guess where the Mystery link points?
Click it and then hit the Back button in your browser to return.

Did you notice something important?

  • The external link opened in a new tab.
  • The internal link opened in the same tab.

This is not a Markdown default, this is an Alpha feature.
This helps users understand when they’re staying within the site and when they’re navigating to a different one.

Why?
Opening internal links in new tabs can be confusing, especially for users who navigate using keyboards or screen readers. It breaks the flow and may cause disorientation if too many tabs open unintentionally.

And that’s one of the main reasons we use relative URL’s instead of hardcoding the full public URL.

[Absolute link](https://[YOUR-PROJECT-NAME].pages.dev/articles/full-page)

Yes, this absolute link is technically correct and accessible to anyone, as long as the target is published.
But it’s not user-friendly in this context, because Alpha will treat it as an external link and open it in a new tab.

Whenever you link to a page within your own site, prefer this:

[Internal link](/articles/full-page/)

It’s shorter, cleaner, and behaves correctly, both locally and when published.

Look again at this link:

[Mystery link](/ "Where will it go?")

The text after the URL ("Where will it go?") is the title of the link.
If you hover your mouse over it, you’ll see it as a tooltip.

Titles are optional, but helpful.

Take this example:

…learn more about Markdown here

“here” is vague. Users have no idea where it leads without clicking. It’s not very accessible or user-friendly.

A better version would be:

…learn more about Markdown at Alpha’s documentation

Now the link text is descriptive and clear, making the title optional, but it’s still a good habit to include both.

Until now, we’ve only linked internally to pages on our website, but we can also link to a specific section within a page by using anchor links.

In Alpha, every ## H2 and ### H3 heading automatically becomes a valid anchor. You can link to them like this:

[Anchor Link](/relative/URL/#heading-text)

Here’s how it works:

  • Use a single # followed by the exact text of the heading, converted to lowercase and with spaces replaced by hyphens (-).
  • This works only for H2 and H3 headings.
## This will be my anchor
[Anchor Link](/articles/full-page/#this-will-be-my-anchor)

Note:

  • If you have two or more headings with the exact same name, Hugo will automatically append -1, -2, etc., to the duplicates. So to link to the second instance, write: ([Anchor Link](/articles/full-page/#this-will-be-my-anchor-1))
  • If the anchor is in the same page, you can simplify the link like this: [Same page anchor](#this-will-be-my-anchor). This is very useful for long pages, like guides or documentation.

External links are more straightforward:

[Hugo Documentation](https://gohugo.io/documentation/ "Explore the hugo documentation")

This link contains:

  • A link description (Hugo Documentation)
  • The absolute URL (https://gohugo.io/documentation/)
  • A descriptive title ("Explore the Hugo documentation")

That’s it, no hidden traps with external links.

But don’t overdo it, you want visitors to stay on your site, not leave it. And keep in mind that when you link to an external site, search engines see it as an actual connection between your site and theirs. That means whatever happens to that site, good or bad, can potentially influence your own site’s reputation.

That’s a long discussion for another time, but for now, just remember two simple rules:

  1. Don’t link to sketchy or illegitimate websites.
  2. Use external links sparingly and only when there’s a meaningful connection between your content and theirs.

And lastly, and I cannot stress this enough.

ALWAYS test your links.

Broken links are frustrating for visitors, harm your site’s credibility, and can negatively affect how search engines view your content.

Images

Alpha was designed for textual content, and it is my belief that images often distract from the actual message without offering much in return. Of course, there are many exceptions but Alpha was not created as a gallery theme, so its support for images is intentionally minimal.

If you do need to add images to support your writing, you can do so using standard Markdown.

To insert an image, use the following syntax:

![Description of the image](filename.jpg "Figcaption of the image")

Let’s walk through a simple example:

  1. Download the image of a cat1 or the image of a dog. 2
  2. Move the downloaded image inside the folder /content/articles/full-page/ in your Hugo site.
  3. Add and modify the Markdown instruction above to your case.

If everything works correctly, you should see an image of a cat or a dog. Otherwise, Alpha will display a warning about the missing image.
Your Markdown might look like this:

![Portrait of a dog](dog.jpg "A cute dog")

As you can see, the Markdown syntax for an image is almost the same as for a link. The only difference is the exclamation mark (!) at the beginning.

The text inside the brackets is the image description. This is used for screen readers and will also appear if the image fails to load. It’s strongly recommended to always include this for accessibility. If the description is missing, Alpha will show a local warning to remind you to add one.

In place of the URL, we provide the filename along with its file extension (e.g. .jpg, .png). Hugo will find the image only if it’s placed in the same folder as your index.en.md (also known as the page bundle).
If the image is missing, placed elsewhere, or the filename is incorrect, Alpha will show a warning that the image was not found.

The optional title, written inside quotes, will appear as a caption (figcaption) below the image.

How and if you’re going to use images in your content, that’s entirely your decision.However, please keep the following in mind:

  • Use high-quality images. Alpha will automatically scale them down to an appropriate resolution and optimize them for the web.
  • Avoid using copyrighted material unless you have permission. Provide attribution where required.
  • And lastly, (consider this a personal favor), don’t use images that are irrelevant to your content just for decoration. They distract more than they help.

Lists

Lists in Markdown are as simple as they get. You can create either unordered (bullet point) lists or ordered (numbered) lists.

Which one you should use depends entirely on the type of content you’re listing:

  • Use a numbered list when the items need to follow a specific order, such as steps in a process or instructions.
  • Use a bullet point list when the items have no inherent order, such as ingredients, features, or options.

This distinction isn’t just for visual clarity. It also improves accessibility for screen readers and enhances semantic meaning for search engines.

Let’s assume your site is about cooking, and you want to create a recipe post.
You write your introduction, and then you need to list the ingredients.
Ingredients don’t need to follow any specific order, so you should use a bullet point list.

To create a bullet point list in Markdown, simply add a dash (-) followed by a space before each item. Each item goes on a new line:

## Ingredients
- 2 eggs  
- 1 cup of flour  
- ½ cup of milk  
- Salt

After the ingredients, of course, comes the procedure, which is a series of steps that must happen in order. For that, you should use a numbered list.

To create a numbered list in Markdown, place a number followed by a dot and a space before each step. Each step goes on a new line:

## Procedure
1. Crack the eggs into a bowl.  
1. Add the flour and milk.  
1. Whisk until smooth.  
1. Add a pinch of salt and cook.

You might be wondering why every line starts with 1.. Markdown doesn’t mind!
Only the first number matters. If the first item starts with 1., the rest will automatically be numbered in sequence. You could even use the same number for every step, and Markdown would still render it correctly as a proper ordered list.

If the first number is 3., the next will be 4. even if you write 1. again, if it’s 2000., the next will be 2001. regardless of what you actually write. That’s why in the example above, even though we wrote 1. four times, the final rendered result shows steps 1 to 4.

Sub-Lists

The example we used earlier was simple, but real-world lists, like recipes or how-to guides, can be more complex, often including sub-items, sub-steps, or a mix of both.

Let’s look at a more realistic scenario. Right now, you’re reading a multi-step guide, and each step contains smaller steps or grouped items.

Here’s what we’ve done so far:

  1. We created GitHub and Cloudflare accounts
  2. We installed software
  3. We published to GitHub
  4. We deployed to Cloudflare Pages
  5. We created our first article
  6. We learned about Frontmatter
  7. And now we’re learning about Markdown

But this list isn’t entirely accurate.

  • Step 2 should mention what we installed.
  • Steps 6 and 7 are actually part of step 5.

To better reflect this, we can use nested lists. In Markdown, that simply means indenting sub-items with either one tab or four spaces.

So let’s rewrite the list, nesting step 2’s items with a numbered sub-list and turning steps 6 and 7 into a bullet sub-list under step 5:

1. We created Github and Cloudflare accounts
2. We installed software:
    1. Git
    2. VS Code
    3. Alpha theme
3. We published to Github
4. We deployed to Cloudflare pages
5. We created our fist article
    - Learned about Frontmatter
    - And now we are learning about Markdown

Looks better! But we forgot to include Hugo under the software installed in step 2!

Do we have to renumber the whole sub-list?
No. Remember, Markdown only cares about the first number. You can just add a new line with 1. Hugo Markdown will still auto-render it correctly:

1. We created GitHub and Cloudflare accounts  
2. We installed software:  
    1. Hugo  
    1. Git  
    2. VS Code  
    3. Alpha theme  
3. We published to GitHub  
4. We deployed to Cloudflare Pages  
5. We created our first content  
    - Learned about Frontmatter  
    - And now we’re learning about Markdown  

Now, some of you may ask:
“Are you so lazy you can’t change three numbers?”

Honestly? Maybe a little. But that’s not the point.
Imagine your list had over 100 items. Say, a chronological list of every novel Stephen King has written and you forgot to include one novel around number 50. If you used manual numbering, you’d have to update every item after that.

With Markdown’s auto-numbering, it’s handled for you.

Checklist

There’s another type of list that’s not officially supported by plain Markdown, but Hugo does support it: the checklist.

Even though Hugo supports rendering checklists, Alpha theme does not offer any interactive functionality for visitors. In other words, visitors can’t click to check or uncheck boxes.
This limits how useful checklists are for interactive purposes, but you may still find them helpful for static content like publishing to-do’s, project stages, or publication status.

To create a checklist in Markdown, start a list and add [ ] (a pair of square brackets with a space between them) before the item. This renders an unchecked box.
To create a checked box, use [x] instead.

Example:

## Unordered checklist
- [x] Checked item  
- [ ] Unchecked item  

## Ordered checklist
1. [ ]Unchecked item
1. [x] Checked item

Of course Markdown is not only links images and headings, with Markdown you can style your content almost as you can with a document editor. As I told you at the beginning these are easy to learn and they only need a bit of practice.

So, now before you click Next Part take five read the Alpha Markdown documentation and try to use each style in your Full Page article.


  1. Cat image by Annette Meyer from Pixabay ↩︎

  2. Dog image by Sonja Kalee from Pixabay. ↩︎