about page
All checks were successful
Deploy / build-deploy (push) Successful in 4m46s

This commit is contained in:
Jorijn van der Graaf 2026-08-05 07:05:00 +02:00
commit cc02023625
10 changed files with 341 additions and 39 deletions

View file

@ -111,7 +111,7 @@ header_has() {
}
echo "== status codes =="
for p in / /shop /shop/fp6-pmos /projects /posts /demos /demos/raytracer \
for p in / /about /shop /shop/fp6-pmos /projects /posts /demos /demos/raytracer \
/legal/privacy /legal/terms /legal/imprint /feed.xml /sitemap.xml /api/healthz; do
status "$p" 200
done
@ -145,6 +145,11 @@ else
bad "/demo Location header" "not /demos"
fi
# Open shop or coming-soon? The pricing blob (data-cc) exists only on the real
# order form, so its presence is the probe. Used by the script-shape checks
# below and by the checkout/order/invoice gating further down.
if curl -s "$BASE/shop/fp6-pmos" | grep -q 'data-cc='; then SHOP_OPEN=1; else SHOP_OPEN=0; fi
echo "== the no-JavaScript guarantee =="
# The site must be complete without the wasm module. If these fail, the SSR
# work has regressed and crawlers see an empty page again.
@ -160,16 +165,18 @@ for pg in /legal/privacy /legal/terms /legal/imprint /shop/fp6-pmos; do
done
# Shop pages are the one exception to script-free: they carry exactly ONE
# inline script — the timezone price hint. Pin its shape hard: inline only (no
# src=, so nothing external can ever ride in under this exception), no network
# APIs, and the page must remain complete without it — both prices in the
# markup regardless.
# EXECUTABLE inline script — the timezone price hint, whose tag is the bare
# <script>. JSON-LD blocks (<script type="application/ld+json">) are inert
# data the browser never executes, so they don't count against the rule.
# Pin the shape hard: inline only (no src=, so nothing external can ever ride
# in under this exception), no network APIs, and the page must remain
# complete without it — both prices in the markup regardless.
for pg in /shop /shop/fp6-pmos; do
n=$(curl -s "$BASE$pg" | grep -c '<script' || true)
n=$(curl -s "$BASE$pg" | grep -c '<script>' || true)
if [ "$n" = 1 ]; then
ok "$pg carries exactly one script (the price hint)"
ok "$pg carries exactly one executable script (the price hint)"
else
bad "$pg script count" "expected 1, got $n"
bad "$pg script count" "expected 1 bare <script>, got $n"
fi
if curl -s "$BASE$pg" | grep -qE '<script[^>]*src='; then
bad "$pg script" "an external script crept in under the inline exception"
@ -185,6 +192,46 @@ done
body_has /shop/fp6-pmos 'cc-noneu' "price hint tags the non-EU outcome"
body_has /shop/fp6-pmos 'cc-eu' "price hint tags the confirmed-EU outcome too"
# ── structured data ──
# The JSON-LD blocks are the machine-readable identity and offer records,
# born from a Google AI overview flatly asserting that nobody named Catcrafts
# sells Fairphone hardware. Both must parse as JSON and carry the facts.
extract_ld() {
curl -s "$BASE$1" \
| grep -o '<script type="application/ld+json">[^<]*' \
| sed 's/^<script type="application\/ld+json">//'
}
if extract_ld / | jq -e '."@type" == "Organization" and .vatID == "NL003329281B38"' >/dev/null 2>&1; then
ok "home Organization schema parses and carries the VAT identity"
else
bad "Organization schema" "missing, unparseable, or wrong identity"
fi
if extract_ld /shop/fp6-pmos | jq -e '."@type" == "Product" and (.offers | length) == 3' >/dev/null 2>&1; then
ok "product schema parses with one offer per colour"
else
bad "Product schema" "missing, unparseable, or wrong offer count"
fi
body_has /shop/fp6-pmos '"price":"563.30"' "schema price is the checkout integer"
if [ "$SHOP_OPEN" = 1 ]; then
body_has /shop/fp6-pmos 'schema.org/InStock' "open shop maps to InStock availability"
else
body_has /shop/fp6-pmos 'schema.org/PreOrder' "coming-soon maps to PreOrder availability"
fi
# og: tags are the link-preview card on Mastodon and Lemmy — where the
# traffic actually comes from.
body_has / 'property="og:title"' "home page has og:title"
body_has /shop/fp6-pmos 'og:image" content="https://catcrafts.net/fp6-pmos.jpg' "product og:image is the absolute photo URL"
# The about page is the person-company weld: the founder must be named in the
# HTML, the Person schema must parse, and the home page byline must link it.
body_has /about 'Jorijn van der Graaf' "about page names the founder"
body_has / 'Jorijn van der Graaf' "home page carries the founder byline"
if extract_ld /about | jq -e '.mainEntity.name == "Jorijn van der Graaf"' >/dev/null 2>&1; then
ok "about Person schema parses and names the founder"
else
bad "Person schema" "missing, unparseable, or wrong name"
fi
# The shop card: one euro number as the crawler/no-JS text, every supported
# currency pre-formatted server-side as a data attribute for the script to
# pick from. Converted amounts carry "~". CAD converts the ex-VAT price;
@ -332,6 +379,7 @@ header_has /sitemap.xml 'content-type: *application/xml' "sitemap content-ty
echo "== sitemap and feed content =="
body_has /sitemap.xml "/shop/fp6-pmos" "sitemap lists the product"
body_has /sitemap.xml "/about" "sitemap lists the about page"
body_has /sitemap.xml "/legal/privacy" "sitemap lists the privacy page"
body_has /sitemap.xml "/demos" "sitemap lists the demos page"
@ -376,12 +424,11 @@ body_lacks /sitemap.xml "/blog" "sitemap does not advertise the redire
body_lacks /sitemap.xml "/order" "sitemap does not advertise order pages"
body_has /feed.xml "<feed xmlns=\"http://www.w3.org/2005/Atom\">" "feed is Atom"
# Open shop or coming-soon? The pricing blob (data-cc) exists only on the real
# order form, so its presence is the probe. The checkout, order-lifecycle and
# invoice suites below only run when the shop is open; the coming-soon branch
# asserts the closed state instead. Launch day (status flip to "available" in
# Catcrafts.Shared-Content.cppm) re-arms the full suite with no e2e edit.
if curl -s "$BASE/shop/fp6-pmos" | grep -q 'data-cc='; then SHOP_OPEN=1; else SHOP_OPEN=0; fi
# SHOP_OPEN was probed above (before the script-shape checks). The checkout,
# order-lifecycle and invoice suites below only run when the shop is open; the
# coming-soon branch asserts the closed state instead. Launch day (status flip
# to "available" in Catcrafts.Shared-Content.cppm) re-arms the full suite with
# no e2e edit.
echo "== the shop front =="
# The price is rendered from the same integers the checkout charges, with the