Home / Alt manpages / hugo-new-theme(1)

  • hugo-new-theme(1)
  • User command
  • linux

Scaffold a New Hugo Theme with hugo new theme

Running hugo new theme drops a full theme skeleton into your project in seconds, but half of it is placeholder metadata you must not ship. Budget fifteen minutes: enough to generate the tree, inspect what Hugo actually created, and clear out the fake licence and homepage links before anyone else sees them.

  • You need: an existing Hugo project and a shell.
  • It will not: publish a site, install a theme, change the active theme setting, or need elevated privileges. Do not use sudo unless your project directory is already wrongly owned.

1. Confirm you are at the Hugo project root

The default destination is ./themes, so the current directory matters. Running the command from a parent directory creates a separate themes tree that your site never uses.

$ cd /path/to/my-hugo-site
$ test -f hugo.toml || test -f hugo.yaml || test -f hugo.json
$ 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

The config test prints nothing when it succeeds. If it fails, stop and find the real project root before creating anything.

Checkpoint

You are in the project directory and the reported version is the one you intend to document or support.

2. Pick a theme name that is not already taken

Use letters, digits and hyphens, such as acme-paper. Check the destination first, as a separate step from creating it:

$ THEME_NAME='acme-paper'
$ test ! -e "themes/$THEME_NAME" && echo 'destination is unused'
destination is unused

A name that already exists may be working code. Do not remove or rename that directory just to make the command pass; change THEME_NAME instead.

3. Generate the skeleton

$ hugo new theme "$THEME_NAME"
Creating new theme in /path/to/my-hugo-site/themes/acme-paper

Hugo creates the directory when needed and refuses to create the same theme twice. A second run with the same name ends in an error that the directory already exists: this installed command has no force option.

Warning

This is the first state-changing step. If it created the wrong directory, do not run a broad recursive removal. Inspect it, copy out anything you need, preserve any edits you have already made, then remove only that newly created directory with your normal, deliberate process.

4. Inspect what Hugo actually generated

List the new tree rather than assuming which files a release ships:

$ find "themes/$THEME_NAME" -maxdepth 4 -type f -print | sort
themes/acme-paper/LICENSE
themes/acme-paper/README.md
themes/acme-paper/archetypes/default.md
themes/acme-paper/content/_index.md
themes/acme-paper/hugo.toml
themes/acme-paper/layouts/_default/baseof.html
themes/acme-paper/layouts/_default/home.html
themes/acme-paper/layouts/_default/list.html
themes/acme-paper/layouts/_default/single.html
themes/acme-paper/layouts/partials/footer.html
themes/acme-paper/layouts/partials/head.html
themes/acme-paper/layouts/partials/header.html
themes/acme-paper/layouts/partials/menu.html
themes/acme-paper/layouts/partials/terms.html
themes/acme-paper/static/favicon.ico
themes/acme-paper/theme.toml

Treat this list as the checkpoint, not a promise: it can vary between Hugo releases. In 0.123.7 the generated theme includes example templates and sample content, not an empty directory. The layouts files are a functional starting point, not a finished design.

5. Replace the placeholder metadata

Open themes/acme-paper/theme.toml. The generated file holds a display name, licence information, a licence link, a description, a homepage, an optional demo URL, tags, features, author sections, and an optional original block for a ported theme.

$ sed -n '1,120p' "themes/$THEME_NAME/theme.toml"
name = 'Theme name'
license = 'MIT'
licenselink = 'https://github.com/owner/repo/LICENSE'
description = 'Theme description'
  • Do not leave URLs pointing at owner/repo, or claim a licence you have not checked.
  • Add your name to the licence copyright line, as the generated instructions ask.
  • Rewrite or remove the original metadata if this theme is your own work, rather than implying it was ported.

Read README.md too: it should explain which templates, assets and Hugo features the finished theme expects. Keep the generated hugo.toml and sample content only if they are useful, and inspect them before committing anything to a repository.

6. Check the template entry points

Start with the four templates under layouts/_default and the partials they call:

$ sed -n '1,100p' "themes/$THEME_NAME/layouts/_default/baseof.html"
$ sed -n '1,100p' "themes/$THEME_NAME/layouts/_default/home.html"
$ sed -n '1,100p' "themes/$THEME_NAME/layouts/_default/single.html"

baseof.html supplies the document shell, while the home, list and single templates define the main page types. The partials give you head, menu, header, footer and taxonomy links.

Tip

Replace the example markup gradually and keep block names consistent with the base template. A missing define or block can make a page render with none of its expected content, and give you nothing to debug at first glance.

The generated sample includes a favicon and no general-purpose stylesheet. Add your own assets under the theme's static or resource directories to suit the design you are building. Do not treat this generated example as a promise about future Hugo skeletons.

7. Verify the result without publishing

$ test -f "themes/$THEME_NAME/theme.toml" && \
  test -f "themes/$THEME_NAME/layouts/_default/baseof.html" && \
  echo 'theme skeleton is present'
theme skeleton is present

A skeleton is not automatically the active theme: the site configuration has to select its name for that, and that should be a separate, reviewed change. If you only wanted the starting files, stop here.

Before committing, check that nothing unrelated was touched:

$ git status --short -- "themes/$THEME_NAME"
?? themes/acme-paper/

If the status shows edits outside this path, investigate them before staging anything. Nothing in this workflow needs elevated privileges, so the original project and any existing theme stay untouched until the new skeleton has been reviewed.

Done means

  • You ran hugo new theme from the intended Hugo project root.
  • The new directory sits under themes/ and did not overwrite an existing one.
  • You inspected the generated metadata, templates, partials and sample content.
  • theme.toml no longer contains unreviewed placeholder names or URLs.
  • You know the skeleton is not active until the site configuration selects it.
  • Git shows only the new theme files, ready for a deliberate review and commit.