This is the full developer documentation for Nix Flake Templates # Nix Flake Templates > Quickly set up a reproducible development environment with Nix. ## How to set up a repository for [Section titled “How to set up a repository for”](#how-to-set-up-a-repository-for) [Rust executable ](recipes/rust/executable) [Web development with TypeScript ](recipes/typescript/web-framework) [OCaml ](recipes/ocaml/generic-dune) # Emacs > How to set up Emacs for using Nix flakes. ## Direnv support [Section titled “Direnv support”](#direnv-support) It is recommended to set up a direnv integration, so you can transparently access programs provided from the development shell. While there is no built-in direnv integration as of Emacs 30, there are a few third-party packages for that. One option is [envrc-mode](https://github.com/purcell/envrc) by Steve Purcell, which you can install as `envrc` from [MELPA](https://melpa.org/#/). ## Other recommendations [Section titled “Other recommendations”](#other-recommendations) These recommendations are not specific to Nix but are suggested to make you feel productive when working with modern software development projects. ### LSP clients [Section titled “LSP clients”](#lsp-clients) * eglot (built-in) * [lsp-mode](https://emacs-lsp.github.io/lsp-mode/) Also, [lsp-booster](https://github.com/blahgeek/emacs-lsp-booster) is recommended for users of both lsp-mode and eglot. See [a corresponding awesome-emacs section](https://github.com/emacs-tw/awesome-emacs?tab=readme-ov-file#lsp-client) for other options. ### Formatters [Section titled “Formatters”](#formatters) * [reformatters](https://github.com/purcell/emacs-reformatter) * [apheleia](https://github.com/radian-software/apheleia/) ### Compile frontend [Section titled “Compile frontend”](#compile-frontend) See [awesome-emacs](https://github.com/emacs-tw/awesome-emacs?tab=readme-ov-file#compiling). ## How to maintain project-specific settings [Section titled “How to maintain project-specific settings”](#how-to-maintain-project-specific-settings) Emacs provides a way to keep per-project configuration that is `.dir-locals.el`. It is also possible to apply common settings to a set of directories using `dir-locals-set-class-variables` and `dir-locals-set-directory-class`. See the Emacs Manual for details. # Enable nix-direnv > How to set up nix-direnv A recommended way to integrate Nix into your environment is via [nix-direnv](https://github.com/nix-community/nix-direnv). Both NixOS and home-manager provide options for running nix-direnv. [NixOS](https://search.nixos.org/options?channel=unstable\&from=0\&size=50\&sort=relevance\&type=packages\&query=nix-direnv): ```nix { programs.direnv = { enable = true; nix-direnv.enable = true; }; } ``` or [home-manager](https://nix-community.github.io/home-manager/options.xhtml): ```nix { programs.direnv = { enable = true; nix-direnv.enable = true; }; } ``` ## Further reading [Section titled “Further reading”](#further-reading) * [nix-direnv](https://github.com/nix-community/nix-direnv) * [Effortless dev environments with Nix and direnv](https://determinate.systems/posts/nix-direnv/) # Getting started with flake templates Note This site provides `llms-full.txt` to give LLM-based coding assistants a full context of this project. You can download it and use it in your chat with the LLM: * [llms-full.txt](https://akirak.github.io/flake-templates/llms-full.txt) ## Configuration [Section titled “Configuration”](#configuration) To use one of these templates, you first have to set up [the Nix package manager](https://nixos.org/download/) with flakes enabled, on your system. You can follow [this tutorial](https://nixos-and-flakes.thiscute.world/nixos-with-flakes/introduction-to-flakes) for instruction. For an optimal development experience with Nix, it is recommended to [install nix-direnv](/flake-templates/configuration/nix-direnv). You also need to configure your editor to integrate with direnv: * [GNU Emacs](/flake-templates/configuration/editor/emacs) Note If you are using a direnv-compatible editor that is not listed above, please feel free to contribute a new guide for the integration method by [opening a PR](https://github.com/akirak/flake-templates/pulls) in the repository. ## Pick a recipe [Section titled “Pick a recipe”](#pick-a-recipe) Once you have set up your editor, you can use one of the templates to initialize your environment. The Recipes section offers several instructions for creating a new development environment from a flake template. Note Because `flake-templates` is a multi-licensed repository, each file in a template contains a header that describes its license. See the examples below: ```plaintext # SPDX-License-Identifier: Unlicense ``` ```plaintext # SPDX-FileCopyrightText: 2021-2025 Akira Komamura # SPDX-License-Identifier: MIT ``` If the generated file is licensed under `Unlicense`, you can safely remove the header. ## Use patterns [Section titled “Use patterns”](#use-patterns) Certain patterns can be commonly applied across many flakes. While these patterns are not required for every project, they offer solutions to typical technical problems in software projects. The Patterns section describes several such patterns, enabling you to readily expand upon flakes initialized using a flake template. # Introduction to Flake Templates Hello, this site provides instructions for setting up a development environment using Nix flake templates. With Nix, it is easy to create a cross-platform reproducible environment. Nix supports multiple platforms including Mac and Linux. Nixpkgs, the package collection of Nix, is the largest on earth. Nix-based development environments are more lightweight than using container-based solutions such as Docker. My [flake templates](https://github.com/akirak/flake-templates) provides a collection of templates for creating a basic environment for developing with Nix. This documentation explains how to use it. ## Target audience [Section titled “Target audience”](#target-audience) This documentation site assumes the reader is * Using Linux or Mac. If you are using Windows, you will need WSL 2 or a virtual machine running Linux. This site doesn’t explain how to set up the underlying environment. * Proficient with command-line. ## Overview of this documentation [Section titled “Overview of this documentation”](#overview-of-this-documentation) If you don’t know how to develop projects with Nix flakes, first read [Getting started](/flake-templates/getting-started). If you have some experiences in development with Nix, you may navigate directly to the relevant sections: * The Configuration section provides guides for configuring your editor for development with Nix flakes. * The Recipes section offers step-by-step instructions for initializing a new flake using one of the available templates. * The Patterns section outlines methods for extending your flake to accommodate additional project requirements. Select a section on the sidebar of this web site. # Continuous Integration on GitHub Actions This tutorial explains how to set up a basic continuous integration workflow on [GitHub Actions](https://docs.github.com/en/actions) using Nix for package building. By building your package with Nix and uploading it to a binary cache, you'll make it easily accessible to users via the `nix run` command. This process streamlines package distribution and installation. The workflow builds the default Nix package defined in your flake using the following third-party actions: * [nix-quick-install-action](https://github.com/nixbuild/nix-quick-install-action) to install Nix. * [cache-nix-action](https://github.com/nix-community/cache-nix-action) to save the Nix store to the GitHub Actions cache to reduce time spent on downloading dependencies. * Optionally, you can enable [cachix-action](https://github.com/cachix/cachix-action), so you can download the artifacts built on CI to your machines as Nix binary cache. Note that there are some alternative hosted services for Nix CI. If the provided setup doesn't satisfy your requirements, you might consider the following options: * [Garnix](https://garnix.io/) * [nixbuild.net](https://nixbuild.net/) ## Adding files from the template [Section titled “Adding files from the template”](#adding-files-from-the-template) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#meta ``` 2. Adjust the `.github/workflows/nix-build.yml` file to match your project requirements. 3. Optionally, you can enable uploading to Cachix. Edit `.github/actions/setup/action.yml` and uncomment relevant sections: ```yaml inputs: cachix-name: description: Name of the Cachix account required: false default: akirak cachix-token: description: Auth token for cachix required: true ``` ```yaml - uses: cachix/cachix-action@v16 with: name: ${{ inputs.cachix-name }} authToken: '${{ inputs.cachix-token }}' ``` Get an authentication token on Cachix and save it as a secret variable `CACHIX_AUTH_TOKEN` in your project. In each workflow in `.github/workflows` directory, pass the auth token to the action: ```yaml - name: Set up Nix uses: ./.github/actions/setup with: cachix-token: ${{ secrets.CACHIX_AUTH_TOKEN }} ``` 4. To save more assets to the cache (e.g. packages of a language-native package system), edit `.github/actions/setup/action.yml` and add their file paths to `paths` option and tweak `primary-key` as needed: ```yaml - name: Restore the package cache uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 1G paths: | node_modules/.pnpm ``` 5. To add more Nix-based workflows, just use the `./.github/actions/setup` action: ```yaml jobs: some-nix-job: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Nix uses: ./.github/actions/setup # with: # cachix-token: ${{ secrets.CACHIX_AUTH_TOKEN }} ``` ## Building multiple packages and performing extra checks [Section titled “Building multiple packages and performing extra checks”](#building-multiple-packages-and-performing-extra-checks) Note The commands described in this section is also contained as comments in `nix-build.yml`. By default, the CI workflow `nix-build.yml` only builds the default package of the flake: ```shell nix build -L ``` If your flake exposes multiple packages, you can use the following command instead to build all packages for each platform: ```shell nix build ".#packages.$(nix eval --expr builtins.currentSystem --impure --raw).*" -L --option keep-going true ``` An alternative way is to add the packages to `checks` and run `nix flake check`: ```shell nix flake check -L --option keep-going true ``` `keep-going` option inverses the default behavior of fail-fast, which is convenient for CI. Also see the following issue for updates: [nix build --all: build all packages in a flake · Issue #7165 · NixOS/nix · GitHub](https://github.com/NixOS/nix/issues/7165) ## Running tests [Section titled “Running tests”](#running-tests) To run tests using a contained environment in Nix, use `checkPhase` and set `doCheck = true`. Consult the builder documentation to see if it has any built-in check. If you'd rather avoid running tests within Nix's sandbox, create a separate workflow instead in addition to the build workflow. ## Also consider [Section titled “Also consider”](#also-consider) * Update the actions automatically by [setting up Renovate](/flake-templates/patterns/updating/renovate). This is already included in the template, so you don't need extra steps for configuration. * The template also ships with a workflow for [checking formats using treefmt-nix](/flake-templates/patterns/formatting/treefmt-nix). It should work out of the box if your flake supports it, but otherwise it will fail. Check out the documentation for details. * Use [nix-fast-build](https://github.com/Mic92/nix-fast-build) if you are trying to build a flake containing several outputs with shared dependencies. # Checking formatting using treefmt-nix on GitHub Actions This tutorial explains how to check formatting on GitHub Actions using [treefmt-nix](https://github.com/numtide/treefmt-nix). ## Add a treefmt-nix configuration [Section titled “Add a treefmt-nix configuration”](#add-a-treefmt-nix-configuration) Some of the flake templates, including `treefmt`, integrates treefmt-nix out of the box. You don't have to add a configuration in this case. Otherwise, please add a configuration to your flake manually by consulting [the documentation](https://github.com/numtide/treefmt-nix?tab=readme-ov-file#flakes). They also provide a flake-parts module, which you can use to set up the thing more easily. Once set up, your project should support reformatting the entire project by running the following command: ```shell nix fmt ``` On CI, you can run the following command to check formatting without making modifications: ```shell nix build ".#checks.$(nix eval --expr builtins.currentSystem --impure --raw).treefmt" ``` ## Add a GitHub workflow for running the check [Section titled “Add a GitHub workflow for running the check”](#add-a-github-workflow-for-running-the-check) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#meta ``` 2. Adjust the `.github/workflows/nix-format.yml` file to match your project requirements. In particular, you may have to tweak the triggers (in `on` section). With [the renovate configuration](/flake-templates/patterns/updating/renovate) shipped by the template, the actions will be automatically updated. # Using nix-systems For some reasons, you might want to limit the target systems of your flake. Most templates use `lib.systems.flakeExposed` from nixpkgs to specify the target systems, but your Nix packages may not be supported on some of the systems. It would be possible to explicitly list the target systems in your flake, but that can be a restriction to its consumers. With [nix-systems](https://github.com/nix-systems/nix-systems), you can specify the default target systems, while allowing users to override the setting at their discretion. To use nix-systems, follow these steps: 1. Add `systems` input to your flake.nix: ```nix inputs = { ... + systems.url = "github:nix-systems/default"; }; ``` 2. Make `systems` input visible in the `outputs` scope in the flake.nix: ```diff outputs = { nixpkgs, ... }: outputs = { nixpkgs, systems, ... }: ``` 3. Replace `nixpkgs.lib.systems.flakeExposed` with `(import systems)`: ```diff eachSystem = f: nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed (system: f nixpkgs.legacyPackages.${system}); nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system}); ``` # Updating Packages with Mend Renovate This tutorial explains how to automatically updates packages using Renovate Bot. ## Add a GitHub workflow for running the check [Section titled “Add a GitHub workflow for running the check”](#add-a-github-workflow-for-running-the-check) The `meta` template contains an example configuration for Renovate. 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#meta ``` 2. Adjust the `.github/renovate.json` file to match your project requirements. ## Resources [Section titled “Resources”](#resources) * [Renovate Docs](https://docs.renovatebot.com/) # Ensuring conventional commits using Cocogitto This tutorial explains how to configure [cocogitto](https://docs.cocogitto.io/) to verify commits in your repository to conform to [conventional commits](https://www.conventionalcommits.org/). ## Add cocogitto to your repository [Section titled “Add cocogitto to your repository”](#add-cocogitto-to-your-repository) Cocogitto is available from Nixpkgs as `cocogitto` package. You can add it to the dev shell of your `flake.nix`: ```diff devShells = { default = pkgs.mkShell { packages = [ pkgs.nodePackages.typescript pkgs.nodePackages.typescript-language-server pkgs.cocogitto ]; }; }; ``` Then generate `cog.toml`: ```sh cog init ``` ## Integrating Git hooks [Section titled “Integrating Git hooks”](#integrating-git-hooks) Cocogitto has a built-in functionality to install git hooks (see [the documentation](https://docs.cocogitto.io/guide/git_hooks.html).) This section describes how to integrate cocogitto into other git-hook frameworks. ### git-hooks.nix [Section titled “git-hooks.nix”](#git-hooksnix) TODO: [git-hooks.nix](https://github.com/cachix/git-hooks.nix) currently doesn't support cocogitto out of the box. It supports [conform](https://github.com/edmundhung/conform) which is an alternative to cocogitto, so it would be possible to cocogitto. ### Lefthook [Section titled “Lefthook”](#lefthook) If you are using [Lefthook](https://lefthook.dev/), add the following snippet to `lefthook.yml` to verify commits in `commit-msg` hook: ```yaml commit-msg: runner: bash commands: cog: run: | cog verify --file {1} ``` ## More information [Section titled “More information”](#more-information) Follow [the user guide](https://docs.cocogitto.io/guide/init.html) for details. # Developing an Elixir Phoenix application > How to develop an Elixir Phoenix with a Nix flake template In this tutorial, you will learn how to add `flake.nix` to an Elixir Phoenix project. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. Make `mix` executable available: ```shell nix shell nixpkgs#elixir ``` 2. Install the scaffolder for Phoenix using `mix archive.install` command. You need to do this only once per machine: ```shell mix archive.install hex phx_new ``` 3. Use `mix phx.new` to scaffold a new project with your preferred options: ```shell mix phx.new 'your_new_project' --no-ecto ``` Tip Phoenix provides various options for initializing a project. Check out the help: ```shell mix help phx.new ``` 4. Enter the directory: ```shell cd 'your_new_project' ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#elixir-app ``` 2. Open `flake.nix` and set the Erlang and Elixir versions: ```diff let # Set the Erlang version erlangVersion = "erlang_26"; erlangVersion = "erlang_27"; # Set the Elixir version elixirVersion = "elixir_1_15"; elixirVersion = "elixir_1_18"; in ``` 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` ### Switch the language server [Section titled “Switch the language server”](#switch-the-language-server) [Lexical](https://github.com/lexical-lsp/lexical/) is the default language server for Elixir, but you can change it to a different one: ```diff [ erlang elixir # You are likely to need Node.js if you develop a Phoenix # application. nodejs # Add the language server of your choice. inputs.lexical.packages.${system}.default elixir-ls # I once added Hex via a Nix development shell, but now I install # and upgrade it using Mix. Hex installed using Nix can cause an # issue if you manage Elixir dependencies using Mix. ] ``` # Developing a Gleam application > How to develop a server-side web application in Gleam with a Nix flake template In this tutorial, you will learn how to add `flake.nix` to a Gleam project. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. Make `gleam` executable available: ```shell nix shell nixpkgs#gleam ``` 2. Run `gleam new` to scaffold a new project: ```shell gleam new --skip-github 'your_new_project' ``` By default, `gleam new` generates `.github` directory containing a CI workflow for running tests, but we don't need it as we will install Gleam using Nix. 3. Enter the directory: ```shell cd 'your_new_project' ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#gleam ``` 2. Open `flake.nix` and update the Erlang version to the current one: ```diff erlang_version = "erlang_26"; erlang_version = "erlang_27"; ``` 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` # Developing a Go executable application In this tutorial, you will learn how to add `flake.nix` to a Go project. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. You can start developing a Go project by simply adding `main.go` and `go.mod` to an empty directory. Refer to [GitHub - golang-standards/project-layout: Standard Go Project Layout](https://github.com/golang-standards/project-layout) for a complex project layout. ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#go ``` 2. Add `.envrc`: ```shell use flake ``` 3. Allow direnv: ```shell direnv allow ``` ## Developing [Section titled “Developing”](#developing) ### Exposing the executable from the flake [Section titled “Exposing the executable from the flake”](#exposing-the-executable-from-the-flake) To expose the program as a Nix flake package, comment out the stub inside `packages` in the `flake.nix`. 1. Adapt `pname` and `version` to match your package information: ```diff packages = eachSystem (pkgs: { default = pkgs.buildGoModule { pname = "hello"; pname = "your-go-program"; # Edit this if you are using a semantic version version = builtins.substring 0 8 (self.lastModifiedDate or "19700101"); version = "0.3.4"; src = self.outPath; vendorHash = lib.fakeHash; meta = { }; }; }); ``` 2. Then build the package with Nix: ```sh nix build .#default ``` 3. It will show an error on the hash, so update `vendorHash` to the value shown in the output. ```diff packages = eachSystem (pkgs: { default = pkgs.buildGoModule { ...intensionaly omitted src = self.outPath; # Set the value shown from nix build - vendorHash = lib.fakeHash; + vendorHash = "sha256-7g261Jf6Qegfz7MnNbqo3Jc5Ft33qHXvst92laOrIY0="; ... }; }); ``` 4. It is also recommended to push your artifacts to a binary cache server and add its settings to the `flake.nix`: ```nix nixConfig = { extra-substituters = [ # Use your cachix account "https://akirak.cachix.org" ]; extra-trusted-public-keys = [ # Use a public key for your binary cache "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M=" ]; }; ``` ### Creating a justfile for local workflows [Section titled “Creating a justfile for local workflows”](#creating-a-justfile-for-local-workflows) You can create the following `justfile` for convenience. ```just build: go build run: go run main.go ``` # Developing a Spring Boot application In this tutorial, you will learn how to create a Spring Boot application using Spring Initializr and add `flake.nix` for development. ## Initialize a Spring Boot project [Section titled “Initialize a Spring Boot project”](#initialize-a-spring-boot-project) 1. Go to [Spring Initializr](https://start.spring.io/) and configure your project. This example chooses Gradle (Kotlin) and the Java language. You can also add dependencies as needed. Click *Generate* to download the project as a ZIP file. 2. Extract the ZIP file to your desired location: ```shell unzip demo.zip cd demo ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the Java template from the root directory of the Spring Boot project: ```shell nix flake init -t github:akirak/flake-templates#java ``` 2. Ensure the JDK version in your `flake.nix` matches your project requirement: ```nix jdk = pkgs.openjdk21_headless; ``` 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` # Adding a Nix-based environment for OCaml > This document describes how to add a Nix-based development environment for OCaml, using ocaml-basic template from github:akirak/flake-templates. In this tutorial, you will learn how to set up a basic development environment for OCaml. Unlike the [ocaml-dune template](/flake-templates/recipes/ocaml/generic-dune), this approach is designed to help you explore an existing OCaml codebase. In this setup, ocaml-lsp provides useful hints on type information and navigation. It is easier to set up than the other template, and it should work whether or not the project uses dune. Note This document won't explain how to initialize a new OCaml project without Dune, because generally Dune is the way, and other paths would be either project-specific or trivial. For starting a new project, follow [the instruction with ocaml-dune template](/flake-templates/recipes/ocaml/generic-dune). ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#ocaml-basic ``` Open `flake.nix` and review the packages under the default development shell. It contains comments for optional dependencies such as `ocamlbuild`, GNU Make, and gdb. Depending on the project, you might want to enable some of them. 2. Add `.envrc`: ```shell use flake ``` 3. Allow direnv: ```shell direnv allow ``` ## Developing [Section titled “Developing”](#developing) The template is basic and intended for existing projects. For development, follow instructions specific to your project. # Developing an OCaml project with Dune and Nix In this tutorial, you will learn how to initialize an OCaml project that can be developed using `dune`. Note This template requires a few more setup steps compared to most other templates. If you're looking to configure a language server for navigating an existing OCaml codebase, consider using the [basic OCaml template](/flake-templates/recipes/ocaml/basic) instead. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. Make `dune` executable available: ```shell nix shell nixpkgs#dune_3 ``` 2. Scaffold a new project using `dune`: ```shell dune init proj 'package_name' 'your-new-project' ``` 3. Enter the project directory: ```shell cd 'your-new-project' ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#ocaml-dune ``` 2. Open `flake.nix` and set the `pname` and `version` of the package to be built, e.g.: ```diff default = ocamlPackages.buildDunePackage { pname = throw "Name your OCaml package"; pname = "hello"; version = throw "Version your OCaml package"; version = "0.1"; duneVersion = "3"; src = self.outPath; ``` 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` ## Developing [Section titled “Developing”](#developing) Once the Nix shell is enabled, you can use `dune` inside the project directory, as you would do in a normal OCaml project. ### Adding OCaml dependencies [Section titled “Adding OCaml dependencies”](#adding-ocaml-dependencies) To add library dependencies to your OCaml project, follow this instruction. In this example, we will be adding `cmdliner` as a new dependency. 1. Add the libraries to `propagatedBuildInputs` (or `checkInputs` if it's a test dependency) attribute to your package: ```diff default = ocamlPackages.buildDunePackage { ... src = self.outPath; propagatedBuildInputs = with ocamlPackages; [ base core core_unix cmdliner ]; }; ``` 2. Add them to `depends` field of your `package` in the `dune-project` file: ```diff (package (name hello) (allow_empty) (depends (ocaml (>= 4.08.0)) (dune (>= 3.16)) (cmdliner (>= 1.3.0)) (alcotest :with-test))) ``` 3. Also add them to `libraries` field of a suitable stanza in the relevant `dune` file. ```diff (library (public_name hello) (name hello) (libraries unix) (libraries unix cmdliner) ) ``` ### Adding OCaml dependencies for testing [Section titled “Adding OCaml dependencies for testing”](#adding-ocaml-dependencies-for-testing) To add dependencies for testing that are not required for production, follow this example. We will be adding `alcotest` and `qcheck` as test dependencies. 1. In `flake.nix`, set `doCheck` to `true` in the arguments to `buildDunePackage`: ```diff default = ocamlPackages.buildDunePackage { ... doCheck = true; }; ``` 2. Also in the arguments, add `checkInputs` field which should be a list of test-only dependencies: ```diff default = ocamlPackages.buildDunePackage { ... doCheck = true; checkInputs = with ocamlPackages; [ alcotest qcheck-core ]; }; ``` 3. If your `dune-project` file contains one or more `package` entries, add the dependencies to `depends` field of relevant package. The dependencies should have `:with-test` option: ```diff (package (name hello) (allow_empty) (depends (ocaml (>= 4.08.0)) (dune (>= 3.16)) (cmdliner (>= 1.3.0)) ; test-only dependency (alcotest :with-test) ; test-only dependency with a version constraint (qcheck-core (and :with-test (>= 0.19))) ... )) ``` 4. Also add the dependencies to the `dune` file for testing (typically `test/dune`): ```diff (test (name test_hello) (libraries alcotest qcheck-core) ) ``` ### Generating documentation for the dependencies [Section titled “Generating documentation for the dependencies”](#generating-documentation-for-the-dependencies) To generate documentation of the dependencies, use `odig`. 1. To generate a documentation, use a `justfile` recipe bundled in the template: ```sh just odig-odoc ``` 2. To search through the documentation, you can run a local instance of [sherlodoc](https://doc.sherlocode.com/) or open a generated HTML file directly. #### Running sherlodoc [Section titled “Running sherlodoc”](#running-sherlodoc) To run sherlodoc, follow this instruction. 1. Enable `sherlodoc` in the `flake.nix`: ```diff devShells = eachSystem ( { pkgs, ocamlPackages, ... }: { default = pkgs.mkShell { inputsFrom = [ self.packages.${pkgs.system}.default ]; buildInputs = ( with ocamlPackages; [ ocaml-lsp ocamlformat ocp-indent ... # (sherlodoc.override { enableServe = true; }) (sherlodoc.override { enableServe = true; }) ] ) # ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools ; }; } ); ``` 2. Run `sherlodoc index` on `*.odocl` files. The template contains a `justfile` recipe, so you can just run: ```sh just sherlodoc-index ``` 3. To browse the documentation, use a justfile recipe: ```sh just sherlodoc-serve ``` For a detailed description, consult [the documentation of sherlodoc](https://github.com/art-w/sherlodoc?tab=readme-ov-file#local-usage). # Python development with uv and Nix > How to set up a basic environment for developing a Python application with uv In this tutorial, you will learn how to set up a development environment for Python. In the environment, you can use [uv](https://docs.astral.sh/uv/) for package management [BasedPyright](https://github.com/DetachHead/basedpyright) as the language server. It is basic but sufficient for navigating an existing code base with LSP, and can be effortlessly added to an existing project. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. Make `uv` executable available: ```shell nix shell nixpkgs#uv ``` 2. Use `uv init` to create a new project: ```shell uv init sample_app --bare ``` 3. Enter the directory: ```shell cd 'sample_app' ``` Below are extra steps to create a minimal [Streamlit](https://docs.streamlit.io/) application. Actual steps would be dependent on the type of application you are creating. Note For Streamlit, there is [a dedicated template](https://github.com/akirak/streamlit-react-template) from the same author, and that template is more recommended specifically for Streamlit projects. Below is just an example for this flake template. 1. Add streamlit to the Python project: ```shell uv add streamlit ``` 2. Create `app.py`: ```shell import streamlit as st _ = st.title("My First Streamlit App with uv") st.write("Hello, Streamlit!") ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#python-uv-simple ``` 2. Add `.envrc`: ```shell use flake # Load the Python environment source .venv/bin/activate ``` If you are using a shell other than bash/zsh, adapt `.venv/bin/activate` accordingly. 3. Allow direnv: ```shell direnv allow ``` For the sample streamlit application, also add `pkgs.streamlit` to the development shell in `flake.nix`. ## Developing [Section titled “Developing”](#developing) Use `uv` to develop the Python project as you would normally do without Nix. Depending on the dependencies of your Python project, you might need to take extra steps. Follow [instructions in the NixOS Wiki](https://wiki.nixos.org/wiki/Python#Python_development_environments_with_Nix). To build the project with Nix, follow the instructions in [Nixpkgs Reference Manual](https://nixos.org/manual/nixpkgs/unstable/#developing-with-python). The sample streamlit application can be run with the following command: ```shell uv run streamlit run app.py ``` # Developing a Rust program > How to develop a Rust program with a Nix flake template In this tutorial, you will learn how to initialize a Rust executable project. You can use `cargo` for most of the workflow. Thanks to [rust-overlay](https://github.com/oxalica/rust-overlay), you can pick a particular channel of the Rust toolchain, and [crane](https://github.com/ipetkov/crane) builds an executable in a reproducible manner with Nix. Rust Analyzer works out of the box. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. Make `cargo` executable available: ```shell nix shell nixpkgs#cargo ``` 2. Use `cargo new` to create a new project: ```shell cargo new 'your-new-project' ``` 3. Enter the directory: ```shell cd 'your-new-project' ``` ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#rust ``` By default, the template will pick the **default** profile of the **latest** version from the **stable** channel. If you prefer a different one, open `flake.nix` and edit the following settings to your preference. Check out [the documentation of the Rust Overlay](https://github.com/oxalica/rust-overlay?tab=readme-ov-file#cheat-sheet-common-usage-of-rust-bin) for details: ```nix let # For details on these options, See # https://github.com/oxalica/rust-overlay?tab=readme-ov-file#cheat-sheet-common-usage-of-rust-bin # # Channel of the Rust toolchain (stable or beta). rustChannel = "stable"; # Version (latest or specific date/semantic version) rustVersion = "latest"; # Profile (default or minimal) rustProfile = "default"; in ``` 2. Add `.envrc`: ```shell use flake ``` 3. Allow direnv: ```shell direnv allow ``` ## Developing [Section titled “Developing”](#developing) Use `cargo` to develop the project as you would normally do without Nix. Depending on the project, you may have to add dependencies such as `pkg-config`, `openssl`, etc. Some of these things are supported in the template, so just check out the `flake.nix` and comment out relevant fields. ### Building the Nix package [Section titled “Building the Nix package”](#building-the-nix-package) The package is exposed as `default` package out of the box, so you can run the application: ```shell nix run . ``` It is recommended to add the settings for your binary cache to `flake.nix`: ```nix nixConfig = { extra-substituters = [ # Use your cachix account "https://akirak.cachix.org" ]; extra-trusted-public-keys = [ # Use a public key for your binary cache "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M=" ]; }; ``` # Command Line Application with Effect > How to initialize an Effect CLI application from a Nix flake template In this tutorial, you will learn how to create a command-line application using `typescript-effect` template in the repository. It is an opinionated template with convenient tooling. The initialized project will be a complete development environment with the following dependencies: This template provides: * [Effect](https://effect.website/) * ESLint (based on [antfu's config](https://github.com/antfu/eslint-config)) * Build tool: tsup for bundling * Development tools: tsx for hot-reloading, lefthook for git hooks * Package manager: pnpm via corepack. You can easily switch to Bun With some tweaks, you can also create a server application. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note The template provides a boilerplate for a complete application containing `package.json`. 1. Create a new directory for your project: ```shell nix flake new -t github:akirak/flake-templates#typescript-effect my-app ``` 2. Enter the directory: ```shell cd my-app ``` 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` 5. Delete the license header comment from `package.json`: ```diff // Delete this comment for this package.json to work // SPDX-License-Identifier: Unlicense { "name": "my-effect-app", ... } ``` 6. Update the dependencies: ```shell pnpm update ``` 7. Tweak the generated configuration files to suit your preferences. ## Understanding the template structure [Section titled “Understanding the template structure”](#understanding-the-template-structure) The template includes a minimal example CLI application in `src/main.ts`. Key configuration files: * **`package.json`**: Pre-configured scripts for development, building, linting, and type checking * **`tsconfig.json`**: TypeScript configuration with Effect Language Service plugin * **`eslint.config.js`**: ESLint setup using @antfu/eslint-config with Effect-specific overrides * **`lefthook.yml`**: Git hooks for pre-commit linting and pre-push type checking ## Developing [Section titled “Developing”](#developing) ### Running the example [Section titled “Running the example”](#running-the-example) The template includes a simple "hello" command that you can run: ```shell # Run in development mode with hot-reloading pnpm dev hello --name World # Or run with tsx directly tsx src/main.ts hello --name World ``` Note By default, the `dev` command loads `.env` file in the project root. The command will fail unless you create the file. If you don't need environment variables, delete the flag from the corresponding `scripts` entry in `package.json`. ### Common development tasks [Section titled “Common development tasks”](#common-development-tasks) ```shell # Type checking pnpm typecheck # Linting pnpm lint # Fix linting issues pnpm lint-fix # Run tests (when added) pnpm test # Build the application pnpm build ``` ### Customizing for your needs [Section titled “Customizing for your needs”](#customizing-for-your-needs) 1. Playwright support: The flake includes optional Playwright browser testing support. Enable it by setting `enablePlaywright = true` in `flake.nix`. Also uncomment the relevant section in the generated GitHub workflow. 2. Frontend development: The ESLint config includes commented-out sections for React and TanStack Router support. Uncomment these if building a frontend application. ### Tips for Effect development [Section titled “Tips for Effect development”](#tips-for-effect-development) * The template disables several ESLint rules that conflict with Effect's coding style (like `array-callback-return` and `no-lone-blocks`) * The TypeScript configuration includes the Effect Language Service plugin for better IDE support ## Next steps [Section titled “Next steps”](#next-steps) * Explore the [Effect documentation](https://effect.website/docs/introduction) to learn more about the library * Check out [@effect/cli documentation](https://effect.website/docs/packages/cli/introduction) for building complex CLI applications * Add testing with vitest (already configured in package.json but the dependencies hasn't been added) # Developing a web application in TypeScript > How to develop a web application in TypeScript with a Nix flake template In this tutorial, you will learn how to add `flake.nix` to a TypeScript web application using `node-typescript` template in the repository. ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) Note In this section, we will be using a framework-specific scaffolder to initialize a project. Nowadays, it is also common for web developers to use an AI prototyping tools such as [v0](https://v0.dev/), [Loveable](https://lovable.dev/), [replit](https://replit.com/), [bolt.new](https://bolt.new/), and [Claude](https://claude.ai/new). If you have used one of those tools to initialize your project, you may still be able to use the template to add a Nix-based environment, so proceed to the next section. Note If you are adding `flake.nix` to an existing project, you can skip this section. 1. You will need one of `npm`, `yarn`, `pnpm`, or `bun`. Both `npm` and `bun` are available directly from Nixpkgs. If you prefer `yarn` or `pnpm`, you will probably need both `yarn`/`pnpm` and `npm`. To make the multiple packages available, you can use the classic `nix-shell` command, or use a devshell in [my personal repository](https://github.com/akirak/flake-pins/). * npm ```shell nix shell nixpkgs#nodejs ``` * yarn ```shell nix-shell -p yarn -p nodejs ``` or ```shell nix develop github:akirak/flake-pins#yarn ``` * pnpm ```shell nix-shell -p pnpm -p nodejs ``` or ```shell nix develop github:akirak/flake-pins#pnpm ``` * bun ```shell nix shell nixpkgs#bun ``` 2. Then follow an instruction for the framework of your choice to initialize the project. Below are some links: * [Install and set up Astro | Docs](https://docs.astro.build/en/install-and-setup/) * [Getting Started: Installation | Next.js](https://nextjs.org/docs/app/getting-started/installation) * [Installation · Get Started with Nuxt](https://nuxt.com/docs/getting-started/installation) * [Creating a project • Docs • Svelte](https://svelte.dev/docs/kit/creating-a-project) ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#node-typescript ``` 2. If the `package.json` in the repository contains `packageManager` section, [corepack](https://github.com/nodejs/corepack) installs the program automatically. Here is an example `packageManager` specification in `package.json`: ```json "packageManager": "pnpm@10.4.0+sha512.6b849d0787d97f8f4e1f03a9b8ff8f038e79e153d6f11ae539ae7c435ff9e796df6a862c991502695c7f9e8fac8aeafc1ac5a8dab47e36148d183832d886dd52", ``` The `flake.nix` should contain `corepack` package in the development shell: ```nix { devShells = eachSystem (pkgs: { default = pkgs.mkShell { buildInputs = [ ... # Use corepack to install npm/pnpm/yarn as specified in package.json pkgs.corepack ... ]; }; }); }; ``` Alternatively, you can install `yarn`, `pnpm`, or `bun` directly using Nix. Open `flake.nix` and comment out the corresponding package name in the `package` field of the default shell, depending on the package manager of your choice. ```diff devShells = eachSystem (pkgs: { default = pkgs.mkShell { buildInputs = [ pkgs.nodejs # Comment out one of these # pkgs.bun # pkgs.nodePackages.pnpm # pkgs.yarn pkgs.yarn ... ]; }; }); ``` There are several other options available. See the comments in the generated `flake.nix`. 3. Add `.envrc`: ```shell use flake ``` 4. Allow direnv: ```shell direnv allow ``` ## Developing [Section titled “Developing”](#developing) You can use `npm`, `yarn`, `pnpm`, or `bun` to develop your application as you would normally do. # Developing a Zig CLI application ## Initialize a new project [Section titled “Initialize a new project”](#initialize-a-new-project) TODO ## Add flake.nix to the project [Section titled “Add flake.nix to the project”](#add-flakenix-to-the-project) 1. Initialize the template from the root directory of the project: ```shell nix flake init -t github:akirak/flake-templates#zig ``` 2. Add `.envrc`: ```shell use flake ``` 3. Allow direnv: ```shell direnv allow ``` # Resources > A collection of resources related to developing a project with Nix flakes. ## Guides [Section titled “Guides”](#guides) * [Introduction to Nix & NixOS │ NixOS & Flakes Book](https://nixos-and-flakes.thiscute.world/introduction/) for a general introduction to Nix and flakes * [Languages and Frameworks](https://nixos.org/manual/nixpkgs/unstable/#chap-language-support) section in the Nixpkgs for language-specific build configurations ## Tools and libraries [Section titled “Tools and libraries”](#tools-and-libraries) * [Flake Parts](https://flake.parts/) is a Nix library and growing ecosystem which helps with development of Nix flakes.