Yet another static site generator based on Next.js
English | 简体中文
Aki-SSG is a static site generator that transforms your markdown contents into a site based on Next.js, with StyleX as Atomic CSS Framework.
- Fork this project to your own repo.
- Clone it to your local space.
- Write your site information in
src/data/site-config.ts. - Run
pnpm installto install dependencies. - Write your articles and pages.
- Run
pnpm devto preview your site. - Run
pnpm buildto build site. - Upload files in
out/directory to your web server. - Set rewrite rules for Nginx or other web server.
- Enjoy it!
You should add this to your virtual host configuration file.
(Only Nginx configuration example will be provided currently)
location / {
try_files $uri $uri.html $uri/ =404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
The site config will be stored in src/data/site-config.ts. This file is fully typed so there will be type hints.
Available configuration:
import { createConfig } from "../utils/createConfig";
export const config: SiteConfig = createConfig({
author: {
name: "Test", // Author name, displayed on the footer and copyright.
email: "test@example.com", // Author email, used to get the gravatar displayed on the navigation bar.
},
blog: {
hostname: "example.com", // The domain of site.
title: "Aki-SSG", // The title of site.
description: "Yet another site generated by Aki-SSG", // The description of site, displayed on the header of site.
favicon: "/favicon.ico", // The site Favicon.
begin_year: 2024, // The beginning year of site, displayed on the footer of the site.
},
style: {
primary_color: "#6db0ec", // The primary color of site.
header_image: "https://blog-oss.allenyou.top/image/658ad4c208349.png", // The header image of site.
header_image: { // Or you can use this to set different images for light or dark mode.
default: "https://blog-oss.allenyou.top/image/658ad4c208349.png", // Light mode
dark: "https://blog-oss.allenyou.top/image/658ad4c208349.png", // Dark mode
},
},
comment: { // Comment configuration.
enabled: "disable", // Disable comment.
},
comment: { // Or set it to enable waline comment.
enabled: "waline",
waline_api: ""
},
optimize: { // Some optimization configuration.
gravatar_mirror: "https://gravatar.com/avatar/", // Gravatar mirror to use.
cdn_prefix: "", // Optional, the cdn url prefix of your static assets. (Refers to assetPrefix config in next.config.ts)
// If not set, static assets will be imported locally.
thumb_query: "", // Optional, the part appended to the thumb image url refered in the posts and pages.
// When the image is not fully loaded, the low resolution thumbnails will be displayed.
// If not set, none of thumb will be displayed.
},
enhanced_markdown: { // Some enhanced markdown features.
shuffle_friend_links: true, // Whether to shuffle friend links on each build time.
},
follow: { // Folo configurations. Informations for Folo subscription claim will be included in RSS.
user_id: "xxxxx"; // User ID used during Folo subscription claim.
feed_id: "xxxxx"; // Feed ID used during Folo subscription claim.
},
extra_links: [ // External links added to navigation bar
{
title: "Example", // Title of external link
url: "https://example.com" // URL of external link
}
]
};);The pages and articles will be written in Aki-SSG Flavored Markdown and saved as .md files. Some information can be described in the front matter part of file(the part quoted with --- before the body of file, written in YAML format)
Pages should be saved as .md files in src/data/pages/ directory. Each file corespond to a page.
The file should be like:
---
slug: example
title: "Example page"
enable_comment: false
allow_index: true
navigation_title: "Page"
navigation_index: 1
draft: false
---
The content to be displayed on the page should be written in markdown here.
And attributes in the front matter should be like:
| Attribute Name | Description |
|---|---|
| slug | Describes the URL of this page. For example, if it is set to example, then the URL of this page will be /example. |
| title | Describes the title of this page. |
| enable_comment(Optional) | A boolean value, describes whether comments will be enabled on this page. Default value is false. |
| allow_index(Optional) | A boolean value, describes whether spiders be allowed to index this page in robots.txt. Default value is false. |
| navigation_title(Optional) | Describes the link content direct to this page shown on the navigation bar. If is left blank, there will be no navigation link to this page. |
| navigation_index(Optional) | An integer, describes the order in which it appears in the navigation bar(in ascending order). Default value is 0. |
| draft(Optional) | A boolean value, describes whether this page is an draft. Drafts will be visiable only in dev preview. Default value is false. |
Articles should be saved as .md files in src/data/posts/ directory. Each file corespond to an article.
The file should be like:
---
id: 1
title: "Hello, World!"
description: 这是一篇测试文章
created_at: "2024-10-04"
modified_at: "2024-10-04"
draft: false
---
The content of this article should be written in markdown here.
And attributes in the front matter should be like:
| Attribute Name | Description |
|---|---|
| id | A unique integer, be used to identify this article. The URL of this article would be /posts/:id |
| title | Describes the title of this article. |
| created_at | Describes the date and time of the last time this article be created. |
| modified_at | Describes the date and time of the last time this article be modified. |
| description(Optional) | Describes the abstract description of this article. If is left blank, "没有描述" will be used by default. |
| draft(Optional) | A boolean value, describes whether this article is an draft. Drafts will be visiable only in dev preview. Default value is false. |
The friend links will be saved in src/data/friend-link.ts. This file is fully typed so there will be type hints.
The file will be like:
export const friend_link_list: FriendLink[] = [
{
// The name of friend link
title: "Example Friend Link",
// The URL of friend link
url: "https://example.com",
// The description of friend link
description: "This is an example friend link.",
// The avatar image of friend link (Optional)
// If not set, a default avatar will be used by default.
avatar: "",
},
];With unified, Aki-SSG uses a extended markdown as richtext standard.
Despite standard markdown grammar, you can use syntaxes below to make your content more colorful!
Aki-SSG supports GitHub Flavored Alerts.
> [!NOTE]
> Highlights information that users should take into account, even when skimming.
> [!TIP]
> Optional information to help a user be more successful.
> [!IMPORTANT]
> Crucial information necessary for users to succeed.
> [!WARNING]
> Critical content demanding immediate user attention due to potential risks.
> [!CAUTION]
> Negative potential consequences of an action.Aki-SSG Flavored Markdown supports grammars from GFM completely.
Aki-SSG uses MathJax to render LaTex expressions.
Use $ Expression $ to insert an inline expression.
Or use syntax below to insert a block expression.
$$
Expression
$$Aki-SSG supports Generic directives/plugins syntax as extension. Here are available directives:
Use ::bilibili{bvid="" cid=""} to embed the Bilibili video player.
| Parameter | Description |
|---|---|
| bvid | The BV ID for the video to embed. |
| cid(Optional) | The episode id for the video to embed. |
Use ::friend_links to insert a friend link list.
The friend links will be loaded from src/data/friend-link.ts
Every chat should be wrapped by :::chat and :::.
Inside a chat, use ::chat_sender{name="Name" avatar="Avatar URL" self} to define a chat participant.
| Parameter | Description |
|---|---|
| name | The displayed name of participant. |
| avatar(Optional) | The URL of avatar image displayed for participant. If not defined, a default avatar with the first character of the name of participant will be used. |
| self(Optional) | If set, the message of this participant will be displayed on the right. |
If participants are defined repeatedly, the later definition will override the earlier definition.
Use ::chat_item[Text]{name="Name" avatar="Avatar URL" self} to define a message in chat.
| Parameter | Description |
|---|---|
| name | The displayed name of participant. If this participant has been defined by using ::chat_sender, the defined parameter will be |
| avatar(Optional) | The URL of avatar image displayed for participant. If not defined, a default avatar with the first character of the name of participant will be used. |
| self(Optional) | If set, the message of this participant will be displayed on the right. |
It should be noted that participants defined by ::chat_sender has the highest priority. When conflict appears, parameters set ::chat_item will be overrided.
Use :meme{group="" mid=""} to insert a meme.
| Parameter | Description |
|---|---|
| group | The group name of meme. |
| mid | The id of the meme. |
If the optimize.meme_base_url item in config is not set, a warning will be displayed instead of meme.
The meme will be displayed as an inline image with 20% scale, loaded from ${optimize.meme_base_url}${group}/${mid}.
The RSS Feed file will be saved in /feed.xml.
The Sitemap file will be saved in /sitemap.xml.
The robots.txt file will be saved in /robots.txt.
The design of this project is imitated from tcdw/koi. Thanks for @tcdw's work!