Hexo is a fast, simple, and powerful static-site framework powered by Node.js. You write your content in plain text (Markdown by default), and Hexo renders it into a complete static website — posts, pages, archives, categories, and tags — ready to deploy anywhere that serves files.
This guide is for the people who build sites with Hexo: bloggers, writers, documentation authors, and developers who want a fast, file-based publishing workflow. It covers installing Hexo, scaffolding a site, writing content, the full command-line interface, the tag plugins you can drop into your posts, configuration you will touch every day, and how to deploy.
Note
Hexo itself is a framework. It does its job through plugins (renderers, generators, deployers) and themes. A freshly scaffolded Hexo site already wires up the essential plugins for you, so you can write your first post within minutes. Where a feature lives in a separate plugin, this guide says so explicitly.
1. Quick Start
Get from nothing to a running blog in five commands.
# 1. Install the Hexo command-line tool globally
npm install -g hexo-cli
# 2. Scaffold a new site into the folder "blog"
hexo init blog
cd blog
# 3. Install the site's dependencies (theme, markdown renderer, server)
npm install
# 4. Write a new post
hexo new "My First Post"
# 5. Generate the static files and preview locally
hexo generate
hexo server
INFO Validating config
INFO Start processing
INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.
Open http://localhost:4000 in your browser to see your site.
Tip
Most commands have short aliases.
hexo g=hexo generate,hexo s=hexo server,hexo d=hexo deploy. Aliases are resolved by prefix, so any unambiguous abbreviation works (hexo gen,hexo ser).
Important
hexo initandhexo serverare provided by the hexo-cli package and the hexo-server plugin respectively — not by the Hexo core.npm installinside a scaffolded site pulls them in. Ifhexo serverreports an unknown command, runnpm install hexo-server --savein your site folder.
2. Requirements
| Requirement | Detail |
|---|---|
| Node.js | >=20.19.0 (declared in Hexo's engines field; older Node will refuse to install) |
| npm | Ships with Node.js; used to install Hexo, plugins, and themes |
| Git | Optional, but required if you deploy with the Git deployer |
| A terminal | All Hexo workflows are command-line driven |
Hexo runs on Windows, macOS, and Linux. Paths in this guide use forward slashes; Hexo normalizes backslashes internally on Windows.
Note
Hexo (the
hexopackage) is version 8.1.2 as documented here. The command-line launcher is the separatehexo-clipackage — keep both reasonably current.
3. Installation
3.1 Install the command-line tool
The hexo command is provided by hexo-cli. Install it globally so you can scaffold and manage sites from anywhere:
npm
npm install -g hexo-cli
yarn
yarn global add hexo-cli
pnpm
pnpm add -g hexo-cli
Verify the install:
hexo version
hexo-cli: 4.3.2
os: ...
node: ...
3.2 Per-project install (alternative)
If you prefer not to install anything globally, you can run Hexo through npx after scaffolding, or add hexo-cli as a local dev dependency and invoke it with npx hexo <command>. Every Hexo site already lists hexo as a dependency in its own package.json.
Tip
A global
hexo-cliplus a localhexodependency is the recommended setup: the global launcher finds and runs the locally-installed Hexo version, so each site can pin its own Hexo release.
4. Scaffolding and Project Anatomy
4.1 Create a site
hexo init <folder>
cd <folder>
npm install
hexo init clones the default starter (which includes a _config.yml, a basic landscape theme reference, the hexo-renderer-marked Markdown renderer, and hexo-server), then npm install downloads them.
4.2 What's in a Hexo site
.
├── _config.yml # Site configuration (the file you edit most)
├── package.json # Site dependencies (Hexo, theme, plugins)
├── scaffolds/ # Templates for `hexo new`
│ ├── draft.md
│ ├── page.md
│ └── post.md
├── source/ # Your content lives here
│ ├── _posts/ # Published posts (Markdown files)
│ ├── _drafts/ # Unpublished drafts (optional)
│ └── _data/ # Site-wide data files (optional)
├── themes/ # Installed themes (or installed via npm)
├── public/ # Generated output (created by `hexo generate`)
└── db.json # Cache of processed source (created at runtime)
| Folder / file | What it is | You edit it? |
|---|---|---|
_config.yml |
The site config — title, URL, permalinks, theme, deployment | Yes, often |
source/_posts/ |
Your blog posts, one Markdown file each | Yes |
source/_drafts/ |
Drafts not yet published | Yes |
source/_data/ |
YAML/JSON data available to themes as site.data |
Sometimes |
source/ (other) |
Static assets and standalone pages (copied or rendered) | Sometimes |
scaffolds/ |
Front-matter templates used by hexo new |
Occasionally |
themes/ |
Theme files (layouts, styles) | If theming |
public/ |
Generated HTML — never edit by hand, it is overwritten | No |
db.json |
Runtime cache — safe to delete (hexo clean removes it) |
No |
Warning
Anything under
source/whose path begins with_(like_posts,_drafts,_data) is treated specially and is not copied verbatim topublic/. Files and folders starting with_or.elsewhere are skipped as "hidden" unless you add them to theincludeconfig.
5. Writing Content
Hexo content is plain text with a front-matter block at the top. Front-matter is a small YAML (or JSON) section between --- delimiters that sets the post's metadata.
5.1 Create a post
hexo new "Hello World"
INFO Created: ~/blog/source/_posts/Hello-World.md
This creates source/_posts/Hello-World.md from the scaffolds/post.md template:
---
title: Hello World
date: 2026-06-05 14:30:00
tags:
---
Write your post content here, in Markdown.
5.2 Front-matter reference
These keys are understood by Hexo for posts and pages. Any other key you add becomes a custom variable available to your theme.
| Key | Applies to | Meaning |
|---|---|---|
title |
post, page | The displayed title |
date |
post, page | Creation date/time (controls sort order and permalink tokens) |
updated |
post, page | Last-modified date (see updated_option in config) |
tags |
post | A list of tags (posts only — pages have no tags) |
categories |
post | A list (or nested list) of categories |
layout |
post, page | Which theme layout to render with (post, page, or a custom one) |
permalink |
post, page | Override the generated URL for this single item |
comments |
post, page | true/false to toggle comments (themes honor this) |
excerpt |
post | Explicit excerpt text |
photos |
post | A list of image URLs (used by gallery/photo post styles) |
published |
post | false keeps a post out of the build even from _posts/ |
Note
Singular aliases are accepted and normalized automatically:
tag→tags,category→categories,photo→photos. Use whichever reads better; Hexo converts them.
Tags and categories
---
title: A Categorized, Tagged Post
date: 2026-06-05 10:00:00
categories:
- Tutorials
tags:
- hexo
- markdown
---
Nested (hierarchical) categories — wrap the hierarchy in a sub-list:
categories:
- [Programming, JavaScript] # Programming → JavaScript
Tip
A category named identically to an existing one is reused, not duplicated. Hierarchies are matched by parent:
[Programming, JavaScript]and[Cooking, JavaScript]create two different "JavaScript" categories under different parents.
5.3 Create a page
Pages are standalone (About, Contact) and live at the top of source/, not in _posts/:
hexo new page "about"
INFO Created: ~/blog/source/about/index.md
This produces source/about/index.md, which publishes to /about/.
5.4 Drafts
Drafts let you work on a post without publishing it. Create one and it lands in source/_drafts/:
hexo new draft "Work In Progress"
INFO Created: ~/blog/source/_drafts/Work-In-Progress.md
Drafts are excluded from the build by default. To preview drafts while writing:
hexo server --draft # or set render_drafts: true in _config.yml
When the draft is ready, publish it (moves the file from _drafts/ to _posts/):
hexo publish "Work In Progress"
INFO Published: ~/blog/source/_posts/Work-In-Progress.md
5.5 Post assets (images alongside posts)
By default, images go in source/images/ (or any folder under source/) and are referenced by path. If you prefer to keep each post's images next to the post, enable post asset folders:
# _config.yml
post_asset_folder: true
Now hexo new "My Post" creates both My-Post.md and a My-Post/ folder. Drop images into that folder and reference them with the asset_img tag (see §8).
6. The Command-Line Interface
Run any command from inside your site folder. Below are the commands provided by the Hexo core, followed by global options.
Note
hexo init,hexo version, andhexo helpcome from hexo-cli.hexo servercomes from the hexo-server plugin. The remaining commands below are built into Hexo core.
6.1 Command summary
| Command | Alias | Purpose |
|---|---|---|
hexo init [folder] |
— | Scaffold a new site (from hexo-cli) |
hexo new <title> |
n |
Create a new post, page, or draft |
hexo generate |
g |
Render the site into public/ |
hexo server |
s |
Serve the site locally with live reload (from hexo-server) |
hexo publish <filename> |
p |
Move a draft into _posts/ |
hexo deploy |
d |
Deploy public/ to a remote |
hexo render <file> |
— | Render one or more files with the renderer plugins |
hexo migrate <type> |
— | Import content from another system |
hexo clean |
— | Delete db.json and public/ |
hexo list <type> |
— | List posts, pages, routes, tags, or categories |
hexo config [name] [value] |
— | View or change configuration |
hexo version |
v |
Show version info (from hexo-cli) |
hexo help |
h |
Show help (from hexo-cli) |
6.2 hexo new — create content
hexo new [layout] <title>
| Argument / option | Meaning |
|---|---|
layout |
post (default), page, draft, or any scaffold name |
title |
The post title — wrap in quotes if it contains spaces |
-p, --path |
Custom path for the new file |
-s, --slug |
Custom slug (controls the filename and URL) |
-r, --replace |
Overwrite an existing file with the same name |
hexo new post "Deep Dive into Static Sites"
hexo new page "contact"
hexo new draft "Half-Baked Idea"
hexo new "Quick Note" --slug quick-note
Tip
Any extra front-matter you want pre-filled can be passed as flags. For example
hexo new "Post" --author Janeaddsauthor: Janeto the new file's front-matter (reserved option names like--path,--slug,--replace,--config,--debug,--safe,--silentare excluded).
6.3 hexo generate — build the site
hexo generate
| Option | Meaning |
|---|---|
-d, --deploy |
Deploy automatically after generating |
-f, --force |
Regenerate every file, ignoring the cache |
-w, --watch |
Watch for changes and regenerate incrementally |
-b, --bail |
Throw and stop on the first unhandled error during generation |
-c, --concurrency |
Max number of files generated in parallel (default: unlimited) |
hexo generate --watch # rebuild on every save
hexo generate --deploy # build then deploy
hexo generate --concurrency 5 # cap parallelism on low-memory machines
Note
Generation is incremental and content-hashed. Hexo computes a SHA-1 of each output route and skips writing files whose hash hasn't changed since the last build. Use
--forceto bypass this when you suspect stale output.
6.4 hexo server — local preview
hexo server
Serves the site at http://localhost:4000 and watches your source for changes. Provided by the hexo-server plugin (installed with a scaffolded site).
| Common option | Meaning |
|---|---|
-p, --port |
Port to listen on (default 4000) |
-i, --ip |
Bind address |
-s, --static |
Serve only the already-generated public/ (no watching) |
--draft |
Include drafts in the preview |
Tip
You can enable an in-memory cache for the server so repeated requests skip re-rendering:
# _config.yml server: cache: true
6.5 hexo deploy — publish your site
hexo deploy
| Option | Meaning |
|---|---|
-g, --generate |
Generate before deploying |
--setup |
Run deployer setup only, without deploying |
Deployment requires a deploy block in _config.yml and a deployer plugin. If deploy is unset, Hexo prints the list of available deployer plugins and exits. See §9.
6.6 hexo clean — reset the build
hexo clean
INFO Deleted database.
INFO Deleted public folder.
Removes db.json (the cache) and public/ (the output). Run this whenever a build looks stale, after changing themes, or before a fresh deploy.
6.7 hexo list — inspect your site
hexo list <type>
type is one of: post, page, route, tag, category.
hexo list post # every post with date, title, path
hexo list category # categories and their post counts
hexo list route # every URL the site will generate
6.8 hexo render — render a single file
hexo render <file1> [file2] ...
| Option | Meaning |
|---|---|
--output |
Write the result to a file (otherwise printed to the terminal) |
--engine |
Force a specific render engine |
--pretty |
Pretty-print JSON output |
hexo render data.yml --output data.json --pretty
This runs a file through Hexo's renderer plugins — handy for converting YAML to JSON, or previewing how a Markdown file renders.
6.9 hexo config — view or edit config
hexo config # print the entire merged config
hexo config title # print one value
hexo config title "My Blog" # set a value and write it back to _config.yml
hexo config server.cache true # dotted keys reach nested settings
Note
Values are type-cast:
true/falsebecome booleans, numbers become numbers,null/undefinedbecome those literals, everything else stays a string.
6.10 hexo migrate — import from elsewhere
hexo migrate <type>
Imports content from another blogging system using a migrator plugin (for example hexo-migrator-rss, hexo-migrator-wordpress). Install the matching hexo-migrator-* package first; running hexo migrate with no type lists the installed migrators.
6.11 Global options
These apply to every command:
| Option | Meaning |
|---|---|
--config <path> |
Use a specific config file (or a comma-separated list to merge several) |
--debug |
Verbose logging plus a debug.log in the site root |
--safe |
Safe mode — load no plugins or scripts |
--silent |
Suppress terminal output |
--draft, --drafts |
Include drafts in the run |
hexo generate --config _config.yml,_config.prod.yml # merge configs left→right
hexo server --safe # diagnose a misbehaving plugin
Tip
--safeis the first thing to try when a build breaks after installing a plugin. If the problem disappears in safe mode, a plugin or ascripts/file is the cause.
7. Configuration You'll Use Daily
Configuration lives in _config.yml at the site root. This section covers the settings you touch most; the Admin Guide carries the complete reference with every key and default.
7.1 Site identity
title: My Blog
subtitle: ''
description: ''
keywords:
author: John Doe
language: en
timezone: ''
Warning
Leaving
timezoneempty makes Hexo use your machine's local timezone and prints a warning on every build. Set it explicitly (for exampletimezone: America/New_Yorkortimezone: UTC) to get stable, reproducible dates. A future major version will default to UTC.
7.2 URL and permalinks
url: https://example.com
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:
pretty_urls:
trailing_index: true # keep index.html in URLs
trailing_html: true # keep .html in URLs
The permalink pattern controls post URLs. Available tokens:
| Token | Expands to |
|---|---|
:year :month :day |
4-digit year, 2-digit month, 2-digit day of the post date |
:i_month :i_day |
Month/day without leading zeros |
:hour :minute :second |
Time components |
:title |
The post's slugified filename/title path |
:name |
The filename portion only |
:post_title |
Slugified post title |
:id |
Internal post ID |
:category |
The post's (last) category, or default_category if none |
:hash |
A short hash derived from slug + date |
permalink: posts/:title/ # /posts/my-post/
permalink: :year/:month/:title.html # /2026/06/my-post.html
permalink: :category/:title/ # /tutorials/my-post/
Important
urlmust be a validhttp/httpsURL androotmust be non-empty, or Hexo refuses to build with anInvalid config detectederror. Ifrootis unset, Hexo derives it from the path portion ofurl.
7.3 Directories
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:
skip_render takes glob patterns for files that should be copied verbatim instead of rendered:
skip_render:
- 'README.md'
- 'migration-guide/**'
7.4 Writing behavior
new_post_name: :title.md
default_layout: post
titlecase: false # auto-titlecase post titles
external_link:
enable: true # open external links in a new tab
field: site
exclude: ''
filename_case: 0 # 0=keep, 1=lowercase, 2=uppercase slugs
render_drafts: false
post_asset_folder: false
relative_link: false
future: true # show posts dated in the future
7.5 Dates, pagination, categories, tags
date_format: YYYY-MM-DD
time_format: HH:mm:ss
updated_option: mtime # mtime | date | empty
per_page: 10
pagination_dir: page
default_category: uncategorized
category_map:
tag_map:
7.6 Theme and deployment
theme: landscape
deploy:
type: ''
Change theme to the folder name under themes/ (or the suffix of an installed hexo-theme-* package). See §9 for deploy.
Tip
You can keep a separate theme config in
_config.<theme>.ymlat your site root. Hexo merges it into the theme's own config, so you can customize a theme without editing files insidethemes/.
8. Tag Plugins — Rich Content in Your Posts
Tag plugins are special {% ... %} snippets you put directly in your Markdown. They expand into HTML when the site is generated. Hexo ships the following built-in tags.
Note
Tag-plugin syntax uses Nunjucks/Swig-style braces. If you ever need to show literal
{% %}in your text (for example, in a tutorial), wrap it in a raw block:{% raw %}...{% endraw %}.
8.1 Images
{% img [class names] /path/to/image [width] [height] [title text [alt text]] %}
{% img /images/photo.png 600 400 "A sunset" "sunset over the bay" %}
{% img thumbnail /images/photo.png %}
Aliases: img, image.
8.2 Post asset images and links
When post_asset_folder: true, reference a post's own assets by slug:
{% asset_img slug [width] [height] [title text [alt text]] %}
{% asset_link slug [title] [escape] %}
{% asset_path slug %}
{% asset_img cover.jpg 800 600 "Cover" %}
{% asset_link report.pdf "Download the report" %}
Aliases for the image tag: asset_img, asset_image.
8.3 Links
{% link text url [external] [title] %}
{% link "Hexo docs" https://hexo.io true "Official documentation" %}
Aliases: link, a, anchor.
URL helpers as tags
{% url_for text path [relative] %}
{% full_url_for text path %}
These produce an <a> linking to a site-relative or fully-qualified URL.
8.4 Linking to other posts
{% post_link slug-or-title [display text] [escape] %}
{% post_path slug-or-title %}
{% post_link hello-world %}
{% post_link hello-world "See my first post" %}
post_link produces a full <a> tag; post_path produces just the URL. You can append a fragment: {% post_link my-post#section %}.
Caution
If the referenced post does not exist,
post_linkandpost_paththrowPost not found. Double-check the slug or title.
8.5 Code blocks
The codeblock tag (alias code) renders highlighted code with optional captions and line marking:
{% codeblock [title] [lang:language] [url] [link_text] [options] %}
code snippet
{% endcodeblock %}
| Option | Meaning |
|---|---|
lang: |
Language for highlighting (e.g. lang:python) |
line_number: |
true/false — show line numbers |
first_line: |
First line number |
mark: |
Highlight specific lines: mark:1,4-7,10 |
wrap: |
true/false — wrap in a table |
highlight: |
false to disable highlighting and emit plain escaped code |
{% codeblock Example lang:javascript mark:2 %}
function hello() {
console.log('highlighted line');
}
{% endcodeblock %}
8.6 Include external code
{% include_code [title] [lang:language] path/to/file %}
Pulls a file from your code_dir (default source/downloads/code/) and renders it as a highlighted block with a "view raw" link. Aliases: include_code, include-code.
8.7 Quotes
{% blockquote [author[, source]] [link] [source_link_title] %}
Quote text
{% endblockquote %}
{% blockquote Albert Einstein %}
Imagination is more important than knowledge.
{% endblockquote %}
Aliases: blockquote, quote. A simpler styled variant:
{% pullquote [class] %}
Pulled-out highlighted text.
{% endpullquote %}
8.8 Embeds
{% iframe url [width] [height] %}
{% iframe https://example.com/embed 100% 400 %}
8.9 Tag quick reference
| Tag (and aliases) | Block? | Purpose |
|---|---|---|
img / image |
no | Insert an image |
asset_img / asset_image |
no | Insert a post-asset image by slug |
asset_link |
no | Link to a post asset |
asset_path |
no | Output a post asset's URL |
link / a / anchor |
no | Insert a hyperlink |
url_for |
no | Link to a site-relative path |
full_url_for |
no | Link to a fully-qualified URL |
post_link |
no | Link to another post |
post_path |
no | Output another post's URL |
codeblock / code |
yes | Highlighted code block |
include_code / include-code |
no | Embed a file from code_dir |
blockquote / quote |
yes | Cited blockquote |
pullquote |
yes | Styled pull-quote |
iframe |
no | Embed an iframe |
raw |
yes | Output literal content unprocessed (from Nunjucks) |
9. Deploying Your Site
Hexo deploys via deployer plugins. Configure the deploy block in _config.yml, install the matching plugin, then run hexo deploy.
9.1 Deploy to GitHub Pages (Git deployer)
npm install hexo-deployer-git --save
# _config.yml
deploy:
type: git
repo: https://github.com/<username>/<username>.github.io.git
branch: gh-pages
hexo clean
hexo deploy --generate # build then push
9.2 Multiple deploy targets
deploy can be a list — Hexo runs each target in order:
deploy:
- type: git
repo: https://github.com/me/site.git
branch: gh-pages
- type: rsync
host: example.com
user: deploy
root: /var/www/site
Note
Each entry needs a
typethat names an installed deployer plugin. If a target's deployer isn't installed, Hexo logsDeployer not foundand skips it. Runninghexo deploywith an emptydeployblock prints the deployer plugins you have installed.
9.3 Deploy checklist
- [ ]
urlandrootin_config.ymlmatch your hosting (custom domain or/repo/subpath) - [ ] A deployer plugin is installed and configured
- [ ]
hexo cleanrun before a release build - [ ]
hexo generateproduces the expected files inpublic/ - [ ]
hexo deploy(orhexo deploy --generate) completes withoutDeployer not found
Tip
For static hosts that pull from a Git repo (Netlify, Vercel, Cloudflare Pages, GitHub Actions), you often skip
hexo deployentirely — point the host at your repo and let it runhexo generate, servingpublic/.
10. Extending Your Site with Plugins and Themes
10.1 Installing plugins
Hexo's capabilities come from plugins published on npm under the hexo- prefix. Install them into your site and they load automatically.
npm install hexo-renderer-marked --save # Markdown rendering (default)
npm install hexo-generator-sitemap --save # generate sitemap.xml
npm install hexo-generator-feed --save # generate an RSS/Atom feed
Important
Hexo core does not ship a Markdown renderer or the index/archive/category/tag page generators. A scaffolded site includes
hexo-renderer-markedfor Markdown. For listing pages (the blog index, monthly archives, per-tag and per-category pages) install generator plugins such ashexo-generator-index,hexo-generator-archive,hexo-generator-category, andhexo-generator-tag. Most themes document which generators they expect.
Common plugin categories:
| Plugin type | Examples | What it adds |
|---|---|---|
| Renderer | hexo-renderer-marked, hexo-renderer-pug, hexo-renderer-stylus |
Render Markdown/templates/styles |
| Generator | hexo-generator-index, -archive, -category, -tag, -sitemap, -feed |
Build listing/index/feed pages |
| Deployer | hexo-deployer-git, hexo-deployer-rsync |
Publish to a remote |
| Tag plugin | community packages | New {% %} tags |
Note
Only packages named
hexo-*(or scoped@scope/hexo-*) are auto-loaded, andhexo-theme-*packages are loaded as themes rather than plugins. Hexo skips@types/*packages.
10.2 Installing a theme
Via npm
npm install hexo-theme-<name> --save
# _config.yml
theme: <name>
Via git clone
git clone https://github.com/<author>/<theme>.git themes/<name>
# _config.yml
theme: <name>
A theme placed in themes/<name>/ takes priority over an installed hexo-theme-<name> package of the same name.
10.3 Site scripts
Any .js file you drop in a scripts/ folder at your site root (or in your theme's scripts/ folder) is loaded as a lightweight plugin. This is the quick way to register a custom helper or tag without publishing a package. (Details and the plugin API are in the Admin Guide.)
11. Troubleshooting
Error: Invalid config detected: "url" should be a valid URL!
Cause: url in _config.yml is missing or not a valid http/https address.
Solution: Set url: https://your-domain.com (with the scheme).
Prevention: Always set url and root before your first build.
Error: Post not found: post_link <slug>
Cause: A {% post_link %} or {% post_path %} tag references a post that doesn't exist.
Solution: Use the post's slug (its filename without .md) or its exact title.
Prevention: Run hexo list post to see valid slugs and paths.
Warning: No timezone setting detected!
Cause: timezone is empty, so Hexo falls back to the machine timezone.
Solution: Set timezone: explicitly (e.g. UTC or America/New_York).
Prevention: Pick a timezone when you first configure the site for reproducible dates.
Markdown isn't being rendered (raw # and * appear)
Cause: No Markdown renderer plugin is installed.
Solution: npm install hexo-renderer-marked --save, then hexo clean && hexo generate.
Prevention: Keep the renderer that hexo init installs; don't remove it.
The blog index / archive / tag pages are missing
Cause: Hexo core only generates post, page, and asset routes. Listing pages need generator plugins.
Solution: Install hexo-generator-index, hexo-generator-archive, hexo-generator-category, hexo-generator-tag as needed.
Prevention: Install the generators your theme expects (its README usually lists them).
Changes don't show up after editing
Cause: Stale cache or output.
Solution: Run hexo clean then hexo generate (or hexo generate --force).
Prevention: Use hexo server (which watches) or hexo generate --watch while writing.
Error: Category / Tag has already existed!
Cause: A duplicate category or tag insertion (typically from a buggy plugin or corrupt db.json).
Solution: Run hexo clean to rebuild the database from source.
Prevention: Don't hand-edit db.json.
hexo server reports an unknown command
Cause: The hexo-server plugin isn't installed in this site.
Solution: npm install hexo-server --save.
Prevention: Run npm install after hexo init so all scaffold dependencies are present.
A plugin broke my build
Cause: A faulty plugin or scripts/ file.
Solution: Run with --safe to load no plugins and confirm; then remove or update the offending package.
Prevention: Add plugins one at a time and rebuild after each.
A draft won't appear in preview
Cause: Drafts are hidden by default.
Solution: Run hexo server --draft, or set render_drafts: true, or hexo publish <name> to promote it.
Prevention: Use hexo publish when a draft is ready.
Future-dated posts are missing
Cause: future: false hides posts dated after "now".
Solution: Set future: true (the default) or correct the post date.
Prevention: Check the date in front-matter.
12. Frequently Asked Questions
Q: Do I write posts in Markdown or HTML?
Markdown by default (rendered by hexo-renderer-marked). You can also write HTML, or install other renderers (Pug, AsciiDoc, etc.). Raw HTML inside Markdown is passed through.
Q: How do I change my site's URL structure?
Edit permalink in _config.yml using the tokens in §7.2. Run hexo clean && hexo generate afterward.
Q: Where do images go?
Either in any folder under source/ (e.g. source/images/) referenced by path, or — with post_asset_folder: true — in a folder next to each post, referenced with {% asset_img %}.
Q: How do I preview before publishing?
hexo server builds and serves locally with live reload. Add --draft to include drafts.
Q: What's the difference between a post and a page?
Posts live in source/_posts/, are dated, support tags/categories, and appear in listings. Pages (e.g. About) live elsewhere under source/ and are standalone.
Q: How do I add comments, search, or analytics?
These are theme features or plugins. Check your theme's documentation and _config.<theme>.yml for the relevant options.
Q: Can I use one config for development and another for production?
Yes — hexo generate --config _config.yml,_config.prod.yml merges multiple files left to right into a _multiconfig.yml.
Q: How do I move my drafts and posts between machines?
Everything under source/, plus _config.yml, package.json, scaffolds/, and your theme, is your site. Commit them to Git. public/ and db.json are regenerated and don't need to be tracked.
Q: Why is my build slow on large sites?
Generation is incremental and cached, but the first build of a big site reads and renders everything. Use --concurrency to tune parallelism, and avoid --force unless you need a clean rebuild.
Q: How do I completely reset?
hexo clean removes db.json and public/. Your source is untouched. Then hexo generate rebuilds from scratch.
Q: Is there a server runtime in production?
No. Hexo produces a static public/ folder. hexo server is only for local preview — in production you serve the static files from any web host or CDN.