> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jylhis.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> How Jotain is structured

# Architecture Overview

Jotain is organised into distinct layers, each with a clear responsibility.

## File Structure

```
jotain/
├── early-init.el       # Pre-package/GUI initialisation
├── init.el             # Entry point — loads modules in order
├── lisp/               # Modular Elisp config (init-*.el, one per concern)
├── emacs.nix           # GNU Emacs build from source
├── default.nix         # Distribution wrapper (Emacs + tree-sitter grammars)
├── module.nix          # Home Manager module for the daemon
├── nix/
│   ├── devenv-emacs-lisp.nix  # devenv language module for Elisp
│   ├── ellsp.nix              # ellsp (Emacs LSP) package definition
│   └── elsa.nix               # elsa (Elisp static analyser)
├── devenv.nix          # Development shell
├── devenv.yaml         # devenv inputs (pinned to flake.lock revs)
├── flake.nix           # Flake entry point — source of truth for pins
├── Justfile            # Task runner recipes
├── docs/               # Mintlify documentation (this site)
└── journal/            # Development journal entries
```

## Layers

### Emacs Lisp Layer

The Elisp configuration is split into three parts:

1. **`early-init.el`** — loaded before `package.el`, before the first frame, before `init.el`. Handles anything that *must* happen that early: the startup GC threshold, `use-package-always-ensure`, frame chrome defaults, native-comp and eln-cache redirection, terminal aliases.

2. **`init.el`** — tiny entry point. Registers MELPA/NonGNU ELPA as fallback archives, puts `lisp/` on the load-path, points `custom-file` at `var/custom.el` (write-only — never loaded back), refreshes archive contents on the first run, and `require`s each module in order.

3. **`lisp/init-*.el`** — one file per concern. See [Modules](/architecture/modules) for the full list and their responsibilities.

### Nix Layer

The Nix layer provides reproducible Emacs builds:

1. **`emacs.nix`** — wraps nixpkgs' default `emacs` attribute (default), the git-based attrs from [`nix-community/emacs-overlay`](https://github.com/nix-community/emacs-overlay) (`git`/`unstable`/`igc`), or `pkgs.emacs-macport` with the full set of build flags exposed as arguments. A cache-parity invariant guarantees that `import ./emacs.nix {}` produces the same store path as `pkgs.emacs` (and each overlay variant the matching overlay attr), so default-rev builds are cache hits against Hydra and `nix-community.cachix.org`. Only custom `rev` pins and Darwin patches run through `overrideAttrs` and intentionally rebuild from source.

2. **`emacs-jylhis.nix`** — builds the pinned `github:jylhis/emacs` Meson fork. The flake exposes it as a non-default opt-in backend so consumer flakes can install the same Jotain setup on the fork without changing the stable default.

3. **`default.nix`** — flake-compat wrapper for the default package set.

4. **`module.nix`** — Home Manager module that runs Jotain as a user-session Emacs daemon (`services.jotain`), generates a desktop entry for `emacsclient`, and can install itself as `EDITOR`/`VISUAL`. Supports systemd on Linux and launchd on macOS, with `services.jotain.emacsBackend = "jylhis"` for the fork backend.

### Development Layer

* **`devenv.nix`** — development shell. Provides the local Emacs build (so `emacs` in the shell matches `just build-bare`), Nerd Fonts, `nil`, `nixfmt-rfc-style`, and `treefmt`. Enables the custom `languages.emacs-lisp` module from `nix/devenv-emacs-lisp.nix`, which provides Emacs + `eask-cli` (with `ellsp` and `elsa` off by default).
* **`Justfile`** — every recipe you run day-to-day: `run`, `debug`, `tty`, `check`, `compile`, `test`, the `build-*` matrix, `fmt`, `update`, `verify`, `clean`, `clean-all`.
* **Pinning** — `flake.lock` is the single source of truth; `default.nix` and `emacs.nix` read it directly via `fetchTarball` so non-flake `nix-build` consumers get the same pin. `devenv.yaml` mirrors the flake's shared input revs (`nixpkgs`, `treefmt-nix`), and `just update` keeps `devenv.lock` in lockstep.
