Table of contents
Content Authoring
This guide covers writing, structuring, and managing content for all three collections: Blog, Snippets, and Projects.
Content Structure
Each collection entry is a folder with one .mdx file per locale:
src/content/blog/my-post/
├── en.mdx # Required (canonical)
├── pt-br.mdx # Optional
├── ja.mdx # Optional
├── zh-cn.mdx # Optional
├── de.mdx # Optional
└── fr.mdx # Optional
File naming: {locale}.mdx — locale must match the folder name in src/i18n/config.ts.
Frontmatter Reference
Blog Posts (blog)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
title |
string | ✅ | — | Post title (used in <title>, OG, listings) |
description |
string | ✅ | — | SEO meta description, social preview |
publishedDate |
ISO date | ✅ | — | Publication date (sorting, RSS, sitemap) |
updatedDate |
ISO date | ❌ | — | Last modification date (shown in UI) |
locale |
en|pt-br|ja|zh-cn|de|fr |
✅ | — | Must match filename |
tags |
string[] | ❌ | [] |
Topic tags (displayed, filterable) |
draft |
boolean | ❌ | false |
true = hidden in production |
featured |
boolean | ❌ | false |
Highlighted on home page |
includeInRss |
boolean | ❌ | true |
Include in /rss.xml |
showTableOfContents |
boolean | ❌ | false |
Show ToC component |
canonicalSourceLocale |
locale | ❌ | — | If translated, source locale |
translation |
object | ❌ | — | Translation metadata |
Translation metadata:
translation:
sourceLocale: "en"
generatedAt: "2025-01-15T10:30:00Z"
generator: "deepl-cli" # or "gpt-4o", "human", etc.
Snippets (snippets)
Inherits all blog fields, plus:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
category |
string | ✅ | — | Grouping (e.g. "bash", "docker", "vscode") |
stack |
string[] | ❌ | [] |
Tech tags (e.g. ["bash", "linux"]) |
level |
enum | ❌ | — | beginner | intermediate | advanced |
Projects (projects)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | ✅ | — | Project name |
description |
string | ✅ | — | Short description |
locale |
locale | ✅ | — | Must match filename |
status |
enum | ✅ | — | active | maintained | paused | archived | completed | experimental |
category |
string | ✅ | — | Grouping (e.g. "translation", "tool", "infrastructure") |
tags |
string[] | ❌ | [] |
Additional tags |
stack |
string[] | ❌ | [] |
Tech stack |
homepageUrl |
URL | ❌ | — | Project website |
repositoryUrl |
URL | ❌ | — | Source code (GitHub, etc.) |
externalUrl |
URL | ❌ | — | Other relevant link |
featured |
boolean | ❌ | false |
Highlight on projects page |
draft |
boolean | ❌ | false |
Hidden in production |
startDate |
ISO date | ❌ | — | Project start |
endDate |
ISO date | ❌ | — | Project end (if archived/completed) |
canonicalSourceLocale |
locale | ❌ | — | If translated |
translation |
object | ❌ | — | Translation metadata |
Writing Content
MDX Features
All .mdx files support:
- Standard Markdown — headings, lists, links, images, tables, blockquotes
- Code blocks with syntax highlighting (Shiki,
github-dark-defaulttheme) - Components — import and use Astro components inline
- Frontmatter variables —
{frontmatter.title}etc. - HTML — raw HTML when needed
Headings
Important: Do not include a top-level # H1 in content body.
- Page title rendered by layout from
frontmatter.title - Use
## H2for major sections - Use
### H3for subsections
Code Blocks
```bash
# Comment
command --flag value
```
```typescript
function greet(name: string): string {
return `Hello, ${name}!`;
}
```
Features:
- Language detection → copy button with label
- Line highlighting:
```ts {2,4-5} - Filename:
```ts:filename.ts - Copy button uses
dict.common.copyCode/dict.common.copied
Scaffolding New Content
Blog Post
pnpm content:new:post my-post
Prompts for slug (e.g. my-new-post), creates 6 locale files with frontmatter template.
Snippet
pnpm content:new:snippet useful-command
Prompts for slug + category, creates 6 locale files.
Content Validation
Schema Validation (Build-Time)
Zod schemas in src/content.config.ts validate:
- Required fields present
- Types correct (dates, URLs, enums)
- Locale matches filename
- Enum values valid
Run:
pnpm build # includes validation
pnpm check # validation only
Content Consistency Check
pnpm content:check
Checks:
- All published EN entries have at least one translation
- Frontmatter consistency across locales
- No duplicate slugs
- Draft entries not linked
Non-strict validation reports missing translations and exits successfully.
Strict validation fails when a published English entry is missing any of pt-br, ja, zh-cn, de, or fr.
STRICT_I18N=true pnpm content:check
Publishing Checklist
Before setting draft: false:
title— clear, descriptive, < 60 chars for SEOdescription— 150-160 chars, includes keywordspublishedDate— today or past datetags— 3-5 relevant, consistent with existingcategory(snippets) — matches existing or new with intentstatus(projects) — accurate- Code blocks tested, copyable
- Links valid (internal + external)
- Images optimized (WebP, < 200KB)
- Table of Contents enabled if > 3 H2 sections
- Translations complete (or
canonicalSourceLocaleset)