From e333034519cc3d4003aaa0ef45d40517ddf4e458 Mon Sep 17 00:00:00 2001 From: James Brechtel Date: Sat, 20 Jun 2026 15:23:04 -0400 Subject: [PATCH] docs: initial scaffold implementation plan --- docs/plans/2026-06-20-initial-scaffold.md | 250 ++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 docs/plans/2026-06-20-initial-scaffold.md diff --git a/docs/plans/2026-06-20-initial-scaffold.md b/docs/plans/2026-06-20-initial-scaffold.md new file mode 100644 index 0000000..7441aad --- /dev/null +++ b/docs/plans/2026-06-20-initial-scaffold.md @@ -0,0 +1,250 @@ +# 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.