mykiwi/mykiwi.blogpublic Fork
⑂ 8804fce
Commits
⬇ Clone ▾
git clone https://git.rickub.com/mykiwi/mykiwi.blog.git
git clone ssh://git@rickub.com/mykiwi/mykiwi.blog.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Give each og-card screenshot its own port, and Japanese a font to fall back to

Two bugs in flake.nix's og-card build step, both silent because Chromium
and the static file server it screenshots against have their stderr
thrown away:

- All 5 languages shared one port (8971) across the build loop. When the
  previous language's server hadn't released it in time, the next
  `python3 -m http.server` failed to bind and every screenshot after that
  point silently landed on the *previous* language's still-running server
  instead - fr.mykiwi.blog/.../og-card.png ended up rendering the Spanish
  page. Each language now gets its own port, so there is nothing left to
  race.

- The sandboxed Chromium has no system fonts of its own, so ja's kicker
  text (JetBrains Mono has no CJK glyphs) rendered as tofu boxes instead
  of falling back the way a real visitor's browser does. ipaexfont
  (~9MB, Japanese-only) is now registered via a generated fonts.conf,
  reached only for codepoints neither self-hosted font covers - no change
  for en/es/fr/pt.
Romain Gautier committed 2026-09-23T09:11:49+02:00 Browse files
8804fce parent: 45af4c3
modified flake.nix +44 -1
@@ -15,6 +15,16 @@
1515 chromium = pin.version "chromium" "153.0.8010.36";
1616 imagemagick = pkgs.imagemagick;
1717 python3 = pkgs.python3;
18+ # A visitor's own OS always supplies *some* CJK fallback font for the
19+ # ja site's kicker text (JetBrains Mono itself has no CJK glyphs at
20+ # all), so this never came up until a real page was rendered by a
21+ # browser with no system fonts of its own to fall back to: the ja
22+ # og-card.png showed tofu boxes instead of "1分で読了" and friends.
23+ # IPAex Gothic is small (~9MB) and just for that fallback - it is
24+ # never the requested font-family, only what fontconfig reaches for
25+ # once Newsreader/JetBrains Mono (self-hosted, already covering every
26+ # other language here) come up short on a codepoint.
27+ ipaexfont = pin.version "ipaexfont" "004.01";
1828 in
1929 {
2030 packages.${system}.default = pkgs.stdenvNoCC.mkDerivation {
@@ -73,8 +83,41 @@
7383 # this is one more, not a new problem.
7484 langs="en es fr pt ja"
7585 export HOME="$TMPDIR"
76- port=8971
86+
87+ # Chromium's font fallback goes through fontconfig, which has
88+ # nothing to search by default in this sandbox - not even the
89+ # site's own self-hosted webfonts, which are @font-face rules the
90+ # page fetches over HTTP, unrelated to what the OS/fontconfig
91+ # supplies. ipaexfont is registered here, once, for every
92+ # language's screenshots: it only ever gets reached for a
93+ # codepoint neither self-hosted font covers (CJK), so it changes
94+ # nothing for en/es/fr/pt.
95+ mkdir -p "$TMPDIR/fontconfig-cache"
96+ # Unindented on purpose: a heredoc terminator has to start in
97+ # column 0 (bash strips leading *tabs* with <<-, not the spaces
98+ # this file otherwise uses throughout).
99+ cat > "$TMPDIR/fonts.conf" <<FONTCONF
100+<?xml version="1.0"?>
101+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
102+<fontconfig>
103+<dir>${ipaexfont}/share/fonts/truetype</dir>
104+<cachedir>$TMPDIR/fontconfig-cache</cachedir>
105+</fontconfig>
106+FONTCONF
107+ export FONTCONFIG_FILE="$TMPDIR/fonts.conf"
108+
109+ # A distinct port per language, not one reused across the loop:
110+ # reusing one, an earlier build hit a silent race where the next
111+ # language's `python3 -m http.server` failed to bind (the previous
112+ # one not yet torn down) and every screenshot after that point
113+ # silently landed on the *previous* language's still-running
114+ # server instead - fr.mykiwi.blog's card came out in Spanish.
115+ # stderr is thrown away below because Chromium is noisy on stdout
116+ # even on success, so that failure mode raised no error either.
117+ # One port per language means there is nothing left to race.
118+ port=8970
77119 for lang in $langs; do
120+ port=$((port + 1))
78121 root="$out/$lang"
79122 python3 -m http.server "$port" --bind 127.0.0.1 --directory "$root" \
80123 >/dev/null 2>&1 &
@@ -15,6 +15,16 @@
15 chromium = pin.version "chromium" "153.0.8010.36";15 chromium = pin.version "chromium" "153.0.8010.36";
16 imagemagick = pkgs.imagemagick;16 imagemagick = pkgs.imagemagick;
17 python3 = pkgs.python3;17 python3 = pkgs.python3;
18+ # A visitor's own OS always supplies *some* CJK fallback font for the
19+ # ja site's kicker text (JetBrains Mono itself has no CJK glyphs at
20+ # all), so this never came up until a real page was rendered by a
21+ # browser with no system fonts of its own to fall back to: the ja
22+ # og-card.png showed tofu boxes instead of "1分で読了" and friends.
23+ # IPAex Gothic is small (~9MB) and just for that fallback - it is
24+ # never the requested font-family, only what fontconfig reaches for
25+ # once Newsreader/JetBrains Mono (self-hosted, already covering every
26+ # other language here) come up short on a codepoint.
27+ ipaexfont = pin.version "ipaexfont" "004.01";
18 in28 in
19 {29 {
20 packages.${system}.default = pkgs.stdenvNoCC.mkDerivation {30 packages.${system}.default = pkgs.stdenvNoCC.mkDerivation {
@@ -73,8 +83,41 @@
73 # this is one more, not a new problem.83 # this is one more, not a new problem.
74 langs="en es fr pt ja"84 langs="en es fr pt ja"
75 export HOME="$TMPDIR"85 export HOME="$TMPDIR"
76- port=897186+
87+ # Chromium's font fallback goes through fontconfig, which has
88+ # nothing to search by default in this sandbox - not even the
89+ # site's own self-hosted webfonts, which are @font-face rules the
90+ # page fetches over HTTP, unrelated to what the OS/fontconfig
91+ # supplies. ipaexfont is registered here, once, for every
92+ # language's screenshots: it only ever gets reached for a
93+ # codepoint neither self-hosted font covers (CJK), so it changes
94+ # nothing for en/es/fr/pt.
95+ mkdir -p "$TMPDIR/fontconfig-cache"
96+ # Unindented on purpose: a heredoc terminator has to start in
97+ # column 0 (bash strips leading *tabs* with <<-, not the spaces
98+ # this file otherwise uses throughout).
99+ cat > "$TMPDIR/fonts.conf" <<FONTCONF
100+<?xml version="1.0"?>
101+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
102+<fontconfig>
103+<dir>${ipaexfont}/share/fonts/truetype</dir>
104+<cachedir>$TMPDIR/fontconfig-cache</cachedir>
105+</fontconfig>
106+FONTCONF
107+ export FONTCONFIG_FILE="$TMPDIR/fonts.conf"
108+
109+ # A distinct port per language, not one reused across the loop:
110+ # reusing one, an earlier build hit a silent race where the next
111+ # language's `python3 -m http.server` failed to bind (the previous
112+ # one not yet torn down) and every screenshot after that point
113+ # silently landed on the *previous* language's still-running
114+ # server instead - fr.mykiwi.blog's card came out in Spanish.
115+ # stderr is thrown away below because Chromium is noisy on stdout
116+ # even on success, so that failure mode raised no error either.
117+ # One port per language means there is nothing left to race.
118+ port=8970
77 for lang in $langs; do119 for lang in $langs; do
120+ port=$((port + 1))
78 root="$out/$lang"121 root="$out/$lang"
79 python3 -m http.server "$port" --bind 127.0.0.1 --directory "$root" \122 python3 -m http.server "$port" --bind 127.0.0.1 --directory "$root" \
80 >/dev/null 2>&1 &123 >/dev/null 2>&1 &