A data-driven, dependency-free Go static-site generator for the OpenDesign
design system. It renders product, portfolio, and home pages from
plain data — portfolio.json, product markdown, and a per-site home.json — and
emits production-grade SEO for every page: <title>/meta, canonical, Open Graph,
Twitter Card, reciprocal hreflang, JSON-LD (Organization/Person,
WebSite, SoftwareApplication), plus sitemap.xml and robots.txt.
No page is hardcoded. Go holds only layout and templates; every product name, status, tech chip, repository link, and copy string comes from data. Point it at a different data root and it renders a different site.
- Zero third-party dependencies — standard library only (
go.modhas norequireblock). - Deterministic output — the same data always produces byte-identical HTML, which makes diffing and evidence-based QA practical.
- i18n-aware — hreflang alternates are generated for every
_content_<lang>/directory found on disk; per-language page output is a single flag. - Durable asset sync — a companion script copies every design-system asset a
page needs into
<site>/assets/od/so deployed pages are fully self-contained and never link back into the source tree (see USAGE.md).
Hand-maintained marketing/portfolio sites drift: a product ships, its status,
license, or repo list changes, and three HTML pages silently go stale. This tool
makes the data the single source of truth. Update portfolio.json once and every
product card, product page, JSON-LD node, and sitemap entry regenerates
consistently. A page is only "done" when it renders from real data.
Requires Go 1.26+. No network access is needed to build (no external modules).
git clone https://github.com/vasic-digital/opendesign-site-generator.git
cd opendesign-site-generator
go build -o gen . # builds the `gen` command
go build ./... # or: build every packagegen -site <key> [-lang en] [-what all|products|portfolio|home] [-root <dir>] [-out <dir>]
| Flag | Default | Meaning |
|---|---|---|
-site |
(required) | Site key selecting a built-in site definition (brand, domain, CSS name, OG image, JSON-LD identity). See DATA-CONTRACT.md. |
-lang |
en |
Language code. en is canonical (unprefixed output); any other code writes localized paths (products/<lang>/…, <lang>/…). |
-what |
all |
What to render: all, products, portfolio, or home. |
-root |
. |
Data/repository root. The generator reads <root>/_content/** and <root>/design-system/** (optional diagrams) from here. |
-out |
<root>/<site.Dir> |
Output base directory for generated HTML. |
sitemap.xml + robots.txt are written on a full -what all English build,
walking the actual output tree so every sitemap URL resolves to a real file.
The examples/ directory ships a complete, self-contained data set
and the output it produces:
go build -o gen .
./gen -site vasic.digital -root examples/data -out /tmp/site-out
# [gen] site=vasic.digital lang=en what=all out=/tmp/site-out products=2
find /tmp/site-out -type f
# index.html portfolio/index.html
# products/helixtrack.html products/sampleutil.html
# robots.txt sitemap.xmlThe committed sample of that exact output lives in
examples/output/. See examples/README.md.
The full JSON / markdown / frontmatter schema the generator consumes — so another project can supply its own data — is documented in DATA-CONTRACT.md. Per-language generation, the durable asset-sync workflow, and the exact SEO output are documented in USAGE.md.
26 standard-library unit tests cover escaping, frontmatter parsing, markdown
rendering, portfolio cards, language discovery, hreflang reciprocity, JSON-LD,
the SEO head, and sitemap/robots generation. They read fixtures from
testdata/, so they pass in a clean checkout with no external data:
$ go build ./...
$ go test ./...
ok github.com/vasic-digital/opendesign-site-generator 0.595s
Verbose (all 26):
$ go test -v ./...
=== RUN TestEscEscapesQuotes
--- PASS: TestEscEscapesQuotes (0.00s)
=== RUN TestParseFrontmatter
--- PASS: TestParseFrontmatter (0.00s)
=== RUN TestParseFrontmatterNoFrontmatter
--- PASS: TestParseFrontmatterNoFrontmatter (0.00s)
=== RUN TestLoadPortfolioAndBySlug
--- PASS: TestLoadPortfolioAndBySlug (0.00s)
=== RUN TestPortfolioDataHasNoPrivateLeak
--- PASS: TestPortfolioDataHasNoPrivateLeak (0.00s)
=== RUN TestEscText
--- PASS: TestEscText (0.00s)
=== RUN TestInline
--- PASS: TestInline (0.00s)
=== RUN TestRenderBody
--- PASS: TestRenderBody (0.00s)
=== RUN TestRenderBodyIndentation
--- PASS: TestRenderBodyIndentation (0.00s)
=== RUN TestRenderBodyEmpty
--- PASS: TestRenderBodyEmpty (0.00s)
=== RUN TestRepoLabel
--- PASS: TestRepoLabel (0.00s)
=== RUN TestLicHideRe
--- PASS: TestLicHideRe (0.00s)
=== RUN TestPortfolioCardChipCap
--- PASS: TestPortfolioCardChipCap (0.00s)
=== RUN TestPortfolioCardHidesTBDLicense
--- PASS: TestPortfolioCardHidesTBDLicense (0.00s)
=== RUN TestFirstNonEmpty
--- PASS: TestFirstNonEmpty (0.00s)
=== RUN TestXMLDeclStripped
--- PASS: TestXMLDeclStripped (0.00s)
=== RUN TestProductHref
--- PASS: TestProductHref (0.00s)
=== RUN TestI18nAttr
--- PASS: TestI18nAttr (0.00s)
=== RUN TestSiteURL
--- PASS: TestSiteURL (0.00s)
=== RUN TestLangPath
--- PASS: TestLangPath (0.00s)
=== RUN TestAvailableLangs
--- PASS: TestAvailableLangs (0.00s)
=== RUN TestHreflangLinksReciprocal
--- PASS: TestHreflangLinksReciprocal (0.00s)
=== RUN TestJSONLDScriptHasType
--- PASS: TestJSONLDScriptHasType (0.00s)
=== RUN TestSoftwareApplicationNodeHidesTBDLicense
--- PASS: TestSoftwareApplicationNodeHidesTBDLicense (0.00s)
=== RUN TestSeoHeadSingletons
--- PASS: TestSeoHeadSingletons (0.00s)
=== RUN TestWriteSitemapRobots
--- PASS: TestWriteSitemapRobots (0.02s)
PASS
ok github.com/vasic-digital/opendesign-site-generator 0.595s
main.go command entry, flag parsing, site definitions (the `sites` map)
data.go portfolio + home data models, JSON loaders, frontmatter parser
portfolio.go portfolio index page renderer
product.go product detail page renderer
home.go home page renderer (standalone + Jekyll shells)
markdown.go minimal markdown -> HTML (headings, lists, bold, code)
seo.go SEO head, hreflang, JSON-LD graph, sitemap.xml + robots.txt
shells.go shared layout chrome (SVG symbols, inline styles, theme toggle)
build.sh reference site-integration script: asset sync + per-site generation
testdata/ fixtures the unit tests read (self-contained)
examples/ runnable data set + committed sample output
MIT.