8 mins
1596 words
Loading views
Posts Page Config

Complete Posts configuration: fields, list styles, post metadata layouts, OG image handling, frontmatter examples, markdown syntax, and expressive-code config.

The following files are compatible with this document:

  • src/pages/posts/[...id].astro - post specific content display page.
  • src/pages/posts/[...page].astro - post list page.
  • src/content/posts - posts collection
  • src/content.config.ts - posts dataset and frontmatter configuration.
  • ec.config.mjs - expressiveCode config.
  • plugins/index.ts - remark and rehype plugins.
  • src/config.ts - posts page config.
  • src/components/posts - most of the components come from here.

Posts Page Configh3

The posts page config is configured in the following code:

config.ts
export const POSTS_CONFIG: PostConfig = {
title: 'Posts',
description: 'Posts by Dnzzk2',
introduce: 'Here, I will share the usage instructions for this theme to help you quickly use it.',
author: 'Dnzzk2',
homePageConfig: {
size: 3,
type: 'compact',
},
postPageConfig: {
size: 10,
type: 'minimal',
},
tagsPageConfig: {
size: 10,
type: 'time-line',
},
ogImageUseCover: false,
postType: 'metaOnly',
imageDarkenInDark: true,
readMoreText: 'Read more',
prevPageText: 'Previous',
nextPageText: 'Next',
tocText: 'On this page',
backToPostsText: 'Back to Posts',
nextPostText: 'Next Post',
prevPostText: 'Previous Post',
recommendText: 'REC',
}

There are a few configuration attributes, please refer to the table below for details.

PropertyDescription
titleTitle displayed on browser tags and title displayed on list pages.
descriptionThe metadata description in the head element of the list page.
introduceThe introduce below the title on the list page.
authorThe author of the posts.
homePageConfigreadme page configuration.
    sizeThe number of posts displayed on the readme page.
    typeIn the read page, the style of displaying data in a list , compactminimaltime-line or image.
    coverLayout
    (optional)
When the type is image, this attribute can set the position of the image in the card. You can choose left or right. If not set, it will appear alternately on the left and right.
postPageConfigSame as homePageConfig above, but size represents the base number of pages and is used for post pages.
tagsPageConfigSame as homePageConfig above, but size represents the base number of pages and is used for tag pages.
ogImageUseCoverWhether to use the cover image as the Open Graph image.
postTypeThe default display component for the top metadata of the post’s specific content display page.You can configure metaOnlycoverSplitcoverTop.
Can be replaced by frontmatter settings for content.
imageDarkenInDarkWhether to darken the image in the dark mode.
readMoreTextThe text of the read more button.
prevPageTextThe text of the previous page button.
nextPageTextThe text of the next page button.
tocTextTitle text of the directory
backToPostsTextThe text of the back to posts button.
nextPostTextThe text of the next post button.
prevPostTextThe text of the previous post button.
recommendTextThe text of the recommend tag.

Type & PostTypeh4

In the above document, we mentioned configurable types for configuring the display style of list data on the readme page, posts page, and tags page, as well as configurable postTypes for displaying metadata at the top of the posts content page.

Here is the specific style display of type:

compact
time-line
minimal
image

Here is the specific style display of postType:

metaOnly
coverTop
coverSplit

Frontmatterh3

After discussing the external list and overall design of the post, let’s take a look at the content of the post together. These contents are all in the src/content/posts folder.

Below is the frontmatter of the post content:

post.md
---
title: 'Litos: Posts Page Config'
description: ''
pubDate: 2025-08-13
author: 'Dnzzk2'
recommend: true
tags: ['Litos', 'Documentation']
---

You can configure the frontmatter of the post content in the following code:

content.config.ts
const posts = defineCollection({
loader: glob({
pattern: '**/*.{md,mdx}',
base: './src/content/posts',
}),
schema: ({ image }) =>
z
.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
tags: z.array(z.string()).optional(),
updatedDate: z.date().optional(),
author: z.string().default(POSTS_CONFIG.author),
cover: image().optional(),
ogImage: image().optional(),
recommend: z.boolean().default(false),
postType: z.custom<PostType>().optional(),
coverLayout: z.custom<CoverLayout>().optional(),
pinned: z.boolean().default(false),
draft: z.boolean().default(false),
})
.transform((data) => ({
...data,
ogImage: data.ogImage ? data.ogImage : POSTS_CONFIG.ogImageUseCover && data.cover ? data.cover : undefined,
})),
})
PropertyDescription
titleTitle of the post.
descriptionOverview of the content of the post, also used for SEO.
pubDatePost release date.
tagsList of tags for posts
updatedDateLatest update date of the post.
In the sorting of the post list, the priority value is greater than the publication date.
authorThe author of the post.
coverWhen the type of the list is image, the cover image used for display, or the cover image displayed at the top of the postType coverSplit or coverTop
ogImageThe Open Graph image of the post.
recommendWhether to display the recommend tag.
postTypeThe display component for the top metadata of the post’s specific content display page. You can configure metaOnlycoverSplitcoverTop
coverLayoutWhen the type is image, this attribute can set the position of the image in the card. You can choose left or right. If not set, it will appear alternately on the left and right.
pinnedWhether to top the post.
draftWhether to hide the post.
TIP

Regarding cover and ogImage.

Cover and ogImage are two independent attributes, and the only one that can connect them is POSTS_CONFIG.ogImageUseCover.

POSTS_CONFIG.ogImageUseCover is enabled by default, so you only need to write cover to configure ogImage at the same time. This applies to situations where the cover and ogImage are the same. If you want to customize ogImage, you can set it separately.

If POSTS_CONFIG.ogImageUseCover is not enabled, ogImage needs to be set separately. If you do not set it, the site’s ogImage will be used as a fallback.

POSTS_CONFIG.ogImageUseCover > cover


Syntax and Code Styleh3

This guide will show you how to format text using Markdown through a 3-day city trip itinerary. Learn Markdown while planning your journey!

Heading Levelsh4

For travel notes, multiple heading levels help organize days, time blocks, and tips:

# 3-Day City Trip Itinerary
## Day 1: Arrival & Old Town
### Morning Plan
#### Coffee Stops
##### Metro Tips
###### Notes

Text Formattingh4

When writing travel notes, highlight important info:

Must-see spots should be bold Flexible time uses italics Critical cautions can use both Optional detours use strikethrough

**Must-see spots** should be bold
_Flexible time_ uses italics
**_Critical cautions_** can use both
~~Optional detours~~ use strikethrough

Packing List (Unordered List)h4

  • Passport, visa
  • Camera, extra battery
    • Bring a fast charger
    • Spare SD card
  • Refillable water bottle
  • Public transport card
- Passport, visa
- Camera, extra battery
- Bring a fast charger
- Spare SD card
- Refillable water bottle
- Public transport card

Day 1 Schedule (Ordered List)h4

  1. Airport → hotel check-in
  2. Old Town walking tour
  3. Evening river cruise
    1. Arrive 15 min early
    2. Queue at Gate B
    3. Window seats recommended
1. Airport → hotel check-in
2. Old Town walking tour
3. Evening river cruise
1. Arrive 15 min early
2. Queue at Gate B
3. Window seats recommended

Blockquotesh4

Traveler tip: Buy a 24‑hour metro pass if you plan 3+ rides in a day.

Save the hotel address in offline maps for quick access.

> Traveler tip: Buy a 24‑hour metro pass if you plan 3+ rides in a day.
>
> Save the hotel address in offline maps for quick access.

Code Blocksh4

Use simple code to estimate budget:

itinerary.ts
type Budget = { flight: number; hotel: number; meals: number; transport: number }
export const total = (b: Budget) => b.flight + b.hotel + b.meals + b.transport
console.log(total({ flight: 1200, hotel: 450, meals: 180, transport: 60 })) // 1890

Tablesh4

Sample schedule:

TimePlaceNotes
09:00Old Town SquareGuided walking tour
12:30Riverside CafeLunch + short rest
18:00City PierSunset cruise

More tips: Official Tourism Board

Trip photo: City skyline

Horizontal Ruleh4


Inline Codeh4

Metro line A runs every 5-7 minutes during peak hours.

Math Formulash4

Daily budget estimation: budget=hotel+meals+transportbudget = hotel + meals + transport

Total trip:

Total Budget=d=13(Hoteld+Mealsd+Transportd)Total\ Budget = \sum_{d=1}^{3} (Hotel_d + Meals_d + Transport_d)

Task Listsh4

Pre-trip checklist:

  • Book flights
  • Reserve hotel
  • Buy metro pass
  • Download offline maps

Footnotesh4

This itinerary draws on local travel guides(click to the footnote) 1.


Expressive-code configh3

In Markdown documents, we use code blocks to display code snippets and other content. This document explains how to customize the code block configuration.

The code blocks in this theme are configured using Expressive Code with all configuration options defined in the ec.config.mjs file. Below is the main configuration options:

ec.config.mjs
import { defineEcConfig } from 'astro-expressive-code'
import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections'
import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
export default defineEcConfig({
defaultLocale: 'zh-CN',
defaultProps: {
wrap: false,
collapseStyle: 'collapsible-auto',
showLineNumbers: false,
preserveIndent: true,
},
minSyntaxHighlightingColorContrast: 0,
styleOverrides: {
uiFontFamily: 'GeistMono, Input Mono, Fira Code, ShangguSansSCVF, monospace',
uiFontSize: '1em',
codeFontFamily: 'GeistMono, Input Mono, Fira Code, ShangguSansSCVF, monospace',
codeFontSize: '14px',
codeLineHeight: '1.4',
borderRadius: '0',
codePaddingBlock: '0.8571429em',
codePaddingInline: '1.1428571em',
borderColor: ({ theme }) => (theme.type === 'dark' ? '#24273a' : '#e6e9ef'),
frames: {
frameBoxShadowCssValue: false,
inlineButtonBackgroundActiveOpacity: '0.2',
inlineButtonBackgroundHoverOrFocusOpacity: '0.1',
},
textMarkers: {
backgroundOpacity: '0.2',
borderOpacity: '0.4',
},
},
plugins: [
pluginCollapsibleSections({
defaultCollapsed: false,
}),
pluginLineNumbers(),
],
themes: ['catppuccin-macchiato', 'catppuccin-latte'],
themeCssSelector: (theme) => (theme.name === 'catppuccin-macchiato' ? '.dark' : ':root:not(.dark)'),
useDarkModeMediaQuery: false,
useStyleReset: false,
})

You can go to the website to view the configuration options of expressive-code.


Comment System (Gitalk)h3

The theme has a built-in Gitalk comment system that uses GitHub Issues as the comment backend. Each post automatically gets its own issue for comments.

Prerequisitesh4

You need to create a GitHub OAuth App first:

  1. Go to GitHub Developer SettingsOAuth AppsNew OAuth App.
  2. Fill in the form:
    • Application name: Any name (e.g. My Blog Comments)
    • Homepage URL: Your site URL (e.g. https://yourdomain.com)
    • Authorization callback URL: Same as your site URL
  3. After creation, copy the Client ID and generate a Client Secret.
  4. Create a public repository on GitHub to store comment issues (e.g. blog-comments).

Configurationh4

Configure the comment system in src/config.ts:

config.ts
export const COMMENT_CONFIG: CommentConfig = {
enabled: true,
system: 'gitalk',
gitalk: {
clientID: import.meta.env.PUBLIC_GITHUB_CLIENT_ID,
clientSecret: import.meta.env.PUBLIC_GITHUB_CLIENT_SECRET,
repo: 'blog-comments',
owner: 'YourGitHubUsername',
admin: ['YourGitHubUsername'],
language: 'en-US',
perPage: 5,
pagerDirection: 'last',
createIssueManually: false,
distractionFreeMode: false,
enableHotKey: true,
},
}

Then set the environment variables. Create a .env file in the project root (refer to .env.example):

.env
PUBLIC_GITHUB_CLIENT_ID=your-github-client-id
PUBLIC_GITHUB_CLIENT_SECRET=your-github-client-secret

Config Propertiesh4

PropertyDescription
enabledWhether to enable the comment system.
systemComment system to use. Options: gitalk, none.
clientIDGitHub OAuth App Client ID.
clientSecretGitHub OAuth App Client Secret.
repoThe GitHub repository name for storing comment issues.
ownerThe GitHub username of the repository owner.
adminArray of GitHub usernames who can initialize comment issues.
languageDisplay language. e.g. en-US, zh-CN, zh-TW.
perPageNumber of comments per page.
pagerDirectionComment sorting direction. last (newest first) or first (oldest first).
createIssueManuallyIf true, issues must be created manually. If false, auto-created on first visit by admin.
distractionFreeModeIf true, enables full-screen overlay when typing a comment.
enableHotKeyWhether to enable Cmd/Ctrl + Enter shortcut to submit comments.
NOTE

To disable comments entirely, set enabled: false or system: 'none' in COMMENT_CONFIG.

CAUTION

The clientID and clientSecret are read from environment variables via import.meta.env. Make sure to add .env to your .gitignore file (already included by default) to avoid leaking secrets.

Footnotesh2

  1. City Tourism Guide, 2024 Edition. (click back to the text)

Comments