# Spine Initial Scaffold — Implementation Plan **Goal:** A minimal Emacs web server that serves a templated "Hello from Emacs." page, exercising the `simple-httpd` + `mustache.el` stack end-to-end. **Architecture:** Single `spine.el` entry point bootstraps packages, starts `simple-httpd` on port 8080, and registers a `/hello` servlet. Templates are `.mustache` files read from a `templates/` directory relative to `spine.el`. **Tech Stack:** Emacs Lisp, `simple-httpd` (MELPA), `mustache` (MELPA), `ht` (transitive). --- ## File structure | File | Responsibility | |------|---------------| | `templates/hello.mustache` | Smoke-test HTML template with `{{title}}` and `{{message}}` placeholders | | `spine.el` | Entry point: package bootstrap, server config, template renderer, `/hello` handler | `spine.el` is the sole Elisp file. No project file, no Makefile — invocation is `emacs --quick --load spine.el`. --- ### Task 1: Create the hello.mustache template **Files:** - Create: `templates/hello.mustache` - [ ] **Step 1: Create templates/ directory and hello.mustache** ```bash mkdir -p templates ``` Write `templates/hello.mustache`: ```html {{title}}

{{message}}

``` - [ ] **Step 2: Verify template file exists** Run: `cat templates/hello.mustache` Expected: outputs the template content above. - [ ] **Step 3: Commit** ```bash git add templates/hello.mustache git commit -m "feat: add hello.mustache smoke-test template" ``` --- ### Task 2: Write spine.el entry point **Files:** - Create: `spine.el` - [ ] **Step 1: Write the full spine.el** Write `spine.el`: ```elisp ;;; spine.el — personal reading tracker, served from Emacs ;; --- package bootstrap ------------------------------------------------ (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) (dolist (pkg '(simple-httpd mustache)) (unless (package-installed-p pkg) (package-refresh-contents) (package-install pkg))) (require 'simple-httpd) (require 'mustache) ;; --- configuration ---------------------------------------------------- (defvar spine-port 8080 "Port for the Spine HTTP server.") (defvar spine-template-dir (expand-file-name "templates/" (file-name-directory load-file-name)) "Directory containing .mustache templates.") ;; --- template rendering ----------------------------------------------- (defun spine-render (name context) "Render templates/NAME.mustache with CONTEXT (an ht hash table). Returns the rendered string." (mustache-render (with-temp-buffer (insert-file-contents (expand-file-name name spine-template-dir)) (buffer-string)) context)) ;; --- handlers --------------------------------------------------------- (defservlet hello text/html () (insert (spine-render "hello.mustache" (ht ("title" "Spine") ("message" "Hello from Emacs."))))) ;; --- start ------------------------------------------------------------ (setq httpd-port spine-port) (httpd-start) (message "Spine listening on http://localhost:%d" spine-port) (provide 'spine) ;;; spine.el ends here ``` - [ ] **Step 2: Verify the file has no syntax errors by loading it with Emacs in batch mode** Run: `emacs --quick --batch --load spine.el` Expected: no errors printed to stderr. The server starts briefly then Emacs exits (batch mode runs the file then quits). You should see something like: ``` Spine listening on http://localhost:8080 ``` If a package is missing, you'll see MELPA refresh output followed by install messages — that's fine, it means the bootstrap worked. - [ ] **Step 3: Commit** ```bash git add spine.el git commit -m "feat: add spine.el — package bootstrap, server, hello handler" ``` --- ### Task 3: Smoke test — first launch (package install) **Files:** - No changes — verification only. **Prerequisite:** Delete any previously installed `simple-httpd` and `mustache` packages so we test the bootstrap path. Run: ```bash rm -rf ~/.emacs.d/elpa/simple-httpd-* ~/.emacs.d/elpa/mustache-* ~/.emacs.d/elpa/ht-* ``` If you're using a custom `package-user-dir`, adjust the paths accordingly. If you don't want to nuke your real packages, set `package-user-dir` to a temp directory for this test: ```bash mkdir -p /tmp/spine-elpa emacs --quick --eval "(setq package-user-dir \"/tmp/spine-elpa\")" --load spine.el ``` (Use whichever approach fits your setup — the key is testing the fresh-install path.) - [ ] **Step 1: Start Emacs with spine.el (fresh package state)** Run (in one terminal, Emacs stays running): ```bash emacs --quick --load spine.el ``` Expected output in the `*Messages*` buffer: - MELPA archive refresh output (first-time only) - Package install messages for `simple-httpd`, `mustache`, `ht` - `Spine listening on http://localhost:8080` - [ ] **Step 2: Verify /hello endpoint** In another terminal: ```bash curl -s http://localhost:8080/hello ``` Expected: HTML output containing `

Hello from Emacs.

` and `Spine`. - [ ] **Step 3: Stop Emacs** In the Emacs terminal, press `C-x C-c` to quit. --- ### Task 4: Smoke test — second launch (no package install) **Files:** - No changes — verification only. - [ ] **Step 1: Start Emacs again (packages already installed)** ```bash emacs --quick --load spine.el ``` Expected: no MELPA refresh output, no package install messages. Only `Spine listening on http://localhost:8080`. - [ ] **Step 2: Verify /hello still works** ```bash curl -s http://localhost:8080/hello ``` Expected: same HTML as before. - [ ] **Step 3: Stop Emacs** (`C-x C-c`) --- ### Task 5: Final commit **Files:** - No code changes — just confirming all commits are done. - [ ] **Step 1: Verify git status is clean** ```bash git status ``` Expected: `nothing to commit, working tree clean` If anything shows as modified, stage and commit it: ```bash git add -A git commit -m "chore: finalize initial scaffold" ``` - [ ] **Step 2: Review commit log** ```bash git log --oneline ``` Expected: 2–4 commits covering the template, spine.el, and any fixes.