Skip to content

Writing Posts

satnaing edited this page Jun 6, 2026 · 1 revision

Writing Posts

Table of Contents

Creating a Post File

Create a .md or .mdx file inside src/content/posts/. The filename becomes part of the post URL.

src/content/posts/my-first-post.md  →  /posts/my-first-post

MDX (.mdx) files support importing and using Astro/React components inside the content.

Subdirectory Organization

You can organize posts into subdirectories. The subdirectory name becomes part of the URL:

src/content/posts/my-post.md             →  /posts/my-post
src/content/posts/2025/my-post.md        →  /posts/2025/my-post
src/content/posts/_2026/my-post.md       →  /posts/my-post  (underscore prefix strips segment)
src/content/posts/docs/_legacy/guide.md  →  /posts/docs/guide
src/content/posts/Example Dir/Post.md    →  /posts/example-dir/post

Underscore prefix: Directories prefixed with _ are excluded from routing. The subdirectory segment is dropped from the URL. Use this to group posts by year or category without affecting URLs, or to store draft files out of the way.

Frontmatter Reference

Frontmatter is YAML at the top of the file, between --- delimiters.

Field Type Required Default Description
title string Yes Post title. Used as the <h1> heading and in meta tags.
description string Yes Short post description. Used in post excerpts and SEO meta.
pubDatetime Date (ISO 8601) Yes Publication date and time in ISO 8601 format.
modDatetime Date (ISO 8601) No null Last modified date. Only add when the post has been edited after publication.
author string No site.author Post author name. Overrides the global default.
featured boolean No false Display this post in the "Featured" section on the home page.
draft boolean No false Mark as draft. Draft posts are not included in the build output.
tags string[] No ["others"] Array of tags for the post.
ogImage string or image path No dynamic or site.ogImage OG image for social sharing. Can be a relative image path (processed by Astro) or a remote URL string.
canonicalURL string No auto Absolute canonical URL for duplicate-content scenarios (e.g. cross-posting).
hideEditPost boolean No false Hide the "Edit page" link for this specific post, overriding the global features.editPost config.
timezone string No site.timezone IANA timezone for this post's date display. Overrides the global site.timezone for this post only.

Only title, description, and pubDatetime are required.

Tip: Get an ISO 8601 datetime string by running new Date().toISOString() in the browser console.

Sample Frontmatter

---
title: My Example Post
description: A short description of what this post is about.
pubDatetime: 2025-06-01T10:00:00Z
modDatetime: 2025-06-05T08:30:00Z
author: Your Name
featured: false
draft: false
tags:
  - tutorial
  - astro
ogImage: ../../assets/images/my-post-cover.jpg
canonicalURL: https://yourotherblog.com/original-post
---

Table of Contents in Posts

To include a table of contents, add a level-2 heading ## Table of contents where you want it to appear:

---
# frontmatter
---

Intro paragraph here.

## Table of contents

## First Section

...

The TOC is rendered as a collapsible section and is automatically generated from the headings in the post.

Headings

The post title from frontmatter serves as the <h1>. Use h2 through h6 (## to ######) for all headings inside the post body. This is not enforced but is recommended for visual consistency, accessibility, and SEO.

Callouts

AstroPaper supports callouts via rehype-callouts (Obsidian-style syntax), available since v6.1.

> [!NOTE]
> Supplementary information.

> [!TIP]
> Helpful advice.

> [!WARNING]
> Something that could go wrong.

> [!DANGER]
> Serious risk.

> [!INFO]
> Neutral context.

> [!SUCCESS]
> Confirmation that something worked.

Collapsible callouts

Add - after the type to collapse by default, or + to expand but allow collapsing:

> [!WARNING]- Collapsed by default
> This content is hidden until expanded.

> [!TIP]+ Expanded, but collapsible
> Starts open and can be collapsed.

Custom titles

> [!NOTE] Did you know?
> The text after the type becomes the callout heading.

Full list of supported types: NOTE, ABSTRACT, INFO, TODO, TIP, SUCCESS, QUESTION, WARNING, FAILURE, DANGER, BUG, EXAMPLE, QUOTE. Many accept aliases (e.g. HINT for TIP, CAUTION for WARNING).

Syntax Highlighting

AstroPaper uses Shiki with the min-light (light) and night-owl (dark) themes. The following transformers are active:

  • Filename/title label — add file="filename" to a code fence:

    ```ts file="src/config.ts"
    const x = 1;
    ```
  • Highlighted lines// [!code highlight] on a line

  • Diff lines// [!code ++] and // [!code --]

  • Word highlights// [!code word:text]

Images

Option 1: src/assets/ (recommended)

Images in src/assets/ are processed and optimized by Astro's Image Service.

![alt text](@/assets/images/example.jpg)

<!-- or relative path -->

![alt text](../../assets/images/example.jpg)

Note: <img> tags and the <Image> component do not work in plain .md files. Use MDX if you need component-based images with custom styles.

Option 2: public/

Images in public/ are served as-is without optimization. Use absolute paths:

![alt text](/assets/images/example.jpg)

OG image recommendations

The recommended OG image size is 1200×640 px. Compress images before adding them (tools: TinyPNG, TinyJPG).

If no ogImage is specified in frontmatter, AstroPaper generates one dynamically (when features.dynamicOgImage is enabled).

VS Code Snippets

AstroPaper ships with workspace snippets in .vscode/astro-paper.code-snippets:

  • frontmatter — inserts the recommended frontmatter block
  • template — inserts a basic post template including a TOC heading

These are automatically available when you open the project in VS Code or Cursor.

Clone this wiki locally