Convert Hugo Front Matter Without Risking Your Content Tree
Convert a Hugo site's front matter with hugo convert and you can rewrite every content file at once, so start with a safe copy. This guide converts front matter to JSON, TOML or YAML into a separate directory, leaving the working site untouched until you have checked the result. The examples match Hugo 0.123.7, the version installed on this machine. Allow about 15 minutes for a small site, plus time to review the diff.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell, a readable Hugo project and enough free space for a second copy of its content tree. This command works on content front matter only: it is not a general converter for Hugo configuration files, templates or rendered output, and it normally needs no elevated privilege.
1. Check the installed command and project
Start by confirming the executable and version. This catches the common distraction where a shell is using a different Hugo binary from the one you expected:
$ command -v hugo
/usr/bin/hugo
$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2026-03-17T19:51:14Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3+esm2
Set the source to the project root, not to one Markdown file. Check that its content directory exists and that you can read it:
$ source_dir=/path/to/my-hugo-site
$ test -d "$source_dir/content" && echo 'content directory found'
content directory found
$ find "$source_dir/content" -type f | head
The subcommands are named toJSON, toTOML and toYAML. They convert all front matter in the content directory, so there is no input-file argument for selecting just one page.
2. Choose a different output directory
Use --output for the first run. Hugo writes the converted content beneath that directory, preserving paths such as content/posts/example.md. The output directory must not be the source directory:
$ output_dir=/tmp/hugo-front-matter-json
$ hugo convert toJSON \
--source "$source_dir" \
--output "$output_dir"
processing 12 content files
On the installed version, a different output path permits the operation without --unsafe. The source project remains unchanged. Hugo may create its normal build lock in the source while it runs; it is not a converted content file.
Checkpoint
Confirm that the result contains content files and that the source still has its original front matter delimiters:
$ find "$output_dir/content" -type f | head
/tmp/hugo-front-matter-json/content/about.md
/tmp/hugo-front-matter-json/content/posts/example.md
$ sed -n '1,12p' "$output_dir/content/posts/example.md"
{
"date": "2026-09-24T10:00:00Z",
"draft": false,
"title": "Example post"
}
Post body goes here.
$ sed -n '1,5p' "$source_dir/content/posts/example.md"
+++
title = "Example post"
Formatting and key order can change during conversion, so treat the output as a generated candidate, not a byte-for-byte copy. Hugo does not copy the whole project into --output; keep your configuration, layouts and assets in the original project while reviewing the converted content.
3. Convert to TOML or YAML instead
Run the same workflow with the target subcommand changed. Use a fresh output directory for each comparison so one result cannot be mistaken for another:
$ hugo convert toTOML \
--source "$source_dir" \
--output /tmp/hugo-front-matter-toml
processing 12 content files
$ hugo convert toYAML \
--source "$source_dir" \
--output /tmp/hugo-front-matter-yaml
processing 12 content files
- TOML front matter is enclosed by
+++. - YAML front matter is enclosed by
---. - JSON front matter is an object at the start of the file.
The body remains after the converted front matter in every case. If the count is not what you expect, stop and inspect the source tree before copying anything back. Do not confuse these commands with Hugo's output formats: toJSON changes front matter syntax, it does not build JSON pages or select a template output.
4. Review before replacing content
Compare the converted tree with the source using a tool that understands your files. If the project is in Git, a useful review is to copy only the changed converted files into a disposable branch or worktree and inspect the diff. Do not overwrite the live content directory merely to obtain a diff.
$ find "$output_dir/content" -type f | sort | wc -l
12
$ grep -RIn '^\(+++\|---\|{$\)' "$output_dir/content" | head
/tmp/hugo-front-matter-json/content/about.md:1:{
/tmp/hugo-front-matter-json/content/posts/example.md:1:{
$ hugo --source "$source_dir" --destination /tmp/hugo-preview
The last command is an optional build check against the original project. It does not prove that every metadata value has the meaning you intended, so inspect dates, booleans, arrays, nested objects and multiline strings in the converted files. A parser can produce valid syntax while a review still catches an unwanted type or value change.
Keep the original source and the converted output until a build and representative page review pass. If the converted tree has missing files or unexpected values, discard that temporary output directory through your normal file-management process and rerun with a new empty destination. Do not use sudo to work around a path or permission mistake; fix ownership or choose a directory you can write.
5. Use in-place conversion only with a backup
Hugo refuses an in-place conversion unless you explicitly add --unsafe. That flag allows the command to rewrite content under the source project, and the manual tells you to back up first:
$ cp -a "$source_dir/content" "$source_dir/content.backup-before-hugo-convert"
$ hugo convert toYAML \
--source "$source_dir" \
--unsafe
processing 12 content files
Warning
This changes every convertible content file under the source content directory. Shell redirection is not involved, but the rewrite is still a state-changing operation. Check your backup and make sure no editor, build job or deployment process is writing the same tree.
Without --unsafe, an in-place attempt fails with an error like this and leaves the front matter unchanged:
Error: command error: Unsafe operation not allowed, use --unsafe or set a different output path
If the result is wrong and the conversion is the only change, restore from the backup after stopping any process that might write the tree:
$ mv "$source_dir/content" "$source_dir/content.failed-conversion"
$ mv "$source_dir/content.backup-before-hugo-convert" "$source_dir/content"
$ hugo --source "$source_dir" --destination /tmp/hugo-recovery-check
Recovery
Do not run those mv commands if the directory contains work made after the conversion. Preserve it, compare the backup and current tree, and resolve the files deliberately. The backup directory can be removed only after the build and content review are complete.
Common traps
- Hugo is not found: install or select Hugo through your normal system-management process, then rerun
command -v hugo. This guide does not require root for conversion once the command is installed. - The source has no content files: check
--sourceand the project layout. The command operates on the content directory, not an arbitrary directory of documents. - The command says the operation is unsafe: use a genuinely different
--outputpath for a review run, or stop and make a verified backup before choosing--unsafe. - Output is syntactically valid but pages look wrong: compare representative front matter values and run a Hugo build. Pay particular attention to dates, booleans, lists and multiline text.
- A destination already contains a previous trial: choose a new empty temporary path. A stale output tree makes file counts and reviews harder to trust.
Done means
- Identified the installed Hugo version and the source project.
- Converted the content front matter into a separate output tree with the chosen subcommand.
- Checked the output file count, delimiters and representative values.
- Passed a Hugo build or equivalent site review before any replacement.
- Backed up any in-place conversion, with the original content still recoverable.