A small tool that wraps npm packages as Hugo Modules, so a Hugo site can consume them without an npm dependency.
Given a package.json with a dependencies block, it downloads each package
from the npm registry, drops it into a per-package directory with a go.mod
and hugo.toml, and writes a root hugo.toml that re-exports all of them
as a single Hugo Module.
Run it from the root of a git repo that will host the wrappers. The Go
module base path is derived from the repo's origin remote.
# Sync wrappers from ./package.json
npmtohugomod
# Override the module base path (skip git-remote auto-detection)
npmtohugomod --module-base github.com/owner/repoRe-runs with an unchanged package.json are no-ops; on a version bump only
the affected package is refetched. Requires hugo and git on PATH.
For each entry in dependencies (e.g. @alpinejs/focus):
alpinejs/focus/package/…— the npm tarball contents.alpinejs/focus/npmpackage.json— npm metadata (informational).alpinejs/focus/hugo.toml— mounts the ESM build underassets/@alpinejs/focus.alpinejs/focus/go.mod— created byhugo mod init. For majors ≥ 2 the module path includes a/vNsuffix (Go semantic import versioning).alpinejs/focus/README.md— has a marker-delimited block showing the import path; updates regenerate just that block, anything outside is preserved.
At the repo root, hugo.toml lists every wrapper as a [[module.imports]]
entry, so a downstream Hugo site can import the whole bundle in one line.
npmtohugomod releaseWalks all wrapper directories and creates a local annotated git tag for each
(then stops — tags are not pushed). Existing tags are skipped, so re-runs
are safe. Fails if the working tree is dirty; pass --allow-dirty to
override.
Tags follow vX.Y.(Z*1000+W), where X.Y.Z is the upstream npm version and
W is bumped on wrapper-only changes (e.g. a hugo.toml tweak). W starts
at 0 and resets on any upstream-version change. The release command
currently always emits W=0; re-tagging after a wrapper-only change is
manual for now.