Files
spine/docs/plans/2026-06-20-initial-scaffold.md

251 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{title}}</title>
</head>
<body>
<h1>{{message}}</h1>
</body>
</html>
```
- [ ] **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 `<h1>Hello from Emacs.</h1>` and `<title>Spine</title>`.
- [ ] **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: 24 commits covering the template, spine.el, and any fixes.