DraftThis is a draft. It shows up on the development site only and is not published.
How to write a post for the endue blog
Where a post lives, what each frontmatter field does, and how a post goes from a draft on dev to a published page on endue.ai.

On this page
This post is a working sample. It is marked as a draft, so it shows up on dev.endue.ai and never on endue.ai. Every element a post can use appears somewhere on this page. Keep the source open next to it when you write your first post.
Where a post lives
Posts are files in src/content/blog/, one folder per language:
src/content/blog/
├── en/
│ ├── agents-on-call.md # a post without images
│ └── building-the-canvas/
│ ├── index.mdx # a post with images of its own
│ └── canvas-before.png
└── ko/
└── agents-on-call.md # same slug: the Korean translation
The file or folder name is the slug, and the slug is the URL: en/agents-on-call.md is published at /blog/agents-on-call/. Use lowercase letters, digits and hyphens.
A post in ko/ with the same slug is its translation. The two pages link to each other, and search engines learn they are one article in two languages. A post does not need a translation.
Frontmatter
| Field | Required | What it does |
|---|---|---|
title |
yes | The headline. Up to 120 characters. |
description |
yes | One or two sentences. Shown on the post card, in search results and in link previews. |
publishedAt |
yes | Publication day, YYYY-MM-DD. Posts are listed newest first. |
updatedAt |
no | Set it only for a real revision. Readers see it next to the date. |
authors |
yes | Keys from src/content/authors.yaml. |
tags |
no | Keys from src/content/tags.yaml. Add a tag there before you use it. |
cover |
no | An image path. It also becomes the post’s link preview. |
coverAlt |
with cover |
What the image shows, for readers who cannot see it. |
draft |
no | true keeps the post off endue.ai. |
canonical |
no | For a post first published somewhere else. |
From draft to published
- Branch from
developand write the post withdraft: true. - Open a merge request to
develop. Once it is merged, the post appears on dev.endue.ai/blog with a Draft badge. Share that link for review. - When the post is ready, change
drafttofalseand merge again. - The post reaches endue.ai with the next release, when
developis merged intomainand the site is deployed.
Writing the body
Links
Write links to other pages on endue.ai as full paths: /blog/agents-on-call/ for a post, /docs/get-started/quickstart/ for the docs, /pricing for a product page. Links to other sites are written as usual.
The build checks every path in a post. A link to a post that does not exist, or that is still a draft when the site is built for endue.ai, stops the build and names the file. Here is one that passes: the blog home.
Images
A Markdown image is resized and served in a modern format automatically:

When an image needs a caption, use the Figure component instead:

Put an image next to the post that uses it (a folder post). If a post and its translation share images, keep them in src/assets/posts/<slug>/ and point both posts there, as this one does.
Callouts
Three types exist: note, tip and warning. Use them rarely. A page full of callouts has none.
Code
Inline code looks like npm run dev. Blocks are highlighted by language:
// How long a post takes to read, as shown under its title.
export function readingMinutes(words: number, wordsPerMinute = 230): number {
return Math.max(1, Math.round(words / wordsPerMinute));
}
Quotes and footnotes
Write the post you would want to find when you search for the problem it solves.
A footnote adds a detail without breaking the sentence.1
Before you merge
- Run
npm run buildand fix what it reports. - Read the page on your own machine with
npm run dev. - Check the link preview: the title, the description and the cover are what people see when the post is shared.
Footnotes
-
Footnotes are collected at the end of the post. ↩


