Uma is a lightweight, no-fuss local CMS for editing Hugo site content locally. It runs as a small Node.js web app; just point it at any local Hugo project folder, and it auto-detects your front matter fields, so it should work with any theme without any additional configuration.
This app was fully generated using Claude and later modified manually.
- Content editor — browse
content/, edit front matter (auto-detected fields: text, numbers, booleans, tags/lists, nested groups), and edit the body in Markdown (EasyMDE). - Data files — browse and edit
data/*.yaml/.json/.tomlwith the same generic field editor. - Media manager — browse, upload, and delete images/files in your detected static/asset folders, with folder navigation and one-click "copy path" / insert-into-content.
- Safe by construction — all file operations are sandboxed to your project folder; no path can escape it.
- No build step on the frontend, no database, no accounts. Just your files.
- Node.js 18 or newer.
cd uma-hugo-cms
npm install
npm start
This starts a local server at http://localhost:4747 and tries to open it
in your browser automatically. On first run, you'll be asked to enter the
full path to a Hugo project folder (the one containing content/ and a
hugo.toml / config.toml, etc.). That path is remembered for next time
(stored in .uma-config.json next to server.js — this file is git-ignored
and never touches your Hugo project).
- Front matter is parsed generically: whatever keys/values exist in a
file's front matter (YAML
---or TOML+++) are turned into editable fields automatically. Add new fields with the "Add field" control at the bottom of the panel. The original format (YAML/TOML) is preserved on save. - New content creates a Markdown file with a small starter front matter
(
title,date,draft: true). You can optionally create it as a "page bundle" (a folder withindex.md), which is useful if the page will have its own attached images. - Media folders are auto-detected from common Hugo conventions
(
static/,static/images,assets/images, etc.) — whichever exist in your project.static/is always offered even if empty, since it's Hugo's default. "Copy path" gives you the URL path Hugo will actually serve the file at (forstatic/, that's the file's path with thestatic/prefix stripped). - Data files are edited with the same generic field editor. If a data file's root is a list (common for things like a team roster), it's editable as a list of entries.
uma-hugo-cms/
server.js Express app + API routes
lib/
safePath.js Path-traversal-safe resolution
frontMatter.js Markdown front matter parse/stringify (YAML/TOML)
dataFile.js Data/ file parse/stringify (JSON/YAML/TOML)
hugoProject.js Project validation + tree/media scanning
public/
index.html, style.css, app.js the frontend
- Front matter/data field editor renders generic controls based on value type — it doesn't know theme-specific field semantics (e.g. it won't know a field is meant to be an image picker vs. plain text). You can still type any value, including a path you copied from the Media tab.
- No live Hugo preview/build integration — this only edits files. Run
hugo serverseparately to preview your site. - Single-user, unauthenticated, local-only by design. Don't expose port 4747 beyond your own machine.
- Doesn't support undo-ing any edits or delete; use with judgment & keep
necessary backup of your files.
If you want to contribute to Uma to add a feature or improve the code, please open an issue or make a pull request.
Please give a ⭐ if this project helped you!
