diff --git a/flake.nix b/flake.nix
index 9f10aef5ef4a2259112b029436934f116373f22f..baa94861ed0d8e1306d74cbbeb3d68e3c770274e 100644
--- a/flake.nix
+++ b/flake.nix
@@ -11,31 +11,32 @@
       let pkgs = nixpkgs.legacyPackages.${system}; in
       rec {
         packages = rec {
-          google_fonts = pkgs.fetchFromGitHub {
-            owner = "google";
-            repo = "fonts";
-            rev = "2fba0d68602b7eb3374d030c1c34939de56023f9";
-            sha256 = "sha256-IFkKwRRyZeOXD8/9n8UDrruUKK6oQK4BD9wYN2dmSAc=";
-          };
           generator = pkgs.stdenv.mkDerivation rec {
             name = "generator";
             version = "0.0.0";
             src = ./src/index.html;
+            src-font = ./src/font;
+            src-template = ./src/svg_templates;
             dontUnpack = true;
             buildPhase = ''
               cp ${src} index.html
               substituteInPlace index.html \
                 --replace "@SVG_BIG_TEMPLATE@" \
-                          "$(base64 -w0 ${svg_templates}/logo_big_template.svg)"
+                          "$(base64 -w0 ${src-template}/logo_big_template.svg)"
               substituteInPlace index.html \
                 --replace "@SVG_SMALL_TEMPLATE@" \
-                          "$(base64 -w0 ${svg_templates}/logo_small_template.svg)"
+                          "$(base64 -w0 ${src-template}/logo_small_template.svg)"
             '';
             installPhase = ''
-              mkdir -p $out $out/img $out/font
+              mkdir -p $out $out/img $out/font $out/js
               cp index.html $out/index.html
+              cp ${opentype_js} $out/js/opentype.min.js
               cp ${favicon}/favicon.svg ${favicon}/favicon.png $out/img
-              cp ${google_fonts}/ufl/ubuntumono/UbuntuMono-Regular.ttf ${google_fonts}/ufl/ubuntu/Ubuntu-Regular.ttf ${google_fonts}/ufl/ubuntu/Ubuntu-Bold.ttf $out/font
+              # bundle the Genos-Bold font, since opentype.js can't work with the
+              # variable-width version that's included in google fonts
+              cp ${google_fonts}/ufl/ubuntumono/UbuntuMono-Regular.ttf ${google_fonts}/ufl/ubuntu/Ubuntu-Regular.ttf ${google_fonts}/ufl/ubuntu/Ubuntu-Bold.ttf \
+                ${google_fonts}/ofl/notosansjp/NotoSansJP-Black.otf ${src-font}/Genos-Bold.ttf \
+                $out/font
             '';
           };
           favicon = pkgs.stdenv.mkDerivation rec {
@@ -50,22 +51,15 @@
               cp favicon.png $out/
             '';
           };
-          svg_templates = pkgs.stdenv.mkDerivation rec {
-            name = "generator";
-            version = "0.0.0";
-            src = ./src/svg_templates;
-            buildPhase = ''
-              substituteInPlace logo_big_template.svg \
-                --replace "@GENOS_FONT@" \
-                          "$(base64 -w0 ${google_fonts}/ofl/genos/Genos\[wght\].ttf)"
-              substituteInPlace logo_big_template.svg \
-                --replace "@NOTO_SANS_JP_FONT@" \
-                          "$(base64 -w0 ${google_fonts}/ofl/notosansjp/NotoSansJP-Black.otf)"
-            '';
-            installPhase = ''
-              mkdir -p $out
-              cp logo_big_template.svg logo_small_template.svg $out/
-            '';
+          opentype_js = pkgs.fetchurl {
+            url = "https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js";
+            sha256 = "sha256-wPnHyoXhgHWogZ5f4t7m4dU1+aImn1MU82zOlKGDrbo=";
+          };
+          google_fonts = pkgs.fetchFromGitHub {
+            owner = "google";
+            repo = "fonts";
+            rev = "2fba0d68602b7eb3374d030c1c34939de56023f9";
+            sha256 = "sha256-IFkKwRRyZeOXD8/9n8UDrruUKK6oQK4BD9wYN2dmSAc=";
           };
         };
         defaultPackage = packages.generator;
diff --git a/src/font/Genos-Bold.ttf b/src/font/Genos-Bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..9520b5c694e6d3ea2f4aed904939b94c5ec81e47
Binary files /dev/null and b/src/font/Genos-Bold.ttf differ
diff --git a/src/index.html b/src/index.html
index d16f9964b927bdc6cc0be516837ad3289b7e490b..79dbeee2cc573c5a850edfd74769f10a01a27f37 100644
--- a/src/index.html
+++ b/src/index.html
@@ -263,8 +263,14 @@
             }
         }
     </style>
+    <script src="js/opentype.min.js"></script>
     <script>
-        onhtmlload = () => {
+         onhtmlload = () => {
+             opentype.load('font/NotoSansJP-Black.otf', (err, notosans) =>
+             opentype.load("font/Genos-Bold.ttf", (err, genos) => main(genos, notosans)))
+         };
+         main = (genos, notosans) => {
+
             svg_big = new DOMParser().parseFromString(atob("@SVG_BIG_TEMPLATE@"), "image/svg+xml").querySelector("svg");
             svg_small = new DOMParser().parseFromString(atob("@SVG_SMALL_TEMPLATE@"), "image/svg+xml").querySelector("svg");
 
@@ -351,11 +357,23 @@
                 // Only show the selected animal
                 [svg_big, svg_small].forEach((e) => e.querySelectorAll(".animal").forEach((e) => e.style.display = e.id === animal_selected ? "inline" : "none"));
 
-                // Set the headline
-                svg_big.querySelector("#headline").innerHTML = headline_text;
+                // we don't have any alignment, so center the text by hand
+                let centered_text_path = (font, text, y, fontsize) => {
+                    let box = font.getPath(text, 0,0, fontsize).getBoundingBox();
+                    // 67.73333 mm is half the width of the svg
+                    return font.getPath(text, 67.73333-box.x2/2, y, fontsize).toSVG();
+                }
+
+                // Set the big headline (this id is the <g> tag of the default font,
+                // which was converted to a group of paths by inkscape)
+                svg_big.querySelector("#headline").innerHTML =
+                    centered_text_path(genos, headline_text, 107.123, 33.84);
 
                 // Set the sub headline, second line starts after the first newline
-                [0, 1].forEach((i) => svg_big.querySelectorAll("#sub_headlines tspan").item(i).innerHTML = sub_headline_texts.length > i ? sub_headline_texts[i] : "");
+                [0, 1].forEach((i) =>
+                    svg_big.querySelectorAll("#sub_headlines g").item(i).innerHTML =
+                        sub_headline_texts.length > i ? centered_text_path(notosans, sub_headline_texts[i], 122+15*i, 14) : ""
+                );
 
                 // Set all colors
                 apply_color = (selector, style_key, value) => [svg_big, svg_small].forEach((e) => e.querySelectorAll(selector).forEach((e) => e.style[style_key] = value));
diff --git a/src/svg_templates/logo_big_template.svg b/src/svg_templates/logo_big_template.svg
index 2f47aad3f76157bfc15ad095f2e6fb3e589f315e..d3995848d8175515ac708144b93368a7031d07dc 100644
--- a/src/svg_templates/logo_big_template.svg
+++ b/src/svg_templates/logo_big_template.svg
@@ -14,21 +14,6 @@
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:svg="http://www.w3.org/2000/svg">
-  <style
-     id="style1263">
-    @font-face {
-       font-family: &quot;Genos&quot;;
-       src: url('data:font/sfnt;base64,@GENOS_FONT@') format('truetype');
-       font-weight: bold;
-       font-style: normal;
-    }
-    @font-face {
-       font-family: &quot;Noto Sans JP&quot;;
-       src: url('data:application/vnd.ms-opentype;base64,@NOTO_SANS_JP_FONT@') format(&quot;opentype&quot;);
-       font-weight: 900;
-       font-style: normal;
-    }
-  </style>
   <sodipodi:namedview
      id="namedview1229"
      pagecolor="#505050"
@@ -150,36 +135,22 @@
      style="display:inline">
     <g
        id="sub_headlines">
-      <text
-         xml:space="preserve"
+      <g
+         aria-label="ブリッジ・バブルス"
          id="text111097-5-6"
-         style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:14.4514px;line-height:0.95;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP Heavy';text-align:center;letter-spacing:-0.777875px;text-anchor:middle;white-space:pre;display:inline;stroke-width:0.264583"
-         x="67.574364"
-         y="121.20871"><tspan
-           style="text-align:center;text-anchor:middle;fill:#62c1a6;stroke-width:0.264583"
-           id="tspan159496-9"
-           class="color_accent">ブリッジ・バブルス</tspan></text>
-      <text
-         xml:space="preserve"
+         style="font-weight:900;font-size:14.4514px;line-height:0.95;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP Heavy';text-align:center;letter-spacing:-0.777875px;text-anchor:middle;white-space:pre;display:inline;stroke-width:0.264583;fill:#62c1a6">
+      </g>
+      <g
+         aria-label="ブリッジ2バブルス"
          id="text111097-5"
-         style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:14.4514px;line-height:0.95;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP Heavy';text-align:center;letter-spacing:-0.777875px;text-anchor:middle;white-space:pre;display:inline;stroke-width:0.264583"
-         x="67.574364"
-         y="136.02525"><tspan
-           style="text-align:center;text-anchor:middle;fill:#62c1a6;stroke-width:0.264583"
-           id="tspan159500"
-           class="color_accent">ブリッジ2バブルス</tspan></text>
+         style="font-weight:900;font-size:14.4514px;line-height:0.95;font-family:'Noto Sans JP';-inkscape-font-specification:'Noto Sans JP Heavy';text-align:center;letter-spacing:-0.777875px;text-anchor:middle;white-space:pre;display:inline;stroke-width:0.264583;fill:#62c1a6">
+      </g>
+    </g>
+    <g
+       aria-label="DiVOC"
+       id="headline"
+       style="font-weight:bold;font-size:33.8435px;line-height:1.25;font-family:Genos;-inkscape-font-specification:'Genos Bold';text-align:center;text-anchor:middle;display:inline;fill:#ffebd8;stroke-width:0.441811">
     </g>
-    <text
-       xml:space="preserve"
-       style="font-size:33.8435px;line-height:1.25;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-align:center;text-anchor:middle;display:inline;fill:#ffebd8;fill-opacity:1;stroke-width:0.441811"
-       x="67.327217"
-       y="107.12258"
-       id="text111095"><tspan
-         sodipodi:role="line"
-         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Genos;-inkscape-font-specification:'Genos Bold';text-align:center;text-anchor:middle;fill:#ffebd8;fill-opacity:1;stroke-width:0.441811"
-         x="67.327217"
-         y="107.12258"
-         id="headline">DiVOC</tspan></text>
   </g>
   <g
      inkscape:groupmode="layer"