Writing Posts
This guide covers how to write and manage blog posts in Firefly, including Frontmatter configuration, Markdown syntax, math formulas, Mermaid diagrams, embedded videos, and more.
File Location
Post files go in the src/content/posts/ directory. You can place .md / .mdx files directly or create subdirectories to organize posts and assets.
src/content/posts/
├── post-1.md
├── post-2/
│ ├── cover.png
│ └── index.md
└── category/
└── post-3.mdFront-matter
Each post starts with YAML front-matter to define metadata:
---
title: My First Post
published: 2025-01-01
description: A short description of the post
image: ./cover.jpg
tags: [Frontend, Development]
category: Frontend
draft: false
---Full Property List
| Property | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Post title |
published | date | Yes | Publish date |
updated | date | No | Update date, defaults to publish date |
description | string | No | Short description shown on post cards |
image | string | No | Cover image path |
tags | string[] | No | Post tags |
category | string | No | Post category |
draft | boolean | No | Draft status, drafts are not visible |
pinned | boolean | No | Pin to top of post list |
slug | string | No | Custom URL path |
lang | string | No | Language code (e.g. zh-CN), only set when different from site default |
author | string | No | Post author |
comment | boolean | No | Enable comments, default true |
licenseName | string | No | Custom license name |
licenseUrl | string | No | Custom license URL |
sourceLink | string | No | Source/reference link |
password | string | No | Post password. When set, the post will be encrypted. See Post Encryption |
passwordHint | string | No | Password hint displayed above the input field |
Cover Image Path
The image property supports:
- Relative path (relative to the post file):
./cover.jpg - public directory (starts with
/):/assets/images/cover.webp - Remote URL (starts with
http://orhttps://):https://example.com/cover.jpg - Random image API:
api(requirescoverImageConfig.tsconfiguration)
Custom URL (Slug)
By default, the filename is used as the URL. Customize it with slug:
---
title: How to Use Firefly
slug: how-to-use-firefly
---Slug Tips
- Use lowercase English and hyphens:
my-awesome-post - Keep it short and descriptive
- Avoid special characters
- Don't change slugs after publishing to preserve SEO and existing links
Drafts
Set draft: true in front-matter to mark a post as draft. Drafts won't appear on the site:
---
title: Draft Example
draft: true
---Set draft to false when ready to publish.
Math Formulas (KaTeX)
Firefly has built-in KaTeX support for rendering math formulas.
Inline Formulas
Wrap with single $:
Euler's formula $e^{i\pi} + 1 = 0$ is one of the most beautiful equations.Block Formulas
Wrap with $$ for centered display:
$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$Matrices
$$
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
$$Sums and Limits
$$
\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}
$$
$$
\lim_{x \to 0} \frac{\sin x}{x} = 1
$$Chemical Equations
$$
\ce{CH4 + 2O2 -> CO2 + 2H2O}
$$See KaTeX Supported Functions for full syntax reference.
Mermaid Diagrams
Firefly supports Mermaid diagrams, rendered as static SVG at build time. Use mermaid as the code block language. See Mermaid Diagram for configuration and supported types.
Flowchart
```mermaid
graph TD
A[Start] --> B{Condition}
B -->|Yes| C[Step 1]
B -->|No| D[Step 2]
C --> E[End]
D --> E
```Sequence Diagram
```mermaid
sequenceDiagram
participant User
participant Server
User->>Server: Send request
Server-->>User: Return response
```ER Diagram
```mermaid
erDiagram
USER {
int id PK
string username
string email
}
ARTICLE {
int id PK
string title
text content
}
USER ||--o{ ARTICLE : writes
```Class Diagram
```mermaid
classDiagram
class User {
+String name
+login()
+logout()
}
class Article {
+String title
+publish()
}
User "1" -- "*" Article : writes
```State Diagram
```mermaid
stateDiagram-v2
[*] --> Draft
Draft --> Review : Submit
Review --> Published : Approve
Review --> Draft : Reject
Published --> [*]
```XY Chart
```mermaid
xychart-beta
title "Monthly Traffic"
x-axis [Jan, Feb, Mar, Apr, May, Jun]
y-axis "Visits" 0 --> 5000
bar [2500, 3200, 4100, 3800, 4500, 4800]
```Admonitions
Supports GitHub, Obsidian, VitePress, and Docusaurus styles (configured via siteConfig.ts → rehypeCallouts.theme).
GitHub / VitePress Style
> [!NOTE] Note
> Information that users should take into account.
> [!TIP] Tip
> Optional information to help users be more successful.
> [!IMPORTANT] Important
> Crucial information necessary for users to succeed.
> [!WARNING] Warning
> Critical content demanding immediate attention.
> [!CAUTION] Caution
> Negative potential consequences of an action.Docusaurus Style
Supported types: note tip info warning danger
:::note
This is a note.
:::
:::tip
A useful tip.
:::
:::info
General information.
:::
:::warning
A warning.
:::
:::danger
Dangerous operation.
:::
:::tip[Custom Title]
This is a tip with a custom title.
:::TIP
Restart the dev server after changing the admonition theme.
Python-Markdown
Firefly supports Python-Markdown and MkDocs Material admonition syntax (!!! and ??? syntax). Enable it in siteConfig.ts:
// src/config/siteConfig.ts
rehypeCallouts: {
theme: "obsidian", // Recommended for best compatibility
enablePythonMarkdownAdmonitions: true, // Enable Python-Markdown syntax
},Note: Only the obsidian theme fully supports all admonition types.
Basic Syntax
!!! note
This is a note.
!!! tip "Custom Title"
This is a tip with a custom title.
!!! warning
This is a warning.Collapsible Syntax
??? note "Click to expand (closed by default)"
This is collapsed by default.
???+ tip "Click to expand (open by default)"
This is expanded by default.Supported Types
- Standard types:
note,tip,info,warning,danger - Custom types:
custom,success,failure, etc. - Nested admonitions (converted to nested blockquotes)
TIP
Restart the dev server after changing the admonition theme or enabling Python-Markdown syntax.
GitHub Repository Card
Embed a GitHub repository info card (data fetched dynamically from GitHub API):
::github{repo="CuteLeaf/Firefly"}Embedding Videos
Paste iframe embed codes directly in Markdown.
YouTube
<iframe width="100%" height="468"
src="https://www.youtube.com/embed/VIDEO_ID"
title="YouTube video player"
frameborder="0" allowfullscreen>
</iframe>Bilibili
<iframe width="100%" height="468"
src="//player.bilibili.com/player.html?bvid=BV_ID&p=1&autoplay=0"
scrolling="no" border="0" frameborder="no"
framespacing="0" allowfullscreen="true">
</iframe>Spoiler Text
Use :spoiler[] syntax to hide text content (supports Markdown formatting):
Content :spoiler[is hidden **haha**]!MDX Format
Firefly supports both .md (Markdown) and .mdx (MDX) formats. MDX allows importing and using Astro/React components in posts.
Importing Components
import { Icon } from 'astro-icon/components'
<div class="flex items-center gap-2 my-4">
<Icon name="fa7-solid:rocket" class="text-4xl text-red-500" />
<span>Rocket launch!</span>
</div>Using Variables
export const year = new Date().getFullYear()
The current year is {year}.TIP
For most use cases, Markdown is sufficient. Only use MDX when you need to embed JSX components or dynamic data.
