Blog Publishing
Write a bilingual MDX article, add a cover, and check it on your blog.
Publish articles from files in your app's content/posts/. Start with a paired English/Chinese post, then check its listing and detail page.
Before You Start
Have dev running and prepare a title, description, date, category, and optional cover. File paths are relative to your selected application's root.
1. Create the Content Pair
Create content/posts/first-post.en.mdx:
---
title: Our first release
description: What we are building and who it is for.
date: "2026-10-12"
categories: ["Product"]
published: true
---
Welcome to our product. Here is what you can do today.
## Get started
Explain the first useful action your reader can take.Create first-post.zh.mdx with the same fields and Chinese content. Keep the filename stem and publication date aligned. Your post body is ordinary MDX; see Rich Content Blocks for Callouts, Cards, and Steps.
2. Add a Cover
Place an image in your app's public/images/blog/, then add image: /images/blog/your-cover.png to both files. Use a descriptive title and description for the article metadata.
3. Open the Blog
Open /blog and the other locale's blog route. Find your title and click through to the article. Dev/build generates content sources automatically; if types are missing, start dev or run the selected app build.
Check Your Result
- The post is listed with its date, category, and optional image.
- Each locale opens the matching translated article.
- Headings, images, body blocks, and metadata display correctly.
- run the selected app build; for two-app products also check
pnpm apps:parityand synchronize content.
Common Problems
| Problem | Fix |
|---|---|
| Frontmatter validation fails | Use the fields below and an ISO date string |
| Cover is broken | Put the image in the selected app's public/ and use a root-relative URL |
| Post is absent from the listing | Check published and locale file names |
| Draft URL is still reachable | published=false removes listing/sitemap inclusion, not detail-route access; keep private drafts outside the deployed content |
Field Reference
| Field | Value |
|---|---|
title | Article title |
description | Optional metadata description |
date | Required ISO date string |
image | Optional cover URL |
categories | String array, default empty |
published | Boolean, default true |
Schema is in app source.config.ts; src/lib/blog-source.ts builds language URLs and src/components/mdx.tsx maps rich blocks. Edit these only when changing behavior. Paid/private articles need server-side auth and entitlement checks; the default blog does not provide a paid-body gate.