diff --git a/13-overlay/README.md b/13-overlay/README.md new file mode 100644 index 0000000..c6a12c4 --- /dev/null +++ b/13-overlay/README.md @@ -0,0 +1,21 @@ +# 13-overlay + +This example shows a small flake overlay. + +It includes: + +- `overlays.default`, +- one package added by the overlay, +- a package output that imports `nixpkgs` with that overlay, and +- a check run by `nix flake check`. + +Useful commands: + +```bash +nix build +./result/bin/hello-overlay + +nix run +nix flake check +nix flake show +``` diff --git a/13-overlay/flake.lock b/13-overlay/flake.lock new file mode 100644 index 0000000..dfdfdf9 --- /dev/null +++ b/13-overlay/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1776548001, + "narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/13-overlay/flake.nix b/13-overlay/flake.nix new file mode 100644 index 0000000..323b7a8 --- /dev/null +++ b/13-overlay/flake.nix @@ -0,0 +1,48 @@ +{ + # Exposes an overlay that adds one package, then imports nixpkgs with that + # overlay so the package is available through normal flake outputs. + description = "A minimal overlay example"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { self, nixpkgs, ... }: + let + system = "x86_64-linux"; + + overlay = _: prev: { + hello-overlay = prev.writeShellScriptBin "hello-overlay" '' + echo "hello from an overlay" + ''; + }; + + pkgs = import nixpkgs { + inherit system; + overlays = [ overlay ]; + }; + in + { + overlays.default = overlay; + + packages.${system}.default = pkgs.hello-overlay; + + apps.${system}.default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/hello-overlay"; + meta.description = "Run the package added by the overlay."; + }; + + checks.${system}.runs = pkgs.runCommand "hello-overlay-runs" { } '' + output="$(${self.packages.${system}.default}/bin/hello-overlay)" + + if [ "$output" = "hello from an overlay" ]; then + echo ok > "$out" + else + echo "unexpected output: $output" >&2 + exit 1 + fi + ''; + }; +} diff --git a/14-template/README.md b/14-template/README.md new file mode 100644 index 0000000..a78b64b --- /dev/null +++ b/14-template/README.md @@ -0,0 +1,17 @@ +# 14-template + +This example shows a small `templates.default` output. + +It includes: + +- one reusable flake template under `template/`, +- a description shown by `nix flake show`, and +- a check that verifies the template files contain the expected scaffold. + +Useful commands: + +```bash +nix flake show +nix flake init -t .#default +nix flake check +``` diff --git a/14-template/flake.lock b/14-template/flake.lock new file mode 100644 index 0000000..dfdfdf9 --- /dev/null +++ b/14-template/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1776548001, + "narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/14-template/flake.nix b/14-template/flake.nix new file mode 100644 index 0000000..77f37f2 --- /dev/null +++ b/14-template/flake.nix @@ -0,0 +1,31 @@ +{ + # Exposes one flake template that scaffolds a tiny dev-shell-based flake. + description = "A minimal flake template example"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { nixpkgs, ... }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + in + { + templates.default = { + path = ./template; + description = "Scaffold a tiny flake with one dev shell."; + }; + + checks.${system}.template-files = pkgs.runCommand "template-files-check" { } '' + cp ${./template/flake.nix} ./flake.nix + cp ${./template/README.md} ./README.md + + grep -q 'devShells\..*default' ./flake.nix + grep -q 'nix develop' ./README.md + + echo ok > "$out" + ''; + }; +} diff --git a/14-template/template/README.md b/14-template/template/README.md new file mode 100644 index 0000000..2cd73de --- /dev/null +++ b/14-template/template/README.md @@ -0,0 +1,9 @@ +# Template Output + +This scaffold gives you a tiny flake with one dev shell. + +Try: + +```bash +nix develop +``` diff --git a/14-template/template/flake.nix b/14-template/template/flake.nix new file mode 100644 index 0000000..6cb5880 --- /dev/null +++ b/14-template/template/flake.nix @@ -0,0 +1,19 @@ +{ + description = "A tiny flake scaffolded from 14-template"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = + { nixpkgs, ... }: + let + system = "x86_64-linux"; + pkgs = import nixpkgs { inherit system; }; + in + { + devShells.${system}.default = pkgs.mkShell { + packages = [ pkgs.jq ]; + }; + }; +} diff --git a/15-follows-and-inputs/README.md b/15-follows-and-inputs/README.md new file mode 100644 index 0000000..baa5884 --- /dev/null +++ b/15-follows-and-inputs/README.md @@ -0,0 +1,21 @@ +# 15-follows-and-inputs + +This example shows multiple flake inputs and one `follows` relationship. + +It includes: + +- a top-level `systems` input, +- `flake-utils` configured to reuse that input with `follows`, +- a small package and app output, and +- a check run by `nix flake check`. + +Useful commands: + +```bash +nix flake metadata +nix flake show +nix build +./result/bin/show-follows +nix run +nix flake check +``` diff --git a/15-follows-and-inputs/flake.lock b/15-follows-and-inputs/flake.lock new file mode 100644 index 0000000..9232a54 --- /dev/null +++ b/15-follows-and-inputs/flake.lock @@ -0,0 +1,64 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1776548001, + "narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/15-follows-and-inputs/flake.nix b/15-follows-and-inputs/flake.nix new file mode 100644 index 0000000..3b6e78c --- /dev/null +++ b/15-follows-and-inputs/flake.nix @@ -0,0 +1,52 @@ +{ + # Shows multiple flake inputs plus a `follows` edge that makes one + # transitive input reuse a top-level input from this flake. + description = "A minimal follows and inputs example"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + systems.url = "github:nix-systems/default"; + + flake-utils = { + url = "github:numtide/flake-utils"; + inputs.systems.follows = "systems"; + }; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + packages.default = pkgs.writeShellScriptBin "show-follows" '' + echo "flake-utils is sharing the top-level systems input" + ''; + + apps.default = { + type = "app"; + program = "${self.packages.${system}.default}/bin/show-follows"; + meta.description = "Run the package built in the follows example."; + }; + + checks.runs = pkgs.runCommand "show-follows-runs" { } '' + output="$(${self.packages.${system}.default}/bin/show-follows)" + + if [ "$output" = "flake-utils is sharing the top-level systems input" ]; then + echo ok > "$out" + else + echo "unexpected output: $output" >&2 + exit 1 + fi + ''; + } + ); +} diff --git a/notes/016-overlays.md b/notes/016-overlays.md new file mode 100644 index 0000000..e42f6af --- /dev/null +++ b/notes/016-overlays.md @@ -0,0 +1,81 @@ +# Overlays + +This note covers `13-overlay/`, which defines `overlays.default` and then imports `nixpkgs` with that overlay to expose the overlaid package as a normal flake output. + +--- + +## 1. What an Overlay Is + +An overlay is a function: + +```nix +final: prev: { + ... +} +``` + +It receives: + +- `prev`: the package set before your changes, and +- `final`: the package set after all overlays are applied. + +The result is an attrset of additions or overrides. + +This example writes the first argument as `_` because it only needs `prev`: + +```nix +overlay = _: prev: { + ... +}; +``` + +--- + +## 2. The Smallest Useful Pattern + +This example adds one package: + +```nix +overlay = _: prev: { + hello-overlay = prev.writeShellScriptBin "hello-overlay" '' + echo "hello from an overlay" + ''; +}; +``` + +Then it imports `nixpkgs` with that overlay: + +```nix +pkgs = import nixpkgs { + inherit system; + overlays = [ overlay ]; +}; +``` + +That is the key mechanic. The overlay itself is just a function. It does nothing until you import a package set with it. + +--- + +## 3. Why the Flake Exposes Both + +The example exposes: + +- `overlays.default`, so other flakes can reuse the overlay, and +- `packages..default`, so the same flake is easy to build and run locally. + +That makes the example useful both as a teaching flake and as a reusable overlay source. + +--- + +## 4. Commands to Try + +```bash +cd 13-overlay + +nix build +./result/bin/hello-overlay + +nix run +nix flake show +nix flake check +``` diff --git a/notes/017-templates.md b/notes/017-templates.md new file mode 100644 index 0000000..0dd6b5b --- /dev/null +++ b/notes/017-templates.md @@ -0,0 +1,46 @@ +# Templates + +This note covers `14-template/`, which exposes `templates.default` so `nix flake init -t` can scaffold a new flake from files in the repository. + +--- + +## 1. What a Template Output Is + +A template output is metadata plus a path: + +```nix +templates.default = { + path = ./template; + description = "Scaffold a tiny flake with one dev shell."; +}; +``` + +The `path` points at the directory that should be copied into the new project. The `description` is what users see in `nix flake show`. + +--- + +## 2. Why the Template Lives in Its Own Directory + +The template is just ordinary files. In this example, `template/` contains: + +- a small `flake.nix`, and +- a short `README.md`. + +That separation matters because the example flake and the template flake are doing different jobs: + +- `14-template/flake.nix` publishes the template, and +- `14-template/template/flake.nix` is the scaffold that gets copied into a new directory. + +--- + +## 3. Commands to Try + +```bash +cd 14-template + +nix flake show + +mkdir /tmp/template-demo +cd /tmp/template-demo +nix flake init -t /path/to/nix-playground/14-template#default +``` diff --git a/notes/018-follows-and-inputs.md b/notes/018-follows-and-inputs.md new file mode 100644 index 0000000..3fd37dd --- /dev/null +++ b/notes/018-follows-and-inputs.md @@ -0,0 +1,57 @@ +# Follows and Inputs + +This note covers `15-follows-and-inputs/`, which defines multiple inputs and uses `follows` so one transitive input is reused instead of resolved separately. + +--- + +## 1. What `follows` Does + +`follows` points one input at another input by name: + +```nix +flake-utils = { + url = "github:numtide/flake-utils"; + inputs.systems.follows = "systems"; +}; +``` + +That means `flake-utils` does not resolve its own separate `systems` input. It reuses the top-level `systems` input from this flake. + +--- + +## 2. Why This Matters + +Without `follows`, transitive dependencies can drift apart. Two flakes may each resolve their own copy of an input, even though you wanted them to share one. + +This example keeps the case small: + +- one top-level `systems` input, +- one dependent flake, `flake-utils`, and +- one `follows` edge that ties them together. + +That makes it easy to inspect with `nix flake metadata`. + +--- + +## 3. Why the Example Still Builds Something + +The flake uses `flake-utils.lib.eachDefaultSystem` so the dependency is not just declared, but actually used. The package itself stays trivial because the point of the example is the input graph, not the package. + +If you want to compare output-generation styles, see `03-multi-system/`. This example is about input wiring. + +--- + +## 4. Commands to Try + +```bash +cd 15-follows-and-inputs + +nix flake metadata +nix flake show + +nix build +./result/bin/show-follows + +nix run +nix flake check +```