From 82902fbfeb07144ed4d505ba68a8bf59ec936d1a Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 21:00:40 +0000 Subject: [PATCH 1/6] Docs: Devcontainers --- book/src/SUMMARY.md | 1 + book/src/chapter_2.md | 86 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 book/src/chapter_2.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 2014c0d..8e69f04 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -1,3 +1,4 @@ # Summary - [Git: Step Zero](./chapter_1.md) +- [Devcontainer](./chapter_2.md) diff --git a/book/src/chapter_2.md b/book/src/chapter_2.md new file mode 100644 index 0000000..3c7f8be --- /dev/null +++ b/book/src/chapter_2.md @@ -0,0 +1,86 @@ +# Devcontainer + +Devcontainers often get a bad reputation—and sometimes deservedly so. Running Docker for a simple webpage feels like swatting a fly with a sledgehammer, especially when the container is bloated and slow. + +But the *idea* behind devcontainers is sound: **a reproducible, isolated development environment**. + +## The Real Problem + +It's not about Docker. It's about maintaining focus and productivity by keeping your working environment clean: + +- VS Code extensions that conflict or clutter +- System binaries that drift between machines +- "Works on my machine" debugging sessions +- Configuration that accumulates like sediment + +A devcontainer solves this by declaring exactly what your environment should contain—nothing more, nothing less. + +> **macOS Users:** If you're developing locally, use [OrbStack](https://orbstack.dev/) instead of Docker Desktop. It's significantly faster, lighter on resources, and makes devcontainer iteration actually pleasant. The trial is generous enough to evaluate whether the speed gains justify the cost. + +## Starting Minimal + +This template's initial devcontainer ([cc11da7](https://github.com/alyssa-e/dev/commit/cc11da7273691c76e44d6317dc5547561d078024)) was intentionally sparse: + +```json +{ + "image": "debian:bookworm-slim", + "features": { + "ghcr.io/devcontainers/features/nix:1": { + "packages": ["direnv"] + } + }, + "customizations": { + "vscode": { + "extensions": ["jnoortheen.nix-ide"], + "settings": { + "editor.wordWrap": "on", + "git.autofetch": true + } + } + } +} +``` + +That's it: +- **Debian slim** - A minimal base, not Ubuntu with kitchen sink +- **Nix + direnv** - The foundation for reproducible tooling (more on this later) +- **One extension** - Nix language support +- **Sensible defaults** - Word wrap, auto-fetch + +## Why This Matters + +The devcontainer is the *second* commit in this repository's history (after `.gitignore`). This ordering is intentional: + +1. **Step 0**: Ignore the right files +2. **Step 1**: Define the environment + +Everything else—the actual code, the tools, the configuration—builds on this foundation. When you open this repository in VS Code or GitHub Codespaces, you get exactly the environment the project expects. + +## The Nix Connection + +Notice that we install Nix immediately. The devcontainer itself stays minimal because Nix (via `shell.nix` and `direnv`) handles the actual development tools. This separation means: + +- The container is fast to build +- Tools are managed declaratively in Nix +- You can use the same Nix configuration outside Docker + +We'll cover Nix in detail in a later chapter. + +## When to Use Devcontainers + +Use them when: +- **Onboarding matters** - New contributors should be productive in minutes +- **Environment consistency is critical** - CI/CD should match local dev +- **You're using Codespaces** - It's the native way to define the environment + +Skip them when: +- The project is simple enough that a README suffices +- Docker overhead genuinely hurts your workflow +- You're the only developer and prefer native tooling + +The goal isn't Docker for Docker's sake—it's having a single source of truth for "what does this project need to run?" + +--- + +- https://containers.dev/ +- https://code.visualstudio.com/docs/devcontainers/containers From a21ecc890d7562b85e1c1c8a78b18e28bcaf62af Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 20:34:42 -0800 Subject: [PATCH 2/6] Apply suggestions from Code Review --- book/src/SUMMARY.md | 2 +- book/src/chapter_1.md | 3 ++- book/src/chapter_2.md | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 8e69f04..9ac43d0 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -1,4 +1,4 @@ # Summary - [Git: Step Zero](./chapter_1.md) -- [Devcontainer](./chapter_2.md) +- [Devcontainers](./chapter_2.md) diff --git a/book/src/chapter_1.md b/book/src/chapter_1.md index c129d0d..42f76e6 100644 --- a/book/src/chapter_1.md +++ b/book/src/chapter_1.md @@ -4,7 +4,7 @@ Git needs no introduction—it's the ubiquitous version control system you alrea ## The Initial Commit -This repository started with a single commit ([821861c](https://github.com/alyssa-e/dev/commit/821861c9bc14679aa12fd1b7c8833219ce0a1616)) containing only a `.gitignore`: +This repository started with a single commit ([821861c](https://github.com/alycda/dev/commit/821861c9bc14679aa12fd1b7c8833219ce0a1616)) containing only a `.gitignore`: ```gitignore # Ignore build outputs from performing a nix-build or `nix build` command @@ -52,5 +52,6 @@ The specific patterns vary; the principle doesn't. Start clean, stay clean. --- +- https://learnxinyminutes.com/git/ - https://git-scm.com/docs/gitignore - https://www.kernel.org/pub/software/scm/git/docs/gitignore.html \ No newline at end of file diff --git a/book/src/chapter_2.md b/book/src/chapter_2.md index 3c7f8be..bea045e 100644 --- a/book/src/chapter_2.md +++ b/book/src/chapter_2.md @@ -1,4 +1,4 @@ -# Devcontainer +# Devcontainers Devcontainers often get a bad reputation—and sometimes deservedly so. Running Docker for a simple webpage feels like swatting a fly with a sledgehammer, especially when the container is bloated and slow. @@ -19,7 +19,7 @@ A devcontainer solves this by declaring exactly what your environment should con ## Starting Minimal -This template's initial devcontainer ([cc11da7](https://github.com/alyssa-e/dev/commit/cc11da7273691c76e44d6317dc5547561d078024)) was intentionally sparse: +This template's initial devcontainer ([cc11da7](https://github.com/alycda/dev/commit/cc11da7273691c76e44d6317dc5547561d078024)) was intentionally sparse: ```json { @@ -82,5 +82,6 @@ The goal isn't Docker for Docker's sake—it's having a single source of truth f --- +- https://learnxinyminutes.com/docker/ - https://containers.dev/ - https://code.visualstudio.com/docs/devcontainers/containers From 378a583d8b6734bd861fbaf3d8fe76de763a163c Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 21:01:12 +0000 Subject: [PATCH 3/6] Docs: Nix - direnv - nix-shell --- book/src/SUMMARY.md | 1 + book/src/chapter_2.md | 2 +- book/src/chapter_3.md | 90 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 book/src/chapter_3.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 9ac43d0..fa48095 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -2,3 +2,4 @@ - [Git: Step Zero](./chapter_1.md) - [Devcontainers](./chapter_2.md) +- [Nix](./chapter_3.md) diff --git a/book/src/chapter_2.md b/book/src/chapter_2.md index bea045e..506e190 100644 --- a/book/src/chapter_2.md +++ b/book/src/chapter_2.md @@ -64,7 +64,7 @@ Notice that we install Nix immediately. The devcontainer itself stays minimal be - Tools are managed declaratively in Nix - You can use the same Nix configuration outside Docker -We'll cover Nix in detail in a later chapter. +We'll cover Nix in detail in the next [chapter](./chapter_3.md). ## When to Use Devcontainers diff --git a/book/src/chapter_3.md b/book/src/chapter_3.md new file mode 100644 index 0000000..14b478f --- /dev/null +++ b/book/src/chapter_3.md @@ -0,0 +1,90 @@ +# Nix + +Nix is a package manager that guarantees reproducibility. Same inputs, same outputs—every time, on every machine. + +If you've ever dealt with "it works on my machine" or spent hours debugging environment differences, Nix solves that problem at the root. + +## The Core Idea + +Traditional package managers install software globally and hope for the best. Nix takes a different approach: + +- **Immutable packages** - Each package is stored in isolation with a unique hash +- **Declarative configuration** - You describe *what* you want, not *how* to install it +- **Reproducible builds** - The same `shell.nix` produces the same environment everywhere + +## The Initial Setup + +This template's first Nix integration ([8b951a5](https://github.com/alycda/dev/commit/8b951a56c38efb96b6f7533d6b10a946b7d3c233)) added three files: + +### shell.nix + +```nix +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = with pkgs; [ just ]; +} +``` + +This declares a shell environment with one tool: `just` (a command runner). Want more tools? Add them to the list: + +```nix +buildInputs = with pkgs; [ just nodejs python3 rustc ]; +``` + +### .envrc + +```bash +use nix +``` + +This one-liner tells `direnv` to activate the Nix shell automatically when you enter the directory. + +### The Hook + +The devcontainer's `postCreateCommand` wires it together: + +```bash +echo 'eval "$(direnv hook bash)"' >> ~/.bashrc && direnv allow +``` + +## How It Works + +1. You `cd` into the project directory +2. `direnv` detects `.envrc` +3. `.envrc` says `use nix` +4. Nix builds/fetches the packages in `shell.nix` +5. Your shell now has those tools available + +Leave the directory, tools disappear. Enter again, they're back. No global pollution. + +## Why This Matters + +The devcontainer installs Nix, but Nix manages the actual tools. This separation is powerful: + +- **Lightweight container** - Just Debian + Nix, nothing else +- **Declarative tools** - `shell.nix` is version-controlled documentation of your dependencies +- **Works anywhere** - Same `shell.nix` works on macOS, Linux, or in Codespaces +- **Easy iteration** - Add a tool to `shell.nix`, run `direnv reload`, done + +## Current State + +The template's `shell.nix` has grown to include several tools: + +```nix +buildInputs = with pkgs; [ just cheat asciinema presenterm tmux mdbook ]; +``` + +Each of these gets its own chapter later. The point is: adding tools is trivial. One line in `shell.nix`, and everyone who clones this repo gets the same environment. + +## Finding Packages + +Search for packages at [search.nixos.org](https://search.nixos.org/packages). The repository has over 100,000 packages—if it exists, Nix probably has it. + +--- + +- https://nixos.org/ +- https://nix.dev/ (tutorials) +- https://direnv.net/ +- https://learnxinyminutes.com/nix/ +- https://nixcloud.io/tour/ From 02164c374bc87b9b4dcbe7326188996b9c2e349a Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 22:05:59 +0000 Subject: [PATCH 4/6] Docs: Nix Home Manager --- book/src/SUMMARY.md | 3 +- book/src/chapter_2.md | 2 +- book/src/{chapter_3.md => nix/README.md} | 0 book/src/nix/home-manager.md | 118 +++++++++++++++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) rename book/src/{chapter_3.md => nix/README.md} (100%) create mode 100644 book/src/nix/home-manager.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index fa48095..8d09938 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -2,4 +2,5 @@ - [Git: Step Zero](./chapter_1.md) - [Devcontainers](./chapter_2.md) -- [Nix](./chapter_3.md) +- [Nix](./nix/README.md) + - [Home Manager](./nix/home-manager.md) \ No newline at end of file diff --git a/book/src/chapter_2.md b/book/src/chapter_2.md index 506e190..94040fe 100644 --- a/book/src/chapter_2.md +++ b/book/src/chapter_2.md @@ -64,7 +64,7 @@ Notice that we install Nix immediately. The devcontainer itself stays minimal be - Tools are managed declaratively in Nix - You can use the same Nix configuration outside Docker -We'll cover Nix in detail in the next [chapter](./chapter_3.md). +We'll cover Nix in detail in the next [chapter](./nix/README.md). ## When to Use Devcontainers diff --git a/book/src/chapter_3.md b/book/src/nix/README.md similarity index 100% rename from book/src/chapter_3.md rename to book/src/nix/README.md diff --git a/book/src/nix/home-manager.md b/book/src/nix/home-manager.md new file mode 100644 index 0000000..57eb5c5 --- /dev/null +++ b/book/src/nix/home-manager.md @@ -0,0 +1,118 @@ +# Nix: Home Manager + +The previous chapter covered `shell.nix` for project-specific tools. But what about tools you want *everywhere*—your editor, your shell configuration, your personal utilities? + +That's what [Home Manager](https://github.com/nix-community/home-manager) solves. + +## shell.nix vs home.nix + +Think of it this way: + +| | shell.nix | home.nix | +|---|---|---| +| **Scope** | Per-project | Per-user | +| **Activates** | When you `cd` into directory | Always available | +| **Use for** | Project dependencies | Personal tools and config | + +`shell.nix` gives you `just` and `mdbook` when working on this template. `home.nix` gives you `helix` and `ripgrep` no matter what directory you're in. + +## The Initial Setup + +Home Manager was introduced in commit [c8ec56a](https://github.com/alycda/dev/commit/c8ec56a009f579f012a17566f5862dd2bd42cd81): + +```nix +{ pkgs, ... }: +{ + programs.home-manager.enable = true; + + home.packages = with pkgs; [ + helix + ripgrep + ]; + + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; + + home.stateVersion = "24.05"; + home.username = "root"; + home.homeDirectory = "/root"; +} +``` + +This declares: +- **Core packages** - `helix` (editor) and `ripgrep` (search) available globally +- **direnv integration** - With `nix-direnv` for faster Nix shell loading +- **Self-management** - Home Manager can update itself + +## Beyond Packages + +Home Manager doesn't just install tools—it *configures* them. The current `home.nix` includes: + +```nix +home.sessionVariables = { + EDITOR = "hx"; + VISUAL = "code"; +}; + +programs.bash = { + enable = true; + initExtra = '' + # Custom shell initialization + ''; +}; +``` + +Your editor preferences, shell configuration, environment variables—all declarative, all version-controlled. + +## The Rebuild Command + +When you modify `home.nix`, apply changes with: + +```bash +just rebuild +``` + +Which runs: + +```bash +home-manager switch -b backup -f .devcontainer/home.nix +``` + +The `-b backup` flag preserves any existing dotfiles that would be overwritten. + +## Current State + +The template's `home.nix` has grown to include: + +```nix +home.packages = with pkgs; [ + helix # Terminal editor + ripgrep # Fast search + jujutsu # Git-compatible VCS + gh # GitHub CLI + claude-code # AI assistant +]; +``` + +Each tool is available immediately in any new shell, not just project directories. + +## Why Two Layers? + +This separation—`shell.nix` for projects, `home.nix` for user—mirrors how you actually work: + +1. **Personal tools** (editor, shell, utilities) follow you everywhere +2. **Project tools** (build systems, language toolchains) activate per-project + +A Node.js project needs `nodejs` in its `shell.nix`. But you want `helix` and `ripgrep` regardless of what project you're in. + +## Up Next: Just + +You've seen `just rebuild` above. The next chapter covers Just—a command runner that ties these tools together with simple, memorable commands. + +--- + +- https://github.com/nix-community/home-manager +- https://nix-community.github.io/home-manager/ +- https://home-manager-options.extranix.com/ From e75999929be26716ea6b54116c88e0c82314ffae Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 23:33:57 -0800 Subject: [PATCH 5/6] Apply suggestions from Code Review --- .devcontainer/devcontainer.json | 2 +- book/src/SUMMARY.md | 3 ++- book/src/nix/README.md | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a37e37b..92cd5c5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,7 @@ ], "features": { "ghcr.io/devcontainers/features/nix:1": { - "packages": [] // home-manager handles packages + "packages": [] // home-manager handles packages, like direnv } }, "secrets": { diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 8d09938..75775d2 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -3,4 +3,5 @@ - [Git: Step Zero](./chapter_1.md) - [Devcontainers](./chapter_2.md) - [Nix](./nix/README.md) - - [Home Manager](./nix/home-manager.md) \ No newline at end of file + - [Home Manager](./nix/home-manager.md) + - [Flakes]() \ No newline at end of file diff --git a/book/src/nix/README.md b/book/src/nix/README.md index 14b478f..98a8bd3 100644 --- a/book/src/nix/README.md +++ b/book/src/nix/README.md @@ -72,7 +72,7 @@ The devcontainer installs Nix, but Nix manages the actual tools. This separation The template's `shell.nix` has grown to include several tools: ```nix -buildInputs = with pkgs; [ just cheat asciinema presenterm tmux mdbook ]; +buildInputs = with pkgs; [ just cheat asciinema_3 presenterm tmux mdbook ]; ``` Each of these gets its own chapter later. The point is: adding tools is trivial. One line in `shell.nix`, and everyone who clones this repo gets the same environment. From b2dc2015e23d88c7b3de86ce3a21954c8d0ededd Mon Sep 17 00:00:00 2001 From: Alyssa Evans Date: Mon, 29 Dec 2025 22:13:57 +0000 Subject: [PATCH 6/6] Docs: Tools - justfile --- book/src/SUMMARY.md | 4 +- book/src/nix/home-manager.md | 2 +- book/src/tools/README.md | 14 ++++ book/src/tools/jj.md | 0 book/src/tools/just.md | 125 +++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 book/src/tools/README.md create mode 100644 book/src/tools/jj.md create mode 100644 book/src/tools/just.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 75775d2..7a0b385 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -4,4 +4,6 @@ - [Devcontainers](./chapter_2.md) - [Nix](./nix/README.md) - [Home Manager](./nix/home-manager.md) - - [Flakes]() \ No newline at end of file + - [Flakes]() +- [Tools](./tools/README.md) + - [Just](./tools/just.md) diff --git a/book/src/nix/home-manager.md b/book/src/nix/home-manager.md index 57eb5c5..ca70255 100644 --- a/book/src/nix/home-manager.md +++ b/book/src/nix/home-manager.md @@ -109,7 +109,7 @@ A Node.js project needs `nodejs` in its `shell.nix`. But you want `helix` and `r ## Up Next: Just -You've seen `just rebuild` above. The next chapter covers Just—a command runner that ties these tools together with simple, memorable commands. +You've seen `just rebuild` above. The [next chapter](./tools/just.md) covers Just—a command runner that ties these tools together with simple, memorable commands. --- diff --git a/book/src/tools/README.md b/book/src/tools/README.md new file mode 100644 index 0000000..54f7b9d --- /dev/null +++ b/book/src/tools/README.md @@ -0,0 +1,14 @@ +# Tools + +This section covers the tools included in this template's `shell.nix`. They're available automatically when you enter the project directory thanks to direnv. + +These aren't arbitrary choices—each solves a specific friction point in development workflows: + +- **Just** - Command runner for memorable aliases +- **cheat** - Quick reference for commands you forget +- **Jujutsu** - Git-compatible VCS with better UX +- **Presenterm** - Terminal-based presentations +- **Asciinema** - Record terminal sessions +- **mdbook** - Generate documentation sites + +All are installed via Nix, so they're reproducible across machines and don't pollute your global system. diff --git a/book/src/tools/jj.md b/book/src/tools/jj.md new file mode 100644 index 0000000..e69de29 diff --git a/book/src/tools/just.md b/book/src/tools/just.md new file mode 100644 index 0000000..43a9311 --- /dev/null +++ b/book/src/tools/just.md @@ -0,0 +1,125 @@ +# Just + +[Just](https://github.com/casey/just) is a command runner—like `make`, but without the baggage. + +No build system complexity. No implicit rules. No tabs-vs-spaces drama. Just simple commands you can remember. + +## Why Not Make? + +Make is powerful but optimized for building C programs in the 1970s. For modern development tasks, you fight against it: + +- Recipes are file-based by default (you want `.PHONY` everywhere) +- Tab-only indentation causes invisible bugs +- The syntax is arcane and full of surprises +- Error messages assume you're compiling object files + +Just drops all that. It's a command runner, not a build system. + +## The Initial Setup + +Just was introduced alongside the Nix shell configuration ([8b951a5](https://github.com/alycda/dev/commit/8b951a56c38efb96b6f7533d6b10a946b7d3c233)): + +```just +_default: + @just --list +``` + +That's the entire initial justfile—a single recipe that lists available commands. The underscore prefix hides it from the list output. + +## Current Recipes + +The template's justfile has grown to include: + +```just +_default: + @just --list + +rebuild: + home-manager switch -b backup -f .devcontainer/home.nix + +cheats: + cheat -l + +present: + presenterm slides.md + +[working-directory: 'book'] +book: + mdbook serve --open + +[working-directory: 'book'] +build-book: + mdbook build +``` + +Each recipe is a memorable alias for a longer command. Can't remember the exact `home-manager` incantation? `just rebuild`. + +## Key Features + +### Self-Documenting + +Running `just` with no arguments shows all available recipes: + +``` +$ just +Available recipes: + book + build-book + cheats + present + rebuild +``` + +### Working Directory Control + +```just +[working-directory: 'book'] +book: + mdbook serve --open +``` + +This runs the command from `book/`, regardless of where you invoke `just`. + +### Variables and Exports + +```just +export USER := shell("whoami") +``` + +Environment variables and shell commands work naturally. + +### Recipe Dependencies + +```just +build-book-gha: + just build-book + mv book ../_site +``` + +Recipes can call other recipes. + +## The Pattern + +A good justfile follows a simple pattern: + +1. **Start minimal** - One `_default` recipe that lists commands +2. **Add as needed** - When you type a command more than twice, make it a recipe +3. **Keep it obvious** - Recipe names should be guessable (`build`, `test`, `deploy`) + +Don't over-engineer it. The goal is to avoid memorizing flags, not to build a complex automation system. + +## Why It Lives in shell.nix + +Just is a project tool—you need it when working on *this* project, not globally. That's why it's in `shell.nix`: + +```nix +buildInputs = with pkgs; [ just cheat asciinema presenterm tmux mdbook ]; +``` + +When you `cd` into the project, direnv activates the Nix shell, and `just` becomes available. + +--- + +- https://github.com/casey/just +- https://just.systems/man/en/ +- https://learnxinyminutes.com/make/