Here are some rules/recommendations, tips & ticks for creating new posts in AstroPaper blog theme.
Table of contents
Open Table of contents
Creating a Blog Post
To write a new blog post, create a markdown file inside the src/data/blog/ directory.
Starting from AstroPaper v5.1.0, you can now organize blog posts into subdirectories, making it easier to manage your content.
For example, if you want to group posts under 2025, you can place them in src/data/blog/2025/. This also affects the post URL, so src/data/blog/2025/example-post.md will be available at /posts/2025/example-post.
If you don’t want subdirectories to affect the post URL, just prefix the folder name with an underscore _.
# Example: blog post structure and URLs
src/data/blog/very-first-post.md -> mysite.com/posts/very-first-post
src/data/blog/2025/example-post.md -> mysite.com/posts/2025/example-post
src/data/blog/_2026/another-post.md -> mysite.com/posts/another-post
src/data/blog/docs/_legacy/how-to.md -> mysite.com/posts/docs/how-to
src/data/blog/Example Dir/Dummy Post.md -> mysite.com/posts/example-dir/dummy-post
Frontmatter
Frontmatter is the main place to store some important information about the blog post (article). Frontmatter lies at the top of the article and is written in YAML format. Read more about frontmatter and its usage in astro documentation.
Here is the list of frontmatter property for each post.
| Property | Description | Remark |
|---|---|---|
| title | Title of the post. (h1) | required* |
| description | Description of the post. Used in post excerpt and site description of the post. | required* |
| pubDatetime | Published datetime in ISO 8601 format. | required* |
| modDatetime | Modified datetime in ISO 8601 format. (only add this property when a blog post is modified) | optional |
| title | Title of the post. (h1) | required* |
| slug | Slug for the post. This field is optional but cannot be an empty string. ("") | optional |
| featured | Whether or not display this post in featured section of home page | default: false |
| draft | Mark this post ‘unpublished’. | default: false |
| tags | Related keywords for this post. Written in array yaml format. | default: others |
| ogImage | OG image of the post. Useful for social media sharing and SEO. | default: SITE.ogImage or generated OG image |
| canonicalURL | Canonical URL (absolute), in case the article already exists on other source. | optional |
| hideEditPost | To hide Edit Post button in a single post. | default: false |
Only
title,descriptionandpubDatetimefields in frontmatter must be specified.
title and slug will be used for generating the slug automatically. In short, if the slug is not specified, the title of the post will be slugified and used as the slug.
Adding table of contents
By default, a post does not include any table of contents (toc). To include toc, you have to specify it in a specific way.
Write Table of contents in h2 format (## in markdown) and place it where you want it to be appeared in the post.
For instance, if you want to place your table of contents just under the intro paragraph (like I usually do), you can do that in the following way.
---
# some frontmatter
---
Here are some recommendations, tips & ticks for creating new posts in AstroPaper blog theme.
## Table of contents
<!-- the rest of the post -->
Headings
There’s one thing to note about headings. The AstroPaper blog posts use title (title in the frontmatter) as the main heading of the post. Therefore, the rest of the heading in the post should be using h2 ~ h6; not h1.
This rule is not mandatory, but highly recommended for visual, accessibility and SEO purposes.
Storing Images for Blog Content
Here are two methods for storing images and displaying them inside a markdown file.
Note! If it’s a requirement to optimize images in markdown you should use MDX.
Inside src/assets/ directory (recommended)
You can store images inside the src/assets/ directory. These images will be automatically optimized by Astro through Image Service API.
You can use either relative path or alias path (@/assets/) to serve these images.
Example: Suppose you want to display example.jpg whose path is /src/assets/images/example.jpg.

<!-- OR -->

<!-- Using img tag with set dimensions -->
<img src="@/assets/images/example.jpg" alt="something" width="100" height="100">
Technically, you can store images inside any directory under
src. In here,src/assetsis just a recommendation.
Inside public directory
You can store images inside the public directory. Keep in mind that images stored in the public directory are unprocessed by Astro, meaning they will be unoptimized and you need to handle image optimization by yourself.
For these images, you should use an absolute path (starting with /); and these images can be displayed using either markdown notation or HTML img tag.
Example: Assume example.jpg is located at /public/assets/images/example.jpg.

<!-- OR -->
<img src="/assets/images/example.jpg" alt="something" width="100" height="100">
Bonus
Image compression
When you put images in the blog post (especially for images under public directory), it is recommended that the image is compressed. This will affect the overall performance of the website.
My recommendation for image compression sites.
OG Image
The default OG image will be placed if a post does not specify the OG image. Though not required, OG image related to the post should be specified in the frontmatter. The recommended size for OG image is 1200 X 640 px.
Since AstroPaper v1.4.0, OG images will be generated automatically if not specified. Check out the blog post for more info.