diff --git a/.gitignore b/.gitignore
index a136337..5467d5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
+# typst
 *.pdf
+
+# Nix
+/result
diff --git a/flake.lock b/flake.lock
index 4b40286..06b249f 100644
--- a/flake.lock
+++ b/flake.lock
@@ -37,7 +37,9 @@
     "root": {
       "inputs": {
         "flake-utils": "flake-utils",
-        "nixpkgs": "nixpkgs"
+        "nixpkgs": "nixpkgs",
+        "typix": "typix",
+        "typst-packages": "typst-packages"
       }
     },
     "systems": {
@@ -54,6 +56,42 @@
         "repo": "default",
         "type": "github"
       }
+    },
+    "typix": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1738982361,
+        "narHash": "sha256-QWDOo/+9pGu63knSlrhPiESSC+Ij/QYckC3yH8QPK4k=",
+        "owner": "loqusion",
+        "repo": "typix",
+        "rev": "bdb42d3e9a8722768e2168e31077129207870f92",
+        "type": "github"
+      },
+      "original": {
+        "owner": "loqusion",
+        "repo": "typix",
+        "type": "github"
+      }
+    },
+    "typst-packages": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1739953413,
+        "narHash": "sha256-wwMCLTFWEJvyQZMZ+N30LrG9w6FfoWfp9tzCt4BXFQc=",
+        "owner": "typst",
+        "repo": "packages",
+        "rev": "7752964daa3196be81af765fa0dedb7b3661da22",
+        "type": "github"
+      },
+      "original": {
+        "owner": "typst",
+        "repo": "packages",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/flake.nix b/flake.nix
index 0e5c05b..e3e3928 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,7 +1,17 @@
 {
+  description = "felschr's CV";
+
   inputs = {
     nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
     flake-utils.url = "github:numtide/flake-utils";
+    typix = {
+      url = "github:loqusion/typix";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+    typst-packages = {
+      url = "github:typst/packages";
+      flake = false;
+    };
   };
 
   outputs =
@@ -10,19 +20,75 @@
       system:
       let
         pkgs = import inputs.nixpkgs { inherit system; };
+
+        typixLib = inputs.typix.lib.${system};
+
+        typstPackagesSrc = "${inputs.typst-packages}/packages";
+        typstPackagesCache = pkgs.stdenvNoCC.mkDerivation {
+          name = "typst-packages-cache";
+          src = typstPackagesSrc;
+          dontBuild = true;
+          installPhase = ''
+            mkdir -p "$out/typst/packages"
+            cp -LR --reflink=auto --no-preserve=mode -t "$out/typst/packages" "$src"/*
+          '';
+        };
+
+        src = typixLib.cleanTypstSource ./.;
+        commonArgs = {
+          typstSource = "main.typ";
+
+          fontPaths = [ ];
+
+          virtualPaths = [ ];
+        };
+
+        commonBuildArgs = commonArgs // {
+          XDG_CACHE_HOME = typstPackagesCache;
+        };
+
+        build-drv = typixLib.buildTypstProject (
+          commonBuildArgs
+          // {
+            inherit src;
+          }
+        );
+
+        build-script = typixLib.buildTypstProjectLocal (
+          commonBuildArgs
+          // {
+            inherit src;
+          }
+        );
+
+        watch-script = typixLib.watchTypstProject commonArgs;
       in
       {
-        devShells = {
-          default = pkgs.mkShell {
-            name = "felschr-cv";
+        checks = {
+          inherit build-drv build-script watch-script;
+        };
 
-            buildInputs = with pkgs; [
-              typst
-              tinymist
+        packages.default = build-drv;
 
-              nixfmt-rfc-style
-            ];
+        apps = rec {
+          default = watch;
+          build = inputs.flake-utils.lib.mkApp {
+            drv = build-script;
           };
+          watch = inputs.flake-utils.lib.mkApp {
+            drv = watch-script;
+          };
+        };
+
+        devShells.default = typixLib.devShell {
+          inherit (commonArgs) fontPaths virtualPaths;
+          packages = [
+            watch-script
+            pkgs.typstfmt
+            pkgs.tinymist
+
+            pkgs.nixfmt-rfc-style
+          ];
         };
 
         formatter = pkgs.nixfmt-rfc-style;