Blog Post Collections — Individual Articles
Create and edit individual blog posts in Dax Pro: frontmatter fields, images, tags, excerpts, ordering, and Markdown body. Each file in content/posts/*.md becomes an article at /posts/{slug}/.
What a Blog Post Collection Is
Every article on your blog is a single Markdown file inside the content/posts/ folder. The filename becomes the URL:
content/posts/why-static-sites-win.md → /posts/why-static-sites-win/
content/posts/blazor-vs-dax-pro.md → /posts/blazor-vs-dax-pro/
content/posts/decap-cms-guide.md → /posts/decap-cms-guide/
Every post shares the same template (post.dax), the same layout, and the same frontmatter structure. The differences are the content: title, description, body, image, and tags.
When you add a new file to content/posts/, the post appears in /posts/ automatically and gets its own URL. When you delete one, both disappear. There is no separate index to update.
This chapter covers everything a post owner needs to know:
1. The frontmatter structure — every field in every post
2. Writing the Markdown body — the content readers see
3. Images — featured images, inline images, and OpenGraph
4. Tags — how they create tag pages and cross-link content
5. Excerpt — the summary that appears on the listing
6. Ordering — how posts sort in the listing and on the homepage
7. Creating a post — via Decap CMS and via file
8. Editing and deleting — both methods
9. Reading time — how to estimate it
10. Common mistakes — patterns that break post pages
The Frontmatter Structure
Every post starts with a frontmatter block. Here is a complete example:
---
layout: "post.dax"
title: "Why Modern Enterprises Are Abandoning Dynamic WordPress for .NET SSG"
description: "An executive breakdown of how replacing dynamic SQL databases with compiled .NET static sites reduces operational hosting expenses by 85% while boosting organic Core Web Vitals scores."
image: "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1200&q=80&auto=format&fit=crop"
date: 2026-03-28
category: "Architecture"
read_time: "5 min read"
read_more: "Read Analysis"
author: "Robert Vance"
tags: ["dotnet", "static", "wordpress", "performance", "migration"]
excerpt: "An executive breakdown of how replacing dynamic SQL databases with compiled .NET static sites reduces operational hosting expenses by 85% while boosting organic Core Web Vitals scores."
Every field explained:
| Field | Purpose | Required? |
|---|---|---|
layout |
The template used to render the post. Must be post.dax. |
Yes |
title |
The post's H1, browser title, listing card title, prev/next link title. | Yes |
description |
Meta description for SEO and OpenGraph description. | Yes |
image |
Featured image. Used as OpenGraph image, listing card thumbnail, and post cover. | Optional |
date |
Publication date in YYYY-MM-DD format. Determines ordering. |
Yes |
category |
Single category name. Shown in the meta line on listing cards and post header. | Optional |
read_time |
Human-readable read estimate. You determine the value; the engine does not calculate. | Optional |
read_more |
"Read more" label on the listing card. Defaults to "Read Article" if omitted. | Optional |
author |
Author name. Shown in the meta line and post header. | Optional |
tags |
List of lowercase tags. Each becomes a tag page at /tags/{tag}/. |
Optional |
excerpt |
Short summary shown on the listing card. Distinct from description. |
Recommended |
Do not change layout. It must always be post.dax.
Field-by-Field Guide
title
The most important field. It appears in six places:
1. The on the post page
2. The in the browser tab
3. The listing card on /posts/
4. The Insights card on the homepage (if the post is among the three most recent)
5. The prev/next navigation on adjacent posts
6. The tag pages where the post appears
Guidelines for post titles:
- Descriptive over clever. "Why Static Sites Beat WordPress for Enterprise Content" outperforms "The Static Revolution" in search and clicks.
- Include your target keyword near the start. If you are writing about Decap CMS, start with "Decap CMS" or put it within the first three words.
- 60–70 characters is ideal. Longer titles get truncated in search results and social cards.
- Avoid clickbait. Enterprise readers distrust headlines like "You Won't Believe What Happened Next."
(what search engines show in results)- OpenGraph description (what social media shows in link previews)
- Fallback for the listing card if
excerptis not set - 150–160 characters. Longer gets truncated.
- Include the primary keyword.
- Write it as a complete sentence that makes someone want to click.
- Do not just repeat the title. The description should add information.
- Recommended dimensions: 1200×630 pixels. This is the OpenGraph standard. Twitter, Facebook, LinkedIn all crop to about this ratio (1.91:1).
- Format:
.webp(smallest, modern),.jpg(universal),.png(largest, use only when transparency is needed). - Content: the image should relate to the post. A technical post about CI/CD might show a terminal; a post about performance might show a speedometer; a post about migration might show a bridge.
- No text overlay. Text in images gets cut off in different crops. Let the title carry the message.
- Unsplash — high quality, free for commercial use
- Pexels — similar
- Pixabay — similar
description
The meta description. Used for:
Guidelines:
Example:
Title: Why Modern Enterprises Are Abandoning WordPress for .NET SSG
Description: An executive breakdown of how compiled .NET static sites reduce hosting costs by 85% while boosting Core Web Vitals.
The title makes a claim; the description adds the specifics.
image
The featured image. Used in three places:
1. OpenGraph image — what appears when the post is shared on Twitter, LinkedIn, Facebook, Slack
2. Listing card thumbnail — the image at the top of the post card on /posts/ and the homepage
3. Post cover — a large image at the top of the post page itself
Guidelines:
Free image sources:
To use an Unsplash image:
1. Find an image
2. Copy the image URL (Unsplash provides direct URLs)
3. Append ?w=1200&q=80&auto=format&fit=crop to the URL
4. Paste into image:
For example:
image: "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1200&q=80&auto=format&fit=crop"
The w=1200 parameter sets width to 1200 pixels. q=80 sets quality to 80%. auto=format uses the best format for the browser. fit=crop crops to the requested aspect ratio.
For your own images:
1. Place the file in public/images/
2. Reference it with a path starting with /:
image: "/images/my-post-image.jpg"
date
Publication date in YYYY-MM-DD format. Determines:
/posts/ listing (most recent first)datePublished in the JSON-LD schemaFormat is strict:
date: 2026-05-12 # correct
date: May 12, 2026 # wrong
date: 05/12/2026 # wrong
Dates in the future are still published. Dax Pro has no scheduling. A post dated 2027 will appear immediately at the top of the listing because its date is the "most recent." If you want to unpublish a post, delete its file.
Changing a post's date changes its position. A post dated 2026-01-01 appears after a post dated 2026-05-01. Use this to control ordering.
category
A single category name. Shown in the meta line on listing cards and post headers. Examples:
category: "Architecture"
category: "Decap CMS"
category: "Performance"
category: "Migration"
category: "Tutorial"
Categories are cosmetic. They do not create a category page (unlike tags). They are displayed text. Choose categories that match the post's topic.
Use consistent categories across posts. If you have three posts about Decap CMS, label them all Decap CMS, not "Decap CMS" and "Decap" and "CMS." Consistency helps readers scan the archive.
Categories are not indexed. Unlike tags, categories do not have their own URLs. If you want indexable categorization, use tags.
read_time
A human-readable read estimate. Examples:
read_time: "5 min read"
read_time: "10 min read"
read_time: "1 min read"
You determine this value. Dax Pro does not calculate it. The number is shown in the meta line of listing cards and post headers.
Estimation:
Be honest. Under-estimating sets false expectations; a "3 min read" that takes 10 minutes frustrates readers. Over-estimating discourages clicks.
read_more
The "read more" label on the listing card. Defaults to "Read Article" if omitted. Examples:
read_more: "Read Analysis"
read_more: "Read Guide"
read_more: "Read Blueprint"
read_more: "Read Tutorial"
read_more: "Read Article"
Customize per post type:
Or use one label everywhere. "Read Article" is a safe default for all posts. Customizing per post is optional; it adds a small amount of personality.
author
Author name. Shown in the meta line of the listing card and post header. Examples:
author: "Robert Vance"
author: "Elena Chen"
author: "Marcus Sterling"
author: "Axcora Team"
Single author per post. Dax Pro supports one author field. If you have multiple authors, pick the primary author or use a team name.
Author bios: the author field is just a name. There is no separate author page or bio. If you want author bios, that is a developer feature — see the Developer Guide.
tags
A list of lowercase tags. Each tag creates a tag page and cross-links the post.
tags: ["dotnet", "static", "wordpress", "performance", "migration"]
Tags must be lowercase. A tag "DotNet" produces a URL /tags/DotNet/ that does not match the generated /tags/dotnet/ page. Uppercase tags break.
Common tags:
dotnet, razor, blazor, decapcms, static, enterprise, migration,
azure, cicd, performance, accessibility, wcag, theming, brand,
audit, compliance, headless, csharp, wordpress, drupal, sitecore
Number of tags per post: two to six is typical. One is fine. Twenty dilutes the taxonomy.
Tags are cumulative. A tag page shows every post and service with that tag. Adding a new tag to one post creates a new tag page listing that one post. Adding the same tag to a second post adds it to the tag page.
Tags are case-sensitive. "dotnet" and "DotNet" are different tags. Always lowercase.
No spaces. "content migration" should be "content-migration" or "migration". Spaces break URLs.
excerpt
The short summary shown on the listing card. Distinct from description:
description — for search engines and social media. 150–160 characters. Written for click-through from search results.excerpt — for the listing card on /posts/. 100–200 characters. Written for scanning.Example:
Description: An executive breakdown of how compiled .NET static sites reduce hosting costs by 85% while boosting Core Web Vitals.
Excerpt: An executive breakdown of how replacing dynamic SQL databases with compiled .NET static sites reduces operational hosting expenses by 85%.
The excerpt is slightly longer and more specific. It appears on the listing card where there is more space than in a search result.
If excerpt is omitted, the listing card falls back to description. This works fine for most posts. Writing a separate excerpt adds precision but is not required.
Writing the Markdown Body
After the closing ---, the body begins. It is rendered as the main content of the post page.
A well-structured post body has:
1. A compelling opening — one or two paragraphs that state the problem or hook. Do not waste the opening on throat-clearing.
2. Section headings — one ## per major point, one ### per sub-point.
3. Body paragraphs — short paragraphs (2–4 sentences each) are easier to scan than long ones.
4. Lists, code blocks, images — break up text and give the reader visual anchors.
5. A concluding section — a short summary or call to action.
Example structure:
## The Core Problem
[Two to four sentences setting up the problem.]
Why Current Solutions Fail
[Analysis of alternatives.]
Specific failure mode 1
[Detail.]
Specific failure mode 2
[Detail.]
The Alternative
[Your approach.]
Conclusion
[Summary and next step.]
Markdown features supported:
## and ### for section headings-1., 2., 3.bold and italiclink text for inline links
for inline images inline code for code referencesLength: there is no enforced minimum or maximum. Technical posts typically run 800–2,000 words. Tutorials may run 2,000–4,000. News posts may run 300–500. Write as long as the topic requires and no longer.
Structure matters more than length. A well-structured 800-word post reads better than an unstructured 2,000-word post.
Adding Images to the Body
In addition to the featured image in the frontmatter, you can add images within the Markdown body. These render as inline images.
Syntax:
Alt text matters. It is read by screen readers (accessibility) and used by search engines. Write meaningful alt text:
Not:
Image paths:
— use /images/filename.jpgSupported formats: .jpg, .png, .webp, .gif, .svg.
File size matters. Images over 500 KB slow the page. Compress before uploading:
Lazy loading: Dax Pro's templates apply loading="lazy" to images. Images below the fold do not block rendering. Images above the fold (the featured image) use fetchpriority="high" for LCP optimization.
Creating a New Post
Via Decap CMS
1. Open https://yoursite.com/admin/
2. Click 📝 Posts in the left sidebar
3. Click New Post (top-right of the posts list)
4. Fill in the fields:
| Field | Value |
|---|---|
| Title | Your post title |
| Description | 150–160 character summary for SEO |
| Image | Optional featured image URL or uploaded file |
| Date | Publication date |
| Category | Single category name |
| Read Time | e.g., 5 min read |
| Read More Label | e.g., Read Analysis |
| Author | Author name |
| Tags | Comma-separated lowercase tags |
| Excerpt | 100–200 character summary for the listing card |
| Body | Markdown body content |
5. Click Publish
6. The file content/posts/{slug}.md is created
7. The host rebuilds and the post appears at /posts/{slug}/
Slug rules: the title determines the filename. Why Static Sites Win → why-static-sites-win.md → /posts/why-static-sites-win/. Choose titles that produce the URLs you want.
Uploading images: the Image field can either accept a URL (paste any external image URL) or upload a file. Uploading places the file in public/images/ and inserts the path automatically.
Directly in the File System
1. Open content/posts/ in VS Code
2. Create a new file (e.g., my-new-post.md)
3. Paste the frontmatter template:
---
layout: "post.dax"
title: "My New Post Title"
description: "A 150-character summary for search engines."
image: "https://images.unsplash.com/photo-1234567890?w=1200&q=80&auto=format&fit=crop"
date: 2026-05-12
category: "Tutorial"
read_time: "5 min read"
read_more: "Read Article"
author: "Your Name"
tags: ["dotnet", "tutorial"]
excerpt: "A 150-character summary for the listing card."
Opening Section
Body content goes here.
Second Section
More content.
4. Save
5. Run dotnet run -- build
6. The post appears at /posts/my-new-post/
Pitfalls of direct creation:
produces /posts/My New Post/ — broken (spaces in URL). Use lowercase with hyphens: my-new-post.md., not May 12, 2026., closing delimiter is --- followed by a blank line.Editing an Existing Post
Via Decap CMS
1. Open https://yoursite.com/admin/
2. Click 📝 Posts
3. Click the post to edit
4. Update fields or body
5. Click Publish
The change commits to Git, the host rebuilds, the post updates within a minute.
Directly in the File System
1. Open content/posts/{slug}.md in VS Code
2. Edit the frontmatter or body
3. Save
4. Run dotnet run -- build (or dotnet run -- start for live preview)
5. Commit and push for production
git add content/posts/{slug}.md
git commit -m "Update post: {title}"
git push
Deleting a Post
Via Decap CMS
1. Open https://yoursite.com/admin/
2. Click 📝 Posts
3. Click the post
4. Click the ⋯ menu in the top-right
5. Choose Delete entry
6. Confirm
Directly in the File System
rm content/posts/{slug}.md
dotnet run -- build
git add content/posts/
git commit -m "Remove post: {title}"
git push
The post disappears from /posts/. Any tags it had that no other post or service uses disappear from /tags/. The homepage Insights section fills the vacancy with the next most recent post.
Ordering and the Homepage
Post ordering in /posts/ and on the homepage Insights section is by date in descending order.
The homepage Insights section shows three posts. These are the three posts with the most recent dates.
If you have three posts and one is dated 2026-05-01, one 2026-04-01, one 2026-03-01:
shows all threeIf you have ten posts and dates range from 2026-05-01 to 2026-01-01:
shows all ten, paginatedTo feature a specific post on the homepage:
1. Change its date to a more recent value than the current three
2. Rebuild
The post appears in the top three.
To remove a post from the homepage Insights:
1. Change its date to an older value
2. Rebuild
The post falls out of the top three.
You cannot pin a post without affecting its date. The homepage Insights is purely date-driven. If you want to highlight a post that is not the most recent, the workaround is to update its date to be more recent.
Draft Workflow
Dax Pro does not have built-in draft support. There is no draft: true field that hides a post from the build. If a post is in content/posts/, it is published.
For draft work, use one of these patterns:
Pattern 1: Local drafts. Write the post in content/posts/draft-post.md while working. Do not commit the file to Git until it is ready. Push when ready.
Pattern 2: Archive folder. Create _archive/drafts/ outside content/. Write posts there. Move to content/posts/ when ready to publish.
Pattern 3: Feature branch. Create a Git branch for the draft. Work on the branch. Merge to main when ready. On Netlify, main deploys; other branches get previews (preview URLs) but not production deployment.
Pattern 4: Future date. Set the date to a future value and skip building locally until the date arrives. But: the host still builds on push, so the post is live from the moment it is pushed. This pattern does not actually prevent publication.
Recommended: Pattern 1 or 3. Local drafts are simplest. Feature branches add preview environments.
Reading Time Estimation
You determine the read_time value. Here is a formula:
1. Count the words in the post body.
2. Divide by reading speed.
3. Round up.
Example:
A post has 1,500 words of technical content. Divide by 220:
1500 / 220 = 6.8 minutes
Round up to 7. Set read_time: "7 min read".
Add time for multimedia:
If the 1,500-word post has 5 code blocks and 3 images:
1500 / 220 = 6.8 min
5 code blocks × 15 sec = 75 sec = 1.25 min
3 images × 10 sec = 30 sec = 0.5 min
Total: 6.8 + 1.25 + 0.5 = 8.55 min
Round up: 9 min read
Set read_time: "9 min read".
Be honest. Under-estimating sets false expectations. Over-estimating discourages clicks. A little buffer (round up) is better than a little optimism.
Common Blog Post Mistakes
Mistake 1: Uppercase tags.
tags: ["DotNet", "Razor"] # wrong
tags: ["dotnet", "razor"] # correct
Uppercase tags break the tag page links.
Mistake 2: Spaces in tags.
tags: ["content migration"] # wrong
tags: ["content-migration"] # correct
Spaces break URL slugs.
Mistake 3: Missing date.
Without a date, the post is treated as having the oldest possible date. It appears last in the listing and never on the homepage Insights.
Mistake 4: Invalid date format.
date: 05/12/2026 # wrong
date: May 12, 2026 # wrong
date: 2026-05-12 # correct
The date must be YYYY-MM-DD.
Mistake 5: Spaces in the filename.
# File: My New Post.md → /posts/My New Post/ (broken URL)
File: my-new-post.md → /posts/my-new-post/ (correct)
Always lowercase, always hyphens, no spaces.
Mistake 6: Duplicate slugs.
Two posts named "Decap CMS Guide" and "Decap CMS Guide!" both become decap-cms-guide.md (or similar) — one overwrites the other. Ensure unique titles or unique filenames.
Mistake 7: Bad image URLs.
If image: "https://example.com/broken.jpg" points to a 404, the listing card shows a broken image. Test the URL in a browser before publishing.
Mistake 8: Very long title.
Why Modern Enterprises Are Abandoning Dynamic WordPress for .NET SSG and What It Means for the Future becomes a very long slug. Shorten the title or accept the long URL.
Mistake 9: Excerpt too long.
Excerpts over 200 characters get truncated on listing cards, sometimes mid-word. Keep excerpts under 200 characters.
Mistake 10: Forgetting the excerpt.
Without an excerpt, the listing card shows the description. This is usually fine. But if the description is written for SEO (starts with "Learn how..." or "Discover the..."), it reads awkwardly on a listing card. Write an excerpt or write the description as an excerpt-style summary.
Mistake 11: Changing a post's date without rebuilding.
Changing the date in the frontmatter affects ordering, but only after a rebuild. If the date changed and the order did not, you forgot to build.
Mistake 12: Placing the post in the wrong folder.
content/posts-archive/old-post.md is not content/posts/. Files outside content/posts/ are not part of the posts collection. They render at their own URL but do not appear in /posts/.
Verifying a Post Page
After creating or editing a post, verify:
1. URL works — navigate to /posts/{slug}/. The page loads.
2. Title — browser tab and H1 match.
3. Breadcrumb — shows "Home / Insights / Title".
4. Description — view source, confirm matches.
5. Featured image — if set, appears as the post cover and as the OpenGraph image.
6. Meta line — shows category, date, author, read time.
7. Body — all Markdown renders correctly.
8. Tags — if set, appears at the bottom of the post as clickable chips.
9. Prev/next — if adjacent posts exist, links appear at the bottom.
10. Listing — the post appears in /posts/ with correct title, excerpt, image, and metadata.
11. Homepage — if the post is among the three most recent, it appears on the homepage Insights.
12. Social card — paste the URL into opengraph.xyz or similar tool to see how it appears when shared.
13. Mobile — resize browser. Text wraps, images scale, body reads cleanly.
If the post shows raw YAML in the browser, the frontmatter is malformed. Check the four rules:
What You Have Now
After this chapter, you can:
Blog posts are done. The next chapter covers GitHub Setup — creating a GitHub account, creating a repository, pushing your project, and creating a personal access token for Netlify and Decap CMS.
→ Continue to GitHub Setup