What this blog can render

Aug 8, 2026·
Felipe Cardoso
Felipe Cardoso
· 5 min read
blog

A reference for my future self. Everything below is verified against the theme’s own source, not guessed from documentation. Each section shows the markup and the thing it produces.

Callouts

GitHub / Obsidian alert syntax. Five types: NOTE, TIP, IMPORTANT, WARNING, CAUTION. Append + Some Title for a custom heading.

> [!NOTE]
> Plain note.

> [!WARNING] Careful with this one
> A warning with a custom title.
Note

Plain note.

Tip

Tips look like this.

Careful with this one

A warning with a custom title.

Caution

The strongest one.

There is also a {{< callout >}} shortcode, but the theme marks it deprecated in favour of the syntax above. Don’t use it.

Mermaid

Fenced block with mermaid as the language. The script only loads on pages that actually contain one.

```mermaid
sequenceDiagram
    Browser->>Pages: GET /en/blog/
    Pages-->>Browser: static HTML
    Browser->>Remark42: GET /api/v1/find
```
sequenceDiagram autonumber participant B as Browser participant P as Cloudflare Pages participant R as Remark42 (VPS) B->>P: GET /en/blog/capabilities/ P-->>B: static HTML + embed.js B->>R: GET /api/v1/find?site=blog R-->>B: comments JSON Note over B,R: anonymous, no account needed

Flowcharts work too:

flowchart LR A[git push] --> B{branch?} B -->|main| C[production build] B -->|other| D[preview deploy] C --> E[fehac.dev] D --> F[*.pages.dev]

Markmap

Mind maps from a nested list. Takes a height attribute.

```markmap {height="300px"}
- Root
  - Branch
    - Leaf
```
- Backend
  - Services
    - APIs
    - Event-driven
  - Data
    - PostgreSQL
    - MongoDB
- Infrastructure
  - AWS
    - CDK
    - CloudFormation
  - Azure
    - Terraform
- Practice
  - CI/CD
  - Observability
  - Incident response

Math

KaTeX. Loads when the page has math: true in front matter, a math shortcode, or the site-wide flag. Inline with $...$, display with $$...$$.

Inline: $O(n \log n)$

$$
p_{99} = \inf\{x : F(x) \ge 0.99\}
$$

Inline: $O(n \log n)$ is the bound.

$$ p_{99} = \inf\{x : F(x) \ge 0.99\} $$

Code

Standard fenced blocks, highlighted by Hugo’s built-in Chroma. Line numbers are off by default site-wide but can be turned on per block.

```python {linenos=true, hl_lines=[2]}
def charge(rate_kw: float) -> float:
    return min(rate_kw, MAX_KW)
```
1def charge(rate_kw: float) -> float:
2    return min(rate_kw, MAX_KW)  # clamp to the connector limit

Steps

Wrap ### headings. Each becomes a numbered step.

{{< steps >}}
### First thing
Do this.
### Second thing
Then this.
{{< /steps >}}
### Provision DNS An `A` record has to resolve before certbot will issue anything. ### Issue the certificate `certbot certonly --webroot`, then swap in the TLS vhost. ### Reload, don't restart `nginx -t` first. It refuses a bad config instead of taking the box down.

Spoilers

{{< spoiler text="Click to expand" >}}
Hidden content.
{{< /spoiler >}}
Why the comment server is not on Cloudflare
Pages is static hosting. Remark42 is a stateful Go process with an embedded BoltDB, so it needs a real host. It runs on my VPS behind nginx, bound to loopback only.

Buttons

{{< button url="/en/about/" >}}About me{{< /button >}}

Charts

Plotly. Point data at a JSON file in the page folder, without the extension. Here demo-chart.json sits next to this index.md.

{{< chart data="demo-chart" >}}

CSV tables

Same idea: a .csv in the page folder. Note the parameter is path, not src. The shortcode’s own docstring says src, but the code reads .Get "path". Using src fails the build with a nil-pointer error.

{{< table path="demo-table.csv" caption="Latency by service" >}}
servicelanguagep99_mserror_rate
charging-enginePython630.02
telemetry-ingestPython1480.11
fleet-apiTypeScript410.01
Latency by service

Regular Markdown tables also work:

FeatureSupportedNotes
Mermaidyeslazy-loaded per page
Markmapyesheight attribute
PlantUMLnosee below

Images

Plain Markdown. The render hook looks in the page folder first, then in assets/media/, and emits a responsive srcset with generated sizes.

![Alt text](authors/me.webp)

Video and audio

{{< video src="clip.mp4" controls="yes" >}}
{{< audio src="episode.mp3" >}}

Both resolve the page folder first, then assets/media/, then a remote URL.

Icons

{{< icon name="brands/github" >}} inline in a sentence.

inline in a sentence.

Jupyter notebooks

{{< notebook path="analysis.ipynb" >}}

Renders an .ipynb inline, useful for the data-heavy posts.

Includes

{{< include "snippets/shared-warning.md" >}}

Pulls another Markdown file in, path relative to content/.

What is not supported

PlantUML. There is no PlantUML render hook or script anywhere in this theme. I checked the layouts and the JS bundle. Options if I ever need it:

  1. Use Mermaid instead. It covers sequence, flowchart, class, state, ER, and Gantt, which is most of what PlantUML gets used for.
  2. Render the .puml to SVG offline and commit the SVG, then embed it as a normal image. No build-time dependency, no external server.

A PlantUML render hook would be maybe twenty lines in layouts/_markup/render-codeblock-plantuml.html, but it would have to call out to a rendering server at build time, which is why I’d rather not.

Front matter that matters

---
title: "Post title"
summary: "Shown in listings and meta description."
date: 2026-08-08
translationKey: some-key   # links the pt/en/ja versions together
authors: [me]
tags: [meta, markdown]
math: true                 # load KaTeX on this page
commentable: true          # inherited from blog/_index.md already
draft: false
---

translationKey is the important one: it is what makes the language switcher jump to the same article instead of the homepage.

Felipe Cardoso
Authors
Senior Backend Engineer
Backend systems, cloud infrastructure and distributed systems. Currently in Tokyo.
Loading comments…