# Deploy Hugo on Lizard

Lizard can build a Hugo source site with `hugo --minify` and serve `public/` through nginx on port `80`. Start from the Hugo source directory, with a Hugo configuration and `content/`, rather than uploading only the generated HTML.

Start with the [complete source example](https://github.com/lizard-build/docs/tree/main/_examples/hugo), which includes the configuration and files used by this recipe.

## Prepare the source

Include your Hugo config, content, layouts, assets, and all theme files needed by the build. The Hugo detector looks for configuration such as `hugo.toml`, `hugo.yaml`, or `config/_default/` plus a `content/` directory.

| Setting | Value |
|---|---|
| Build | `hugo --minify` |
| Output | `public/` |
| Production server | nginx |
| Service port | `80` |

Set `baseURL` to the intended public site URL, including its trailing slash. Rebuild after assigning a different hostname so links and generated sitemap entries use it. Check [Hugo's build and output guide](https://gohugo.io/getting-started/usage/).

## Check build dependencies

The default Hugo build image is `hugomods/hugo:base`; it does not pin a Hugo version for your project. If a theme needs a particular Hugo version, the extended edition, or Node tooling, use a complete Dockerfile with those dependencies and the version you tested.

A Hugo config and `content/` select the Hugo builder before Go or Node detection. Hugo Modules projects with `go.mod` use a build image with Go support. A `package.json` causes the build to stop with a request for a Dockerfile: install the Node dependencies, build the assets, then run `hugo --minify`. See [build decision order](https://lizard.build/docs/concepts/build-pipeline#build-decision-order).

## Build locally and deploy

```bash
hugo --minify
hugo server
```

Inspect `public/` after the first command. Use the local server to check content and theme rendering; `hugo server` is not the production start command.

After [CLI setup](https://lizard.build/docs/framework-guides#prepare-the-project), deploy the source directory:

```bash
lizard init --name hugo-site
lizard add --service web
lizard up --service web --port 80
lizard logs --build --service web --json
lizard ps --json
```

If you use the generated hostname, read it after the first deploy:

```bash
lizard service show web --json
```

Set `baseURL` in `hugo.toml` to that hostname:

```toml
baseURL = "https://YOUR_PUBLIC_HOST/"
```

Upload the changed config so the build uses the public URL:

```bash
lizard up --service web --port 80
```


Exclude local generated output and secrets. For an upload, ensure theme source files actually exist in the directory you send; a remote submodule reference alone is not the theme content.

## Verify the deployed site

Open the live home page, an inner article, and an image. Check the generated canonical URLs and `sitemap.xml`. Test a made-up path's HTTP status. New Hugo builds serve the generated HTML and return HTTP 404 for missing pages. No custom Dockerfile is needed for the simple source layout in this guide. Rebuild older images to pick up the current routing rules.

Use [static routes and 404s](https://lizard.build/docs/framework-guides/static-routing) if you need a custom nginx policy. A custom Hugo build stage must include the theme's required Hugo version and tools, run `hugo --minify`, and copy `public/` into the serving image.

If theme assets are missing, inspect the build logs, theme source, and `baseURL`. If the wrong builder starts, check that the Hugo config and `content/` are in the upload root and inspect existing service overrides. Hugo produces static files, so content changes need a new build.

See [tested versions and cloud results](https://lizard.build/docs/framework-guides/validation) for the September 9, 2026 deployment checks and their limits.

