Files
spine/docs/specs/2026-06-21-edit-book-actions-design.md
T

4.4 KiB

Edit Book Actions — design spec

Problem

The index page shows books grouped by status but provides no way to change a book's status, add reading notes, or record ratings. Users must edit the Org file manually. We need lightweight, context-sensitive edit actions accessible from the agenda view.

Interaction model

Click a book row on the index page → the footer (minibuffer) shows action links tailored to that book's current status. Clicking an action either performs it immediately (status transitions) or shows a lightweight prompt page (add note, mark read with date).

No JavaScript. All actions are plain <a href> links or simple HTML forms.

Actions per status

WANT

  • Mark reading — immediate: sets TODO to READING
  • Add note — prompt page: date + textarea, appends a note

READING

  • Mark read — prompt page: date picker (default today) Rating is deferred (see out of scope).
  • Abandon — immediate: sets TODO to ABANDONED
  • Add note — prompt page: date + textarea

READ

  • Read again — immediate: sets TODO to READING
  • Add note — prompt page: date + textarea

ABANDONED

  • Try again — immediate: sets TODO to READING

Implementation

New Org write functions (spine.el)

spine-set-status (id status &optional date)

Finds the book by :ID: property, changes its TODO keyword to status, and records the state transition in the LOGBOOK drawer (using org-todo). If date is provided (for READ status), sets a :READ_DATE: property.

spine-add-note (id text &optional date)

Finds the book by :ID:, appends - [YYYY-MM-DD] text to the headline body. Date defaults to today if not provided. Follows the same pattern as spine-add-book: find-file-noselect, modify, save, kill-buffer.

spine-set-rating (id rating)

Sets the :RATING: property on the book.

Handler: httpd/edit

Single handler dispatching on action query param:

  • action=status — calls spine-set-status with id and value (the target TODO state). Redirects to /index?id=<id>.
  • action=note — GET shows a prompt page with date + textarea for the book. POST processes: calls spine-add-note with id, text, and optional date. Redirects to /index?id=<id>.
  • action=rating — calls spine-set-rating with id and value. Redirects to /index?id=<id>.
  • Unknown action or missing id — redirect to /index silently.

The prompt page for notes is a minimal HTML page (no Mustache template needed — small enough to inline): shows the book title as context, a date input (default today), a textarea, and a submit button. POST data includes id, action, date, text.

Model: spine-index-model minibuffer extension

When a book is selected (selected-id matches), the model gains a minibuffer field:

("minibuffer" .
  (ht ("actions"
    (list
      (ht ("label" "Mark reading") ("href" "/edit?id=X&action=status&value=READING"))
      (ht ("label" "Add note")     ("href" "/edit?id=X&action=note"))))))

Actions are computed from the selected book's :status property. The exact set follows the table in "Actions per status" above.

Template: index.mustache minibuffer section

The existing minibuffer footer placeholder is replaced with a dynamic version:

{{#minibuffer}}
<footer class="minibuffer">
  <span class="muted">M-x</span>
  <span style="display:flex;gap:.5rem;flex-wrap:wrap">
    {{#actions}}
    <a href="{{href}}" class="pill {{command}}">{{label}}</a>
    {{/actions}}
  </span>
</footer>
{{/minibuffer}}

Styled as pill links consistent with the existing pill classes. M-x prefix keeps the Emacs feel.

Testing

New test file test/spine-edit-test.el:

  • spine-set-status changes TODO state correctly for each transition
  • spine-set-status records LOGBOOK entry
  • spine-add-note appends a note with the correct format
  • spine-add-note defaults to today when no date provided
  • spine-set-rating sets the rating property
  • Model includes minibuffer field when book is selected
  • Model has correct action set per status

Out of scope

  • Editing book properties (author, format, ISBN) — add-book covers creation; editing those can come later if needed
  • Deleting books — add-book is additive; no delete flow yet
  • Rating prompt on the "Mark read" page — deferred; rating can be set separately
  • Inline editing in the detail section — the minibuffer actions are the primary surface for now