From c3b2d89ddc0f2ed65a19beaa88d16c97aaabcece Mon Sep 17 00:00:00 2001 From: Oier Bravo Urtasun Date: Wed, 10 Jun 2026 22:17:52 +0200 Subject: [PATCH] feat(landing): switch heading font to Block Blueprint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace Pixelify Sans with Block Blueprint as the heading font (theme.headFont). Block Blueprint isn't on Google Fonts, so it's vendored straight from 1001fonts (License: 1001Fonts Free For Personal Use — fine for this private friends' server) as a TTF, with a hand-written @font-face appended to fonts.css. The vendor step is added to fetch-fonts.sh (runs after the Google rewrite so it survives re-runs). Pixelify stays available as a HEAD_FONTS option + the hard-coded fallback. Co-Authored-By: Claude Opus 4.8 --- landing/public/fonts/BlockBlueprint.ttf | Bin 0 -> 67844 bytes landing/public/fonts/fonts.css | 10 +++++++++ landing/src/data/site.ts | 5 +++-- tooling/fetch-fonts.sh | 26 ++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 landing/public/fonts/BlockBlueprint.ttf diff --git a/landing/public/fonts/BlockBlueprint.ttf b/landing/public/fonts/BlockBlueprint.ttf new file mode 100644 index 0000000000000000000000000000000000000000..17afc37235b4b7b7139b805aee5077860915efcd GIT binary patch literal 67844 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 = { + blockblueprint: "'Block Blueprint', system-ui, sans-serif", pixelify: "'Pixelify Sans', system-ui, sans-serif", "8bit": "'Press Start 2P', monospace", silkscreen: "'Silkscreen', system-ui, sans-serif", diff --git a/tooling/fetch-fonts.sh b/tooling/fetch-fonts.sh index ff74dcf..5155a91 100755 --- a/tooling/fetch-fonts.sh +++ b/tooling/fetch-fonts.sh @@ -41,4 +41,30 @@ echo "→ writing fonts.css (URLs rewritten to /fonts/…)" # Rewrite absolute gstatic URLs to local /fonts/. echo "$raw" | sed -E 's#https://fonts\.gstatic\.com/[^)]+/([^)/]+\.woff2)#/fonts/\1#g' > "$out/fonts.css" +# Block Blueprint — the heading font. NOT on Google Fonts, so it can't ride the +# css2 request above; vendored straight from 1001fonts (License: 1001Fonts Free +# For Personal Use — fine for this private friends' server). TTF only, no woff2 +# (no woff2 toolchain assumed). Appended AFTER the rewrite so it survives re-runs. +echo "→ vendoring Block Blueprint (1001fonts)" +bb_ttf="$out/BlockBlueprint.ttf" +if [ ! -f "$bb_ttf" ]; then + tmpzip="$(mktemp)" + curl -fsSL -A "$UA" -o "$tmpzip" "https://www.1001fonts.com/download/blockblueprint.zip" + unzip -p "$tmpzip" BlockBlueprint.ttf > "$bb_ttf" + rm -f "$tmpzip" + echo " BlockBlueprint.ttf" +fi +cat >> "$out/fonts.css" <<'EOF' +/* Block Blueprint — vendored from 1001fonts (NOT on Google Fonts; appended by + fetch-fonts.sh after the Google rewrite). License: 1001Fonts Free For Personal + Use. Single weight, TTF (no woff2 toolchain on the build box). */ +@font-face { + font-family: 'Block Blueprint'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/fonts/BlockBlueprint.ttf) format('truetype'); +} +EOF + echo "✓ fonts vendored into $out"