Cloudflare Workers provides a serverless execution environment that lets you run applications at the edge without configuring or maintaining infrastructure. Workers Static Assets lets a Worker serve static files (HTML, CSS, JS, images) straight from Cloudflare’s network, with no Worker code at all, which is ideal for static sites.
Workers Sites is deprecated. Earlier versions of this guide used Workers Sites (a
[site]block inwrangler.toml, backed by KV storage) and the old@cloudflare/wranglerv1 CLI. Cloudflare deprecated Workers Sites in Wrangler v4 and recommends Workers Static Assets for new projects. This guide uses Static Assets; see Migrating from Workers Sites if you have an existing project.
This guide uses Hugo to generate the static files. Hugo is a fast static site generator written in Go that turns Markdown (and other content) into static HTML. If you are new to it, see Blogging with Hugo. You can use any static generator; the steps are the same once you have a build output directory.
Prerequisites
- Node.js and npm (for Wrangler). Wrangler supports the Current, Active LTS and Maintenance LTS Node.js release lines.
- A Hugo site (or any static site) with a build output directory (e.g.
public/for Hugo). - A Cloudflare account (free tier is enough).
Install the Workers CLI (Wrangler)
Deploying to Workers uses Wrangler, the Cloudflare Workers CLI. Cloudflare recommends installing it locally in your project rather than globally, so each project pins its own version. From your site’s root directory:
npm install --save-dev wrangler@latest
Then run it with npx wrangler <command>. If you skip the install, npx wrangler fetches the latest version on demand.
The old global install,
npm install -g @cloudflare/wrangler, is Wrangler v1. It is deprecated and does not support the commands below. Uninstall it (npm uninstall -g @cloudflare/wrangler) to avoid running the wrong binary.
See the Wrangler installation docs for other package managers.
Generate your static site
Build your Hugo site so the output directory (e.g. public/) is ready to upload:
hugo --gc --minify
Don’t use hugo -D for a production build: -D includes draft posts, which would then be published. Use whatever build command your static generator provides; the important part is having a folder of static files (e.g. public/).
Log in to Cloudflare
Log in to Cloudflare (this opens a browser to authenticate):
npx wrangler login
Confirm which account you are logged in to:
npx wrangler whoami
With Static Assets there is no workers-site directory or Worker script to generate, so the old wrangler init --site step is gone. All you need is a config file.
Configure wrangler.toml
Create wrangler.toml in your site’s root and point assets.directory at your build output:
name = "citizix"
compatibility_date = "2026-11-01"
[assets]
directory = "./public" # Your Hugo (or other) build output directory
not_found_handling = "404-page" # Serve the nearest 404.html with a 404 status
nameis the Worker’s name; replacecitizixwith your project name.compatibility_datepins the Workers runtime behaviour; set it to the date you create the project.- There is no
mainentry: an assets-only Worker needs no script. not_found_handling = "404-page"serves Hugo’s404.htmlfor unknown paths. Leave it out and unmatched requests get a plain 404.html_handlingdefaults toauto-trailing-slash, so/about/servespublic/about/index.html, which matches Hugo’s default output.
Wrangler also accepts the same settings as wrangler.jsonc. You no longer need to add account_id by hand: Wrangler uses the account you logged in with. If your login has access to several accounts, set account_id in wrangler.toml (find it in the Cloudflare dashboard under Workers & Pages) or run npx wrangler whoami to list them.
Preview locally
Preview your site before deploying:
npx wrangler dev
This serves your static site locally (by default at http://localhost:8787) with the same routing rules Workers uses in production, so you can confirm everything looks correct. Rebuild with Hugo after content changes; for writing, hugo server is still the faster loop. wrangler dev replaces the old wrangler preview --watch, which was removed.
Publish your site
Choose where to publish:
- workers.dev subdomain: a free
<name>.<your-subdomain>.workers.devURL. This is enabled by default; no extra config is needed. - Custom domain: a domain whose DNS is on Cloudflare. Add a Custom Domain route to
wrangler.toml. Cloudflare creates the DNS record and certificate for you.
Custom domain example:
[[routes]]
pattern = "example.com"
custom_domain = true
Unlike the old route = "example.com/*" setup, you don’t need to look up a zone_id. If you only want the custom domain, add workers_dev = false to turn off the workers.dev URL.
Then build and deploy:
hugo --gc --minify
npx wrangler deploy
Your static site will be live on your workers.dev URL or your custom domain. To deploy on every push instead of from your machine, connect the repository in the Cloudflare dashboard under Workers & Pages and set the build command (e.g. hugo --gc --minify) there.
Migrating from Workers Sites
If you have an existing Workers Sites project:
- Replace the
[site]block (bucket = "./public",entry-point = "workers-site") with the[assets]block shown above. - Remove
mainand theworkers-site/directory, unless you also run custom Worker code. In that case keepmainand addbinding = "ASSETS"under[assets]so your script can fetch assets. - Replace
wrangler previewwithwrangler dev, andwrangler publishwithwrangler deploy.
For the full list of differences, see Cloudflare’s Workers Sites page.
Summary
You installed Wrangler, built a Hugo (or other) static site, configured wrangler.toml with an [assets] block pointing at your build directory (and optionally a custom domain), previewed it with wrangler dev, and deployed with wrangler deploy. For more, see Cloudflare Workers Static Assets and Hugo’s documentation. If you also want traffic steering across origins, see Cloudflare Load Balancers with geo-steering.