Skip to content

About

hivecommons.dev — placeholder site (GitHub Pages)

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Source for hivecommons.dev (GitHub Pages). Static site: index.html, style.css, and assets/ — no build step.

Custom domain is pinned via CNAME. llms.txt carries a short machine-readable summary for LLM crawlers (its integration and sponsor lists are gated against index.html by scripts/llms-txt.test.mjs), and sitemap.xml lists the canonical top-level pages (not every shortcut redirect) for robots.txt's Sitemap: entry — when adding a new top-level page, add it to sitemap.xml too.

Shortcut redirects

Short paths like /docs, /code, /discord are meta-refresh redirect pages. All of them are generated by make-redirects.sh: edit the MAP at the top of the script, run ./make-redirects.sh, then commit the regenerated index.html files — don't hand-edit them, since a future run of the script will silently overwrite any hand edit.

scripts/check-redirects.sh enforces this: it regenerates the pages into a scratch directory and fails if any committed redirect page is missing from MAP, any MAP entry has no committed page, or a committed page differs from what the script emits.

Checks

The Link check workflow (.github/workflows/links.yml) runs its links, test and redirects jobs on every pull request and on every push to main, so commits pushed straight to main are checked too and main carries a same-named baseline to compare a red PR job against.

  • scripts/check-links.sh [--external-warn] — resolves every internal link/anchor and probes external URLs (CI runs it with --external-warn on PRs and pushes; the weekly scheduled run and manual dispatch hard-fail on broken external links).
  • scripts/check-links.test.sh — fixture-based self-test of the link checker; runs offline (fake curl).
  • node --test scripts/story-dialog.test.mjs — runs the Share-your-story dialog script from stories/index.html against a stub DOM and checks the prefilled-issue URL, validation, 1500-char trim, and popup-blocked fallback. Zero dependencies.
  • node --test scripts/acmm-levels.test.mjs — runs the ACMM levels tablist script from index.html against a stub DOM with deterministic timers and checks tab activation, roving tabindex, arrow/Home/End keys, auto-rotation, and every pause condition (hover, focus, hidden tab, reduced motion, out of view). Zero dependencies.
  • node --test scripts/carousels.test.mjs — runs the hero carousel and projects carousel scripts from index.html against a stub DOM with deterministic timers and checks dot generation, slide/aria-current state, live-region announcements, keyboard/swipe/hash navigation, auto-rotate and every pause condition, hero height measurement (clones, resize debounce), and projects scroll-sync (debounced scroll, scrollend, IntersectionObserver). Zero dependencies.
  • node --test scripts/page-scripts.test.mjs — static gate over every committed HTML page: each inline <script> parses, each JSON-LD block is valid schema.org JSON, no external <script src> is introduced, and sitemap.xml lists exactly the canonical top-level pages (redirect shortcuts excluded, new pages required). Zero dependencies.
  • node --test scripts/page-markup.test.mjs — static markup gate over every committed non-redirect HTML page: ids are unique, every ARIA idref (aria-controls, aria-labelledby, aria-describedby, …) and label for resolves to an id on the page, every <img> has alt, <html> declares lang, role="tab"/"tabpanel" carry their ARIA pair, and every [data-*] selector an inline script queries exists in the markup (so a dropped attribute cannot make a carousel silently no-op). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/page-structure.test.mjs — static tree gate over every committed HTML page (redirect shortcuts and 404.html included). Browsers never reject malformed HTML, they repair it silently, so the gate parses each page the way the HTML tokenizer does (comments, raw-text <script>/<style>/<textarea>/<title> bodies, quoted attributes, the spec's optional end tags for <li>/<p>/<option>/table parts, foreign content for inline SVG) and fails on anything a browser would have to repair: a stray or mismatched end tag, an element never closed, </br> or a self-closing <div/>, a block element inside <p> (which leaves its </p> stray), an attribute repeated on one element (the second is dropped), a raw </> inside an attribute value (which truncates the tag every sibling gate tokenizes with [^>]*), <li>/<option>/<tr>/<figcaption>/… outside their required parent, interactive content nested inside <a>/<button>/<label>, non-metadata content in <head>, and a page without exactly one <html>, <head> and <body> (plus exactly one <main> on non-redirect pages). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/style-contract.test.mjs — static gate over style.css (every local stylesheet the pages link) and the pages' inline <style> blocks: comments, strings, braces and parens balance and every declaration is name: value; every var(--x) without a fallback names a custom property defined somewhere (stylesheet, inline style=, or a script setProperty); every [data-*] selector in CSS matches an element on some page; every class an inline script adds/toggles is styled by a rule (or read back by the script); every custom property a script sets (--hero-h) is read by CSS; every local url() (self-hosted @font-face files, images) names a committed file whose magic bytes match its format() hint or extension; and every font file under assets/fonts/ is referenced by some url(). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/page-images.test.mjs — static gate over every local image the pages embed (<img src>/srcset, icon and preload as="image" <link>s, og:image): each is a committed, non-empty file whose magic bytes match its extension (a PNG re-exported as SVG under the old .png name fails); every <img> with width/height declares the file's intrinsic aspect ratio (PNG IHDR, JPEG SOF, GIF header, SVG viewBox) and is not drawn larger than a raster's pixels; every <img> SVG has a root viewBox; and every image file under assets/ is referenced by some page or stylesheet url(). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/page-meta.test.mjs — static gate over every page's <head> and the Markdown/llms.txt documents: each canonical page has exactly one <title>, a description, charset/viewport, a canonical that matches the path the page is served at, og:url equal to it, the full Open Graph + Twitter card set with og:*/twitter:* pairs in agreement, no duplicated meta, no noindex; og:image is a committed file whose PNG header matches any declared og:image:width/height; each redirect page is noindex with a canonical equal to its refresh target; and every relative Markdown link and hivecommons.dev URL in README.md, runbooks/*.md and llms.txt resolves to a committed file. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/page-404.test.mjs — static gate over the custom error page, which page-meta.test.mjs deliberately skips. GitHub Pages serves /404.html for every unknown path at any depth, so the page must live at the repository root and nowhere else, keep exactly one noindex robots meta, carry no canonical/og:*/twitter:* identity and no meta-refresh, use only root-absolute or external href/src (a relative style.css breaks under /some/deep/path), link back to /, resolve every root-absolute reference to a committed file, and keep body text that scripts/check-links.sh's SOFT_404_RE matches (so a misrouted URL serving the page with HTTP 200 is still flagged); no other page may match that regex. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/story-cards.test.mjs — static gate over every <article class="story-card"> in stories/index.html, which are hand-copied per PR: the avatar src, its alt, the handle link href and its text all name the same GitHub handle; the avatar keeps loading="lazy", referrerpolicy="no-referrer", width/height and the onerror hide; exactly one <h3>; at least one <a class="inline-link"> pointing at a GitHub pull/issue/commit; every link in the card is https://github.com/… (the page promises public GitHub evidence only); every Month D, YYYY is a real date; no handle has two cards. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/page-csp.test.mjs — static gate over the <meta http-equiv="Content-Security-Policy"> on every non-redirect page. GitHub Pages cannot send response headers, so the policy ships as a <meta> tag and inline scripts are allow-listed by sha256- hash: the test recomputes the hash of every inline <script> body and on*= handler and fails when the policy is missing one or carries a stale one (a drifted hash silently disables that script in every browser — after editing any inline script, update its hash in the page's CSP meta). It also requires default-src 'none', rejects 'unsafe-inline'/'unsafe-eval' in script-src, requires the meta to precede every <script>/<link> in <head>, and requires every external <img> origin to appear in img-src. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/llms-txt.test.mjs — static gate keeping llms.txt in step with index.html: the agent CLIs it names must equal the Agent CLIs chips, the inference engines/gateways it names must equal the engine and gateway chips (classifier chips excluded), and its infrastructure thanks must equal the infra-thanks logo labels — in both directions, so adding, renaming or dropping a chip without updating llms.txt fails CI. Also requires the "See all integrations" docs URL to appear in llms.txt. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/jsonld-contract.test.mjs — static gate keeping the schema.org JSON-LD on index.html in step with the page it describes (page-scripts.test.mjs only checks that it parses): exactly one application/ld+json graph with @context https://schema.org; the Organization's sponsor and funder lists are identical and name exactly the infra-thanks logos (label minus its parenthetical, e.g. Akamai (Linode) → Akamai) with each url equal to that logo chip's link; Organization.url is the site root and logo an absolute site URL; the Hive SoftwareApplication.keywords names every integration chip (classifier chips included), every keyword is a chip or visible page text (case-insensitive, plural allowed), none repeats, and every name an including … list in featureList enumerates is a chip; and every url, codeRepository, sameAs and sponsor url is https and linked by an href somewhere on the page (trailing-slash differences ignored). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/availability-probes.test.mjs — static gate over the URL list the scheduled availability job in links.yml probes: every probed URL is https, under hivecommons.dev, carries its trailing slash when it is a directory page (GitHub Pages answers 301 for /docs, which curl without -L reports as a failure) and resolves to a committed page; every canonical page in sitemap.xml and /404.html is probed; at least one redirect shortcut is probed; no duplicates. Fixing a failure means editing the workflow's probe list. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/site-origin.test.mjs — static gate tying the site origin to CNAME, the one file GitHub Pages actually reads for the host: CNAME must be a single bare lowercase DNS host (no scheme, path, port, trailing dot, second line or CRLF); every SITE_ORIGIN constant the other gates hardcode, every sitemap.xml <loc>, the robots.txt Sitemap: URL and every canonical page's <link rel="canonical">/og:url must be at https://<CNAME>; and no committed page, stylesheet or text asset may link the hivecommons.github.io fallback host (which bypasses the custom domain). Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/redirect-targets.test.mjs — static gate over what a browser makes of each shortcut-redirect page. make-redirects.sh interpolates every MAP url and label into HTML through its html_escape(), so the gate parses the MAP, rejects any url or label that carries ", < or > or a label that decodes as a character reference (defense in depth: nothing a shortcut target needs), and then decodes each committed page's refresh url=, canonical href and <a href> under HTML attribute rules (legacy no-semicolon entities such as &para, &reg, &copy included) and its <title>/link text under text rules, requiring each to resolve to exactly the MAP url/label; any other ambiguous ampersand on the page is reported (&amp;, &lt;, &gt; and &quot; — what html_escape() emits — are the accepted escapes). It also runs the real generator body against a hostile fixture MAP (raw & separators, legacy/numeric references, ", <, > in url and label) in a scratch directory and requires every emitted page to decode back to exactly its entry, so html_escape() is exercised directly rather than only through the characters the committed MAP happens to contain. Each rule has a fixture self-test. Zero dependencies.
  • scripts/check-redirects.sh — redirect-page drift gate described above.
  • scripts/check-redirects.test.sh — fixture-based self-test of the drift gate; runs offline against throwaway sites with a two-entry generator.
  • node --test scripts/ci-wiring.test.mjs — static gate keeping links.yml, scripts/ and this list in step: every scripts/*.sh gate and *.test.sh self-test is run by a run: step in a job that runs on every PR/push (they are listed by hand, unlike the node --test scripts/*.test.mjs glob, which must itself be present and run on every PR/push). A job-level if: counts as a gate only when it can skip a push or pull_request event: scripts/actions-if.mjs evaluates the expression for both, so the github.event_name != 'schedule' || … trim that lets the 6-hourly cron run availability alone is accepted, while an unrecognised expression is not; every scripts/*.sh gate has a sibling self-test; no .mjs that imports node:test sits outside the glob's *.test.mjs name; the workflow runs on pull_request and on push to main; every shell script is executable; and this ## Checks section names every gate and self-test. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/workflow-docs.test.mjs — static gate keeping the prose about links.yml in step with it: in this README and runbooks/*.md, the workflow name must match the workflow's name:; every job the docs name must exist under jobs:; jobs the docs say run on every PR/push must have no if:, or one that scripts/actions-if.mjs evaluates true for both push and pull_request, and the ones they call weekly-only or manual-only must carry an if: on schedule / workflow_dispatch (which the workflow must declare); every weekday and HH:MM UTC must match the cron: expression; and the --external-warn flag must be what the workflow passes outside schedule/dispatch and what scripts/check-links.sh accepts. Each rule has a fixture self-test. Zero dependencies.
  • node --test scripts/automation-docs.test.mjs — static gate keeping the prose about every workflow under .github/workflows/ in step with it. Wherever this README or runbooks/*.md introduces a workflow as **<name>** … (.github/workflows/), the file must be committed and its name: must equal the bold text, and the introducing paragraph's claims must match the triggers: "push to main" needs a push trigger covering main; "every pull request" needs pull_request; "weekly" needs a schedule with a plain weekly cron; a literal cron `M H * * D` must equal the workflow's cron:; "manual dispatch" needs workflow_dispatch; back-ticked pull request activity types (closed, …) must be exactly pull_request.types; and "code scanning" needs a github/codeql-action/upload-sarif step. Every committed workflow must be introduced that way in this README, so new automation cannot land undocumented. Each rule has a fixture self-test. Zero dependencies.

Local preview and running the checks

Prerequisites: Python 3 (any recent version) for previewing, and Node.js (the node --test runner) for the gates; no npm install is needed.

python3 -m http.server 8000     # then open http://localhost:8000/
node --test scripts/*.test.mjs  # every Node gate (what CI runs)
scripts/check-links.test.sh     # link-checker self-test (offline)
scripts/check-redirects.test.sh # redirect-gate self-test (offline)
scripts/check-redirects.sh      # redirect-page drift gate

Run these from the repository root before opening a PR. The previewed pages are served from the checkout as-is, so root-absolute links (/stories/) resolve locally the same way they do on the live site. Each gate is described under Checks.

Availability monitoring

The Link check workflow runs every Monday at 09:17 UTC, every 6 hours for the availability probe alone, and can also be run manually from the Actions tab. On those runs, its separate availability job requests the live homepage, /stories/, a sample of the shortcut redirects and /404.html over HTTPS and fails unless every one returns HTTP 200 (the list is kept in step with the committed pages by scripts/availability-probes.test.mjs). Connection/TLS errors and timeouts also fail the job. Requests have bounded retries for transient failures. PR and push-to-main runs only check the checkout; they do not probe the production site.

Review failed runs in Actions and configure GitHub Actions notifications for the workflow if you operate the site. See the rollback runbook for investigation and recovery. This 6-hourly probe is a basic availability signal, not continuous uptime monitoring or a check after every deployment. The 6-hourly runs skip the heavier jobs; the full link check runs weekly. External link failures remain warnings in the separate links job.

Traffic analytics and shortcut usage tracking are not configured. Adding them requires an operator to choose a backend/property and settle privacy and consent requirements first (see issue #73).

Repository automation

OpenSSF Scorecard (.github/workflows/scorecard.yml) — Runs OpenSSF security scorecard analysis on every push to main, weekly (cron 23 5 * * 1), and on manual dispatch from the Actions tab. Results are published to GitHub's code scanning dashboard.

Close linked issues (.github/workflows/close-linked-issues.yml) — Automatically closes issues linked to a closed pull request when a PR transitions to closed.

Incident response — When a bad deploy or incident impacts visitors of hivecommons.dev (broken pages, dead redirects, domain issues), use the postmortem template to document it blamlessly and fact-based. Coordinate recovery using the release-rollback runbook.

Code of Conduct

Hive Commons website contributors are expected to follow the CNCF Code of Conduct.

About

hivecommons.dev — placeholder site (GitHub Pages)

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages