diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 768515efe582ff22dccd5ac83828479dc2495db8..f0dba1ef22b408587094147652774740ee4e3bd6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,11 +1,10 @@
 stages:
 - generate
 - check
-- impure
 
 generate-flake-ci:
   stage: generate
-  script: nix run "git+https://gitlab.homotopic.tech/haskell/flake-to-gitlab-ci" > flake-ci.yml
+  script: nix run "git+https://gitlab.homotopic.tech/haskell/flake-to-gitlab-ci?ref=refs/tags/0.2.1.0" > flake-ci.yml
   artifacts:
     paths:
       - flake-ci.yml
@@ -17,12 +16,3 @@ flake-ci:
       - artifact: flake-ci.yml
         job: generate-flake-ci
     strategy: depend
-
-impure-tests:
-  stage: impure
-  rules:
-  - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-    when: manual
-    allow_failure: true
-  script:
-  - nix run .#run-impure-tests
diff --git a/flake.nix b/flake.nix
index d41d81652d1a272c4115622d031415d896c7478c..c75b61ec403e9066a10521fddc7b9dad4b1ba129 100644
--- a/flake.nix
+++ b/flake.nix
@@ -19,80 +19,92 @@
     , nixpkgs
     , ...
     }:
-    flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
-    let
-      pkgs = nixpkgs.legacyPackages.${system};
-    in
-    with pkgs.lib;
-    with pkgs.writers;
-    with lint-utils.writers.${system};
-    let
-
-      horizon-gen-nix-app = get-flake horizon-gen-nix;
-
-      haskellLib = pkgs.haskell.lib.compose;
-
-      legacyPackages = pkgs.callPackage (nixpkgs + /pkgs/development/haskell-modules) {
-        buildHaskellPackages = pkgs.haskell.packages.ghc942;
-        compilerConfig = pkgs.callPackage ./configuration-ghc-9.4.x.nix { inherit haskellLib; };
-        configurationCommon = import ./configuration.nix;
-        configurationNix = { pkgs, haskellLib }: self: super: { };
-        ghc = pkgs.haskell.compiler.ghc942;
-        inherit haskellLib;
-        initialPackages = import ./initial-packages.nix;
-        nonHackagePackages = self: super: { };
-      };
+    flake-utils.lib.eachSystem [ "x86_64-linux" ]
+      (system:
+      let
+        pkgs = nixpkgs.legacyPackages.${system};
+      in
+      with pkgs.lib;
+      with pkgs.writers;
+      with lint-utils.writers.${system};
+      let
+
+        horizon-gen-nix-app = get-flake horizon-gen-nix;
+
+        haskellLib = pkgs.haskell.lib.compose;
+
+        legacyPackages = pkgs.callPackage (nixpkgs + /pkgs/development/haskell-modules) {
+          buildHaskellPackages = pkgs.haskell.packages.ghc942;
+          compilerConfig = pkgs.callPackage ./configuration-ghc-9.4.x.nix { inherit haskellLib; };
+          configurationCommon = import ./configuration.nix;
+          configurationNix = { pkgs, haskellLib }: self: super: { };
+          ghc = pkgs.haskell.compiler.ghc942;
+          inherit haskellLib;
+          initialPackages = import ./initial-packages.nix;
+          nonHackagePackages = self: super: { };
+        };
 
-      packages = filterAttrs
-        (n: v: v != null
+        packages = filterAttrs
+          (n: v: v != null
           && builtins.typeOf v == "set"
           && pkgs.lib.hasAttr "type" v
           && v.type == "derivation"
           && v.meta.broken == false)
-        legacyPackages;
-
-      horizon-gen-gitlab-ci = writeBashBin "gen-gitlab-ci" "${pkgs.dhall-json}/bin/dhall-to-yaml --file .gitlab-ci.dhall";
-
-      run-impure-tests = writePorcelainOrDieBin {
-        name = "run-impure-tests";
-        src = ./.;
-        command = ''
-          export PATH=$PATH:${pkgs.nix-prefetch-git}/bin:${pkgs.cabal-install}/bin
-          cabal update
-          rm pkgs -rf && nix run .#horizon-gen-nix;
-          nixpkgs-fmt pkgs/*
-        '';
-        advice = "Try removing the offending packages from pkgs/ and running nix run .#horizon-gen-nix";
-      };
+          legacyPackages;
+
+        horizon-gen-gitlab-ci = writeBashBin "gen-gitlab-ci" "${pkgs.dhall-json}/bin/dhall-to-yaml --file .gitlab-ci.dhall";
+
+        run-impure-tests = writePorcelainOrDieBin {
+          name = "run-impure-tests";
+          src = ./.;
+          command = ''
+            export PATH=$PATH:${pkgs.nix-prefetch-git}/bin:${pkgs.cabal-install}/bin
+            cabal update
+            rm pkgs -rf && nix run .#horizon-gen-nix;
+            nixpkgs-fmt pkgs/*
+          '';
+          advice = "Try removing the offending packages from pkgs/ and running nix run .#horizon-gen-nix";
+        };
 
-      run-impure-tests-app = {
-        type = "app";
-        program = "${run-impure-tests}/bin/run-impure-tests";
-      };
+        run-impure-tests-app = {
+          type = "app";
+          program = "${run-impure-tests}/bin/run-impure-tests";
+        };
 
-    in
-    {
+      in
+      {
 
-      apps = {
+        apps = {
 
-        horizon-gen-nix = horizon-gen-nix-app.outputs.apps.${system}.horizon-gen-nix;
+          horizon-gen-nix = horizon-gen-nix-app.outputs.apps.${system}.horizon-gen-nix;
 
-        horizon-gen-gitlab-ci = {
-          type = "app";
-          program = "${horizon-gen-gitlab-ci}/bin/gen-gitlab-ci";
+          horizon-gen-gitlab-ci = {
+            type = "app";
+            program = "${horizon-gen-gitlab-ci}/bin/gen-gitlab-ci";
+          };
+
+          run-impure-tests = run-impure-tests-app;
         };
 
-        run-impure-tests = run-impure-tests-app;
-      };
+        checks = {
+          dhall-format = lint-utils.outputs.linters.${system}.dhall-format { src = ./.; };
+          nixpkgs-fmt = lint-utils.outputs.linters.${system}.nixpkgs-fmt { src = ./.; };
+        };
 
-      checks = {
-        dhall-format = lint-utils.outputs.linters.${system}.dhall-format { src = ./.; };
-        nixpkgs-fmt = lint-utils.outputs.linters.${system}.nixpkgs-fmt { src = ./.; };
-      };
+        inherit legacyPackages;
+
+        inherit packages;
 
-      inherit legacyPackages;
+      }) // {
+      templates = rec {
 
-      inherit packages;
+        default = minimal;
 
-    });
+        minimal = {
+          description = "horizon-platform minimal template";
+          path = ./templates/minimal;
+        };
+
+      };
+    };
 }
diff --git a/templates/minimal/ChangeLog.md b/templates/minimal/ChangeLog.md
new file mode 100644
index 0000000000000000000000000000000000000000..9da5940ec078e92e00dc89d49e24468588a82747
--- /dev/null
+++ b/templates/minimal/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for template
+
+## v0.1.0.0
diff --git a/templates/minimal/LICENSE b/templates/minimal/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..342c588b3a040858158b87f55432d4f8deab7d57
--- /dev/null
+++ b/templates/minimal/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2022
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/templates/minimal/README.md b/templates/minimal/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..69f582fe4e4a2692236ea90fc6ce5059e73753ab
--- /dev/null
+++ b/templates/minimal/README.md
@@ -0,0 +1,18 @@
+# horizon-minimal-template
+
+This template is a barebones haskell template using
+[horizon](https://horizon-haskell.net). Just add
+things to the dependencies in the cabal file.
+
+## Building
+
+```
+nix build
+```
+
+## Development
+
+```
+nix develop
+cabal test all
+```
diff --git a/templates/minimal/app/Main.hs b/templates/minimal/app/Main.hs
new file mode 100644
index 0000000000000000000000000000000000000000..14e874c472ac6b3675486b4989e0977a3c33f97f
--- /dev/null
+++ b/templates/minimal/app/Main.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import qualified Lib (main)
+
+main :: IO ()
+main = Lib.main
diff --git a/templates/minimal/cabal.project b/templates/minimal/cabal.project
new file mode 100644
index 0000000000000000000000000000000000000000..c14fcd10d62cd81ffb6607c5de09776f456cfad3
--- /dev/null
+++ b/templates/minimal/cabal.project
@@ -0,0 +1,3 @@
+packages: ./.
+
+test-show-details: streaming
diff --git a/templates/minimal/flake.lock b/templates/minimal/flake.lock
new file mode 100644
index 0000000000000000000000000000000000000000..695eb8f9f61a21a80158540d9ff28087f3ecdde0
--- /dev/null
+++ b/templates/minimal/flake.lock
@@ -0,0 +1,177 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "locked": {
+        "lastModified": 1667395993,
+        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake-utils_2": {
+      "locked": {
+        "lastModified": 1659877975,
+        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
+        "type": "github"
+      },
+      "original": {
+        "id": "flake-utils",
+        "type": "indirect"
+      }
+    },
+    "flake-utils_3": {
+      "locked": {
+        "lastModified": 1644229661,
+        "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "get-flake": {
+      "locked": {
+        "lastModified": 1644686428,
+        "narHash": "sha256-zkhYsURWFrvEZLkIoBeqFBzSu+cA2u5mo6M8vq9LN7M=",
+        "owner": "ursi",
+        "repo": "get-flake",
+        "rev": "703f15558daa56dfae19d1858bb3046afe68831a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "ursi",
+        "repo": "get-flake",
+        "type": "github"
+      }
+    },
+    "horizon-gen-nix": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1670944091,
+        "narHash": "sha256-WFj0uQqaEIURuZpfsb8yy/iqyzN8Lrc9BpWloL5a4R0=",
+        "rev": "8eb5ffc81cd8331f340546d746a786c7b2f021a6",
+        "revCount": 109,
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/horizon/horizon-gen-nix"
+      },
+      "original": {
+        "rev": "8eb5ffc81cd8331f340546d746a786c7b2f021a6",
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/horizon/horizon-gen-nix"
+      }
+    },
+    "horizon-platform": {
+      "inputs": {
+        "flake-utils": "flake-utils_2",
+        "get-flake": "get-flake",
+        "horizon-gen-nix": "horizon-gen-nix",
+        "lint-utils": "lint-utils",
+        "nixpkgs": "nixpkgs_2"
+      },
+      "locked": {
+        "lastModified": 1671046351,
+        "narHash": "sha256-P80LAEx8E0bE1X3J23PUlnE/kkvK9txAe82iuWCxC9g=",
+        "ref": "refs/heads/master",
+        "rev": "eba696abb902fd5538dd006a297e699c7b2cee80",
+        "revCount": 762,
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/horizon/horizon-platform"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/horizon/horizon-platform"
+      }
+    },
+    "lint-utils": {
+      "inputs": {
+        "flake-utils": "flake-utils_3",
+        "nixpkgs": "nixpkgs"
+      },
+      "locked": {
+        "lastModified": 1669815989,
+        "narHash": "sha256-yDE8uxa/O633VeRBlJKSY5q9JtzoBoMANvgupdI42YI=",
+        "ref": "refs/heads/master",
+        "rev": "5b97bd76dd6756dfc29a32d25a5c78c0522bac10",
+        "revCount": 39,
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/nix/lint-utils"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://gitlab.homotopic.tech/nix/lint-utils"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1644525281,
+        "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "48d63e924a2666baf37f4f14a18f19347fbd54a2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_2": {
+      "locked": {
+        "lastModified": 1665830552,
+        "narHash": "sha256-qel2bZ9TqfW8WzWCWdjuCy4bVFhhGsEeqFv/bj1ka2s=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "26b7e6ab6a864c3e7e077bcb27a49f0480b9894a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "nixpkgs_3": {
+      "locked": {
+        "lastModified": 1671095104,
+        "narHash": "sha256-BgI8tDJgORrKX9lF93enEDKP5WxIoVBt9+1zoGIfx7k=",
+        "owner": "nixos",
+        "repo": "nixpkgs",
+        "rev": "7634c3250b6870e76f2e611cb95b72392add9aef",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nixos",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "horizon-platform": "horizon-platform",
+        "nixpkgs": "nixpkgs_3"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/templates/minimal/flake.nix b/templates/minimal/flake.nix
new file mode 100644
index 0000000000000000000000000000000000000000..7eefaf6d7c0b3f54ac58ac04dc7eeeb15eae6c89
--- /dev/null
+++ b/templates/minimal/flake.nix
@@ -0,0 +1,39 @@
+{
+  description = "haskell-template";
+  inputs = {
+    flake-utils.url = "github:numtide/flake-utils";
+    horizon-platform.url = "git+https://gitlab.homotopic.tech/horizon/horizon-platform";
+    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+  };
+  outputs =
+    inputs@
+    { self
+    , flake-utils
+    , horizon-platform
+    , nixpkgs
+    , ...
+    }:
+    flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
+    let
+      pkgs = import nixpkgs { inherit system; };
+      legacyPackages = with pkgs.haskell.lib.compose;
+        horizon-platform.legacyPackages.${system}.override {
+          overrides = hfinal: hprev: {
+            haskell-template = hprev.callCabal2nix "haskell-template" ./. { };
+          };
+        };
+    in
+    {
+
+      devShells.default = legacyPackages.haskell-template.env.overrideAttrs (attrs: {
+        buildInputs = attrs.buildInputs ++ [
+          legacyPackages.cabal-install
+          pkgs.stylish-haskell
+          pkgs.nixpkgs-fmt
+        ];
+      });
+
+      packages.default = legacyPackages.haskell-template;
+
+    });
+}
diff --git a/templates/minimal/src/Lib.hs b/templates/minimal/src/Lib.hs
new file mode 100644
index 0000000000000000000000000000000000000000..ff89e4cf7852bc57bc26ebc0ebb9c4e13af3730b
--- /dev/null
+++ b/templates/minimal/src/Lib.hs
@@ -0,0 +1,4 @@
+module Lib (main) where
+
+main :: IO ()
+main = putStrLn "Hello"
diff --git a/templates/minimal/template.cabal b/templates/minimal/template.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..537edebb8a71c1e9f340981582e475fdc6d2feb9
--- /dev/null
+++ b/templates/minimal/template.cabal
@@ -0,0 +1,72 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.34.7.
+--
+-- see: https://github.com/sol/hpack
+
+name:           template
+version:        0.1.0.0
+synopsis:       Short description of your package
+description:    Please see the README on GitHub at <https://github.com/githubuser/ranger#readme>
+category:       Web
+author:         Daniel Firth
+maintainer:     dan.firth@homotopic.tech
+copyright:      2022 Daniel Firth
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://gitlab.homotopic.tech/haskell/template
+
+library
+  exposed-modules:
+      Lib
+  other-modules:
+      Paths_template
+  hs-source-dirs:
+      src
+  default-extensions:
+      DataKinds
+      DerivingStrategies
+      GHC2021
+  ghc-options: -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe
+  build-depends:
+      base >=4.7 && <5
+  default-language: Haskell2010
+
+executable template
+  main-is: Main.hs
+  other-modules:
+      Paths_template
+  hs-source-dirs:
+      app
+  default-extensions:
+      DataKinds
+      DerivingStrategies
+      GHC2021
+  ghc-options: -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , template
+  default-language: Haskell2010
+
+test-suite template-tests
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  other-modules:
+      Paths_template
+  hs-source-dirs:
+      test
+  default-extensions:
+      DataKinds
+      DerivingStrategies
+      GHC2021
+  ghc-options: -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module -Wno-safe -Wno-unsafe -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+  default-language: Haskell2010
diff --git a/templates/minimal/test/Main.hs b/templates/minimal/test/Main.hs
new file mode 100644
index 0000000000000000000000000000000000000000..652d2cb8fee6d2719ca48a16e74f9483c8443880
--- /dev/null
+++ b/templates/minimal/test/Main.hs
@@ -0,0 +1,6 @@
+module Main
+  ( main
+  ) where
+
+main :: IO ()
+main = putStrLn "Test suite not implemented."