diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..1291b53
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,65 @@
+{
+  description = "Subtytle flake";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+
+    crane.url = "github:ipetkov/crane";
+
+    flake-utils.url = "github:numtide/flake-utils";
+  };
+
+  outputs = { self, nixpkgs, crane, flake-utils, ... }:
+    flake-utils.lib.eachDefaultSystem (system:
+      let
+        pkgs = nixpkgs.legacyPackages.${system};
+
+        craneLib = crane.mkLib pkgs;
+
+        # Common arguments can be set here to avoid repeating them later
+        # Note: changes here will rebuild all dependency crates
+        commonArgs = {
+          src = craneLib.cleanCargoSource ./.;
+          strictDeps = true;
+
+          buildInputs = [
+            # Add additional build inputs here
+          ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
+            # Additional darwin specific inputs can be set here
+            pkgs.libiconv
+          ];
+        };
+
+        subtytle = craneLib.buildPackage (commonArgs // {
+          cargoArtifacts = craneLib.buildDepsOnly commonArgs;
+        });
+      in
+      {
+        checks = {
+          inherit subtytle;
+        };
+
+        packages.default = subtytle;
+
+        apps.default = flake-utils.lib.mkApp {
+          drv = subtytle;
+        };
+
+        devShells.default = craneLib.devShell {
+          # Inherit inputs from checks.
+          checks = self.checks.${system};
+          LIBCLANG_PATH = "${pkgs.llvmPackages_17.libclang.lib}/lib";
+          RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
+
+          packages = with pkgs;[
+            openssl
+            pkg-config
+            libiconv
+            cargo-hakari
+            llvmPackages.clang
+            cmake
+
+          ];
+        };
+      });
+}