Skip to content

Latest commit

 

History

History
222 lines (170 loc) · 9.98 KB

File metadata and controls

222 lines (170 loc) · 9.98 KB

Data contract

The generator is data-driven: Go holds layout and templates, and everything else comes from data under your -root. This document is the complete schema so any project can supply its own data.

Everything is read relative to -root:

<root>/
  _content/
    portfolio/portfolio.json          # product metadata (source of truth)
    products/<slug>.md                # one markdown file per product
    sites/<site-file>.home.json       # one homepage document per site
  _content_<lang>/                    # OPTIONAL: presence enables hreflang for <lang>
  design-system/
    diagrams/<slug>.svg               # OPTIONAL: architecture figure injected into a product page

There are two layers:

  1. Site definitions — per-site identity (brand, domain, OG image, JSON-LD kind). Compiled in; you edit the sites map in main.go.
  2. Content data — per-page content (products, home). Pure data files; no code changes.

1. Site definitions (sites map in main.go)

Site-level identity is not read from data files — it is defined in the sites map in main.go and selected with -site <key>. To render for your own project, add an entry to that map. Each Site has:

Field Type Purpose
Key string The -site value that selects this definition.
Brand string Display brand; used in <title> suffixes, OG site_name, footers, JSON-LD name.
CSSName string Basename of the deployed brand stylesheet at <site>/assets/od/<CSSName>.css.
HomeJSON string Path (relative to -root) of the homepage document for this site.
Dir string Default output subdirectory (used when -out is omitted).
Domain string Production host (no scheme); every absolute URL, canonical, and sitemap <loc> is built from it.
OGImage string Root-relative Open Graph / letterhead image path (should exist on the deployed site).
LDKind string JSON-LD identity type: "Organization" or "Person".
SameAs []string JSON-LD sameAs profile URLs for the identity node.

Genericity note. Because site identity is compiled in, adapting this tool to a new brand means editing the sites map (a few lines) in addition to supplying data files. The -site key must match a map entry; unknown keys exit with an error. Two example definitions ship in main.go (vasic.digital, a standalone site; milosvasic.ru, a Jekyll-embedded site) that you can copy and adjust.


2. portfolio.json

The single source of truth for product metadata, shared by the portfolio page, every product page, the homepage product cards, and the JSON-LD graph.

{
  "schema": "portfolio/v1",     // free-form version string (informational)
  "count": 2,                    // MUST equal entries.length (a test asserts this on your data if you reuse the fixture guard)
  "tiers": ["helix-primary", "vasic-util-secondary"],  // ordered tier keys; each becomes a portfolio section
  "excluded": [],                // informational; slugs intentionally omitted
  "entries": [ /* PortfolioEntry[] */ ]
}

PortfolioEntry

Field JSON key Type Notes
Name name string Display name. Used as page <h1>, card title, JSON-LD name.
Slug slug string URL slug. Product page is products/<slug>.html; also the design-system/diagrams/<slug>.svg lookup key.
Tier tier string Must be one of tiers. Groups the entry into a portfolio section.
Order order int Shown on the product page eyebrow (// tier: X · order N).
Status status string Rendered verbatim as a status badge and as the CSS modifier od-badge--status--<status> (e.g. beta, production, stable, scaffold). Keep it a single CSS-safe token.
License license string SPDX-style id (e.g. MIT). Values matching `^(unverified
Private private bool Marks a private product. A guard asserts a private:true entry carries no repos (suppression is expected upstream at your data gate).
Tech tech []string Technology chips. Portfolio cards show the first 6 then a +N overflow chip; product pages show all.
Repos repos []string Repository URLs. github.com/... URLs are shortened to owner/repo; others shown in full.
Summary summary string Primary description: meta description, card blurb (fallback), JSON-LD description.
Tagline tagline string Short blurb; preferred over summary for the portfolio card blurb.
Source source string Path (relative to -root) of the product markdown file for this entry.

Description precedence for a product page's meta/OG: summarytagline"<name> — <brand> product." (first non-empty).


3. Product markdown (_content/products/<slug>.md)

Each entry's source points at a markdown file: YAML-ish frontmatter + a markdown body.

---
name: HelixTrack
status: beta
license: MIT
tech:
  - Go
  - PostgreSQL
---
# HelixTrack

Intro paragraph with **bold** and `code`.

## A section

- a list item
- another item

Frontmatter (a deliberately minimal YAML subset)

  • Delimited by a leading --- line and a closing --- line.
  • key: value → a scalar.
  • key: with an empty value, followed by - item lines → a string list.
  • Only scalars and simple string lists are supported (no nesting, no inline flow collections). A file with no frontmatter is a hard error for a product.

Note: page identity (name, status, license, tech, repos) for rendering comes from portfolio.json, not the frontmatter. The frontmatter is parsed and available, and keeping it in sync with the portfolio entry is the recommended convention, but the body is what the product page renders.

Body markdown (supported subset)

Markdown Output
# Title dropped (the page <h1> comes from the portfolio name)
## Heading <h2>
- item runs <ul><li>…</li></ul>
blank-line-separated <p>…</p> (consecutive non-blank lines join with a space)
**bold** <strong>…</strong>
`code` <code>…</code>

Anything else is treated as paragraph text. Text is HTML-escaped (&, <, >; quotes are preserved in body content) before inline substitution.


4. Homepage document (_content/sites/<site>.home.json)

One JSON document per site (Site.HomeJSON). It describes the homepage as an ordered list of typed blocks.

{
  "site": "vasic.digital",
  "kind": "standalone",        // "standalone" -> full HTML page; "jekyll" -> a Jekyll `default`-layout fragment
  "brand": "Example Digital",  // brand shown in the page body/footer
  "lang": "en",
  "title": "",                 // <title> (standalone)
  "description": "",           // meta description (standalone)
  "css": "vasic-digital",       // informational; deployed CSS basename
  "footer": "",                // footer text (standalone)
  "blocks": [ /* HomeBlock[] */ ]
}

HomeBlock (type selects the shape)

type Renders Key fields
hero Hero section eyebrow, title, lede, ctas[], stats[]
section Content section id, optional section header (eyebrow/title/lede), groups[], optional trailing ctas[] (ctaWrap, ctaStyle)
contact Contact section id, eyebrow, title, lede, contacts[]

Reusable value objects

I18nText — visible text plus its i18n key: { "i18n": "hero.title", "text": "Hello", "class": "", "html": false }. When html is true, text is emitted as trusted (pre-escaped) HTML.

CTA{ "i18n", "label", "href", "variant" ("primary"|"secondary"|"ghost"), "dl", "icon" }. If dl is set the CTA renders as a <button data-dl> (e.g. a download action); otherwise an <a href>.

Stat{ "i18n", "value", "label" } (hero stat tile).

Group — a sub-block of a section: { "eyebrow", "title", "lede", "marginTop", "kind" ("prose"|"cards"|"tech"), "grid", "paras": I18nText[], "cards": Card[] }.

Card — a product/tech card: { "slug", "name", "nameI18n", "status", "noBadge", "tech": [], "blurb": I18nText, "readmore": I18nText }. If slug is set and status is empty, the status badge is pulled from the matching portfolio.json entry; readmore links to products/<slug>.html (via Jekyll's relative_url filter when kind is jekyll).

Contact{ "i18n", "label", "html" } where html is trusted inner HTML for the value line.

See examples/data/_content/sites/vasic-digital.home.json for a complete, working document.


5. Languages (_content_<lang>/)

The generator discovers languages by scanning -root for _content_<lang>/ directories (e.g. _content_de/, _content_ru/). For every language found:

  • en is always present and canonical (unprefixed paths).
  • Directory names containing an underscore in the code (e.g. _content_de_proof) are ignored as scratch dirs.
  • The discovered set (en first, remainder sorted) drives the reciprocal hreflang matrix emitted in every page head, plus x-default → EN.

Per-language page output is produced by running with -lang <code> (see USAGE.md); merely creating _content_<lang>/ enables the hreflang alternates.


6. Optional architecture diagram (design-system/diagrams/<slug>.svg)

If a file <root>/design-system/diagrams/<slug>.svg exists, its SVG (with any leading <?xml …?> declaration stripped) is injected into that product's page as an <figure class="od-diagram">. Missing files are simply skipped.