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.
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.
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.
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.
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
+++.---.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.
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.
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.
command -v hugo. This guide does not require root for conversion once the command is installed.--source and the project layout. The command operates on the content directory, not an arbitrary directory of documents.--output path for a review run, or stop and make a verified backup before choosing --unsafe.