Skip to content

docs: promote the action docs to /sbomify-action/ and wire them into the site - #138

Merged
vpetersson merged 3 commits into
sbomify:masterfrom
vpetersson-bot:docs/consolidate-sbomify-action-page
Aug 31, 2026
Merged

docs: promote the action docs to /sbomify-action/ and wire them into the site#138
vpetersson merged 3 commits into
sbomify:masterfrom
vpetersson-bot:docs/consolidate-sbomify-action-page

Conversation

@vpetersson-bot

@vpetersson-bot vpetersson-bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #136, which left /sbomify-action/ as a short standalone overview funnelling into /guides/sbomify-action/. That answers open question #1 from that PR, in the other direction: the docs now live at /sbomify-action/, and the standalone page is gone.

The problem

Two pages covered the same ground, and the standalone one had already drifted from the section shipped two days earlier:

Its description said 17 ecosystems its own table listed 14 — no Haskell, Erlang or Clojure
TeamCity missing from the "Beyond GitHub" runtime list
OIDC and attestation presented as universal immediately before a section saying "the same tool runs anywhere". Both are GitHub-only, as the section states plainly
The funnel was the last section on the page below everything else

The deeper issue ran the other way. The 20-page section had inbound links from exactly two files, both in content/guides/_index.md. Every other page on the site — ~19 language guides, the FAQs, the integrations page — still pointed at the raw GitHub repo. The docs existed but nothing on the site led to them.

Three commits

1. Fold the standalone page in

content/sbomify-action.md deleted. One canonical page, so the two can't compete for the same query or drift apart again.

Carried over the one thing it had that the section lacked: per-language links from the lockfile table in sources.md, plus a Docker guide link from the container-images section.

Then wired the section into the site. The "swiss army knife" paragraph in 17 language and platform guides now links to the docs and the runtimes index, keeping the repo link in the sentence. Inbound links went from 2 files to 20.

2. Promote to /sbomify-action/

/guides/ is where tutorials live — "how to make an SBOM in Rust". The action is a product surface: open source, works standalone with no account, its own release cadence. /sbomify-action/ is the URL that belongs in the action repo's README and the Marketplace listing, and it sits naturally alongside /features/ and /compliance/ rather than under one of them.

The section shipped two days ago, so this is the cheapest possible moment to move it. All 20 pages moved, every old /guides/sbomify-action/* URL aliased, 205 internal links rewritten across 41 files.

One thing that would have broken silently

The BreadcrumbList block in head.html keys off Hugo's derived .Section, not frontmatter. Moving the directory changed it from guides to sbomify-action, which isn't in the $crumbSections dict — all 20 pages would have shipped with no breadcrumb schema and nothing would have complained. Registered, with a note that new top-level sections have to be added there.

Related: the section: frontmatter key on these pages is dead — nothing reads .Params.section anywhere in the site. Updated it rather than leave 20 pages claiming a section they're not in, but it has no effect. Stripping it from all 53 pages that carry it is worth a separate cleanup.

Drift fixed along the way

The docs already contradicted these:

  • The integrations page still claimed generators are "pre-installed" in the image and must be "installed separately" for the local CLI. Since v26.8.0 they are fetched on first use, digest-pinned and cached — docs: comprehensive sbomify-action documentation section #136 fixed this everywhere except here.

  • Five guides named the wrong generator, against the v26.8.0-validated table in sources.md:

    Guide Said Actually
    docker cdxgen → Syft Syft → cdxgen (reversed)
    rust cdxgen cargo-cyclonedx
    go cdxgen cyclonedx-gomod
    java cdxgen cyclonedx-maven / cyclonedx-gradle
    scala cdxgen cyclonedx-sbt

    Swift also tightened from "cdxgen or Syft" to Syft, which is what the priority table says.

Examples stay on @master

A version in an example goes stale the moment the next release ships, and every release then needs a docs sweep to stay honest. So examples use @master, and this PR removes the 19 @v26.8.0 pins #136 introduced in the docs section.

Two places keep a concrete version deliberately, because they are about pinning rather than examples to copy: advanced.md's "Version pinning" block, which contrasts tag vs SHA vs floating and needs a real tag to make the point, and its CalVer sentence explaining the scheme. Dated blog posts keep their pins as historical records.

The version-pinning note on the GitHub Actions page named v26.8.0 as "readable and fine for most projects" — true of a tag, false of the @master the examples now use. Rewritten to say what the examples use and why, pointing at the trade-offs in advanced.md.

Verification

  • bun run lint — passes
  • hugo --minify --environment production — clean, 493 pages, 169 aliases
  • All 16,107 internal links and anchors in the built site resolve (every href on every built page, checked against real page paths and id attributes)
  • Sitemap carries all 20 new URLs and none of the old; aliases stay out of it, so there is one canonical per page
  • Breadcrumb schema verified rendering correctly on moved pages
  • No JS or images added, so the 100/100 PageSpeed target is unaffected

Follow-up

The action repo's README and Marketplace listing should point at https://sbomify.com/sbomify-action/. The .gitlab-ci.yml and pipe.yml issues flagged in #136 are still open there.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq

vpetersson-bot and others added 3 commits August 31, 2026 15:23
Follow-up to sbomify#136. The standalone /sbomify-action/ page was a second,
drifting copy of material the new section already covers, and the section
itself had almost no inbound links from the rest of the site.

Consolidate:

- Delete content/sbomify-action.md and alias /sbomify-action/ to
  /guides/sbomify-action/. One canonical page, so the two stop competing
  for the same query and cannot drift apart again. The old page listed 14
  ecosystems while its own description said 17, omitted TeamCity, and
  presented OIDC and attestation as universal rather than GitHub-only.
- Carry over the one thing it had that the section lacked: per-language
  links from the lockfile table in sources.md, plus a Docker guide link
  from the container images section.

Wire the section into the site:

- Point the "swiss army knife" paragraph in 17 language and platform
  guides at /guides/sbomify-action/ and /guides/sbomify-action/runtimes/
  instead of only the GitHub repo. The repo link is kept in the sentence.
- Inbound links to the section go from 2 files to 20.
- Tidy the duplicate /sbomify-action/ entries in the guides index, and
  register quickstart, how-it-works and sources in llms.txt.

Fix drift the docs already contradicted:

- Language guides pinned @master while the new section pins @v26.8.0;
  updated across guides, FAQs, zero-to-hero and the integrations page.
  The deliberate @master counter-example in advanced.md and the dated
  blog posts are left alone.
- The integrations page still claimed generators are "pre-installed" in
  the image and must be "installed separately" for the local CLI. Since
  v26.8.0 they are fetched on first use, digest-pinned and cached.
- Five guides named the wrong generator: container images use Syft then
  cdxgen (not the reverse), Rust uses cargo-cyclonedx, Go uses
  cyclonedx-gomod, Java uses cyclonedx-maven/cyclonedx-gradle, Scala uses
  cyclonedx-sbt, and Swift is handled by Syft.

Verified: bun run lint passes, hugo --minify --environment production
builds 493 pages clean, and all 16,106 internal links and anchors in the
built site resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq
/guides/ is where tutorials live - "how to make an SBOM in Rust". The
action is a product surface: open source, works standalone with no
account, and /sbomify-action/ is the URL that belongs in the action
repo's README and the Marketplace listing. Two segments of "this is a
tutorial" framing undersold it.

Moves the 20-page section from /guides/sbomify-action/* to
/sbomify-action/*. Every old URL is aliased, so the paths shipped two
days ago in sbomify#136 still resolve. 205 internal links rewritten.

Breadcrumb schema needed registering: the BreadcrumbList block in
head.html keys off Hugo's derived .Section, so moving the directory
changed it from "guides" to "sbomify-action" and would have silently
dropped the schema from all 20 pages. Added to $crumbSections, with a
note that new top-level sections have to be registered there.

Worth knowing: the `section:` frontmatter key on these pages is dead -
nothing reads .Params.section. Updated it anyway to stay honest rather
than leave 20 pages claiming to be in a section they are not.

Verified: bun run lint passes, hugo --minify --environment production
builds 493 pages with 169 aliases, all 16,106 internal links and anchors
resolve, and the sitemap carries all 20 new URLs and none of the old.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq
Reverts the @master -> @v26.8.0 change from earlier in this branch, and
extends the same reasoning to the 19 pins sbomify#136 introduced in the docs
section. A version in an example goes stale the moment the next release
ships, and every release then needs a docs sweep to stay honest.

Two places keep a concrete version deliberately, because they are about
pinning rather than examples to copy:

- advanced.md's "Version pinning" block, which contrasts tag vs SHA vs
  floating and needs a real tag to make the point
- advanced.md's CalVer sentence explaining the scheme

Rewrote the version-pinning note on the GitHub Actions page, which named
v26.8.0 as "readable and fine for most projects" - true of a tag, false
of the @master the examples now use. It now says what the examples use
and why, and points at the trade-offs in advanced.md.

Dated blog posts keep their pins as historical records.

Verified: bun run lint passes, hugo --minify --environment production
builds 493 pages, all 16,107 internal links and anchors resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq
@vpetersson
vpetersson merged commit abf96ea into sbomify:master Aug 31, 2026
2 checks passed
vpetersson-bot added a commit to vpetersson-bot/sbomify.com that referenced this pull request Aug 31, 2026
/llms.txt is generated from layouts/home.llms.txt via the `llms` output
format, as hugo.toml itself documents. The file at the repository root
is not in static/, so Hugo never copies it and it has never been served.

It was not harmless. It looked authoritative, so it got maintained -
f473861 'fix: update llms.txt hierarchy description' edited a file
nobody could read - and it misled me during sbomify#138, where I added the new
action pages to it and reported them as registered. The pages that
actually needed adding were missing from the generated file until the
previous commit.

Nothing is lost. Every section it carried exists in the generated
output, and the two that looked unique to it - Content Policy and
Contact - are byte-identical there.

Verified by building with and without the file: the two runs are
byte-identical across all 493 pages, which is the proof it was never
published.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq
vpetersson pushed a commit that referenced this pull request Aug 31, 2026
… llms.txt

Two related things, both consequences of #138 moving the action docs out
of /guides/.

## The section key does nothing

53 pages carried `section:` in their frontmatter - 19 guides, 19
sbomify-action, 15 compliance. Nothing reads it. Every template uses
Hugo's built-in `.Section`, which is derived from the file's directory
and cannot be set from frontmatter:

  $ grep -rniE '\.params\.section|param "section"' layouts/
  $ (no matches)

The 20 matches are all `.Section` or `where ... "Section" ...`, which
resolve the page method, not params.

It is not merely dead, it is a trap: it went stale during the /guides/
move, leaving pages declaring `section: guides` while actually living in
`sbomify-action`. Removed rather than wired up, since `.Section` is the
idiomatic mechanism and already works.

## The action pages had fallen out of llms.txt

Both /llms.txt and /llms-full.txt are generated from a fixed list of
sections. That list had no entry for `sbomify-action`, so when #138
moved those pages out of `guides` they landed in no group at all and
stopped being emitted - all 20 of them, silently, including the full
text in llms-full.txt.

Added a "sbomify Action" group to both. 18 pages return to llms.txt and
19 to llms-full.txt.

## Verification

The build was diffed file by file against a baseline built from
b54f243. After committing - so `enableGitInfo` reads the same git state
CI does - the only differences are:

- 19 guides pages and sitemap.xml, where `dateModified` and `lastmod`
  move because those files genuinely changed
- llms.txt and llms-full.txt, gaining the action pages

Nothing else in 493 pages changed, which is the point: removing the key
has no rendered effect.

Worth recording, because it cost time: building with an uncommitted tree
made the `cra` taxonomy term render as "Cra" instead of "CRA". The tag
is spelled `CRA` in two posts and `cra` in five, and Hugo takes the
casing from page order, which shifts when `enableGitInfo` cannot read
dates for dirty files. It is not a real difference - it disappears once
committed - but it makes a dirty-tree build diff misleading.

Also confirmed: two consecutive builds from identical sources are
byte-identical, so the diff above is signal rather than noise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UatuV4CjoCupLTRYNbD3Wq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants