Scriptorium: textbook solutions
Reference for how I file textbook solutions under the Scriptorium — the right tab on the Fragments page. Mostly for me, since I will forget the schema.
The shape of it
Three nested levels, plus the solution itself:
- Book. Title and author. Has a slug for URLs (not yet exposed as a page).
- Chapter. Belongs to a Book. Has a numeric number and an optional title.
- Section. Belongs to a Chapter. Optional level — some books don't have
sections, just end-of-chapter problems. Has a free-text
label(so I can type "3.2" or "II.A" or whatever the book prints) and an optional title. - Fragment (the solution). Belongs to whichever level is deepest in the book's structure. For a sectioned book, attach to the Section. For a chapter-only book, attach to the Chapter. The Book auto-fills from there.
A single solution Fragment can cover one problem or a span ("Problems 3.2.1–3.2.5" or "End-of-chapter exercises"). I title each Fragment with whatever scope I picked.
The progress marker
Each solution Fragment has a progress_marker field. If set, it renders next
to the title as a muted italic suffix:
Section 3.2 (through 3.2.5)
Use it when I've published a Fragment that I'm still adding problems to. When I finish the section, I clear the field; the title reverts to clean "Section 3.2". Freeform — the field accepts anything that reads sensibly after the title in parens:
- (through 3.2.5)
- (in progress)
- (stopped at the harder ones)
- (only end-of-chapter problems for now)
The title stays canonical; the suffix is metadata.
Admin workflow
Everything lives at /cellar/ (the renamed Django admin).
- Add a Book. Title, author, slug. Save.
- In the Book change page, add Chapters via the inline. Number and optional title per row. Save.
- In the Chapter change page, add Sections via the inline if the book
uses them. Set the
orderinteger to control display order; thelabelis what renders to the page. - Add a Fragment. In the Solution placement fieldset, pick the deepest unit (Section if sectioned, otherwise Chapter). The Fragment's save method derives chapter from section and book from chapter, so I don't have to pick all three. The clean method rejects inconsistent picks (a Section from a different Chapter).
- Optionally fill
progress_markerif I'm publishing mid-work. - Publish or draft by setting (or leaving blank)
published_at. Drafts are visible to me at the fragment URL but hidden from the public.
Resuming a draft
The "I'll never finish a section in one sitting" workflow:
- First sitting: write Problems 3.2.1 and 3.2.2 in the body. Set
progress_marker = "through 3.2.2". Setpublished_at = now(). Publish. - Second sitting: open the Fragment in
/cellar/, append Problem 3.2.3 to the body (markdown picks up where I left off). Updateprogress_marker = "through 3.2.3". Save. The live page updates. - Last sitting: append the final problem. Clear
progress_marker. Save. The page now reads "Section 3.2" without the suffix — done.
Alternatively, hold publication until done: leave published_at blank
while drafting, set it when I'm ready for the world to see the half-finished
state. Either pattern works. Public is the gate; the suffix is the WIP
indicator.
Where the solutions render
/fragments/→ Solutions tab. Full tree: Book → Chapter → (Section →) Fragments. Books sorted by most-recent-activity. Inside each book, chapters by number; sections byorder./fragments/<slug>/. Individual Fragment detail page. Same as any other Fragment./scriptorium/. The chronological year-archive (unchanged by this feature). Solutions show alongside notes there.- Tag pages. If I tagged the solution, it appears under those tags.
/fragments/feed/. Atom feed. Solutions and notes share the same feed.
Solutions are filtered OUT of the Notes tab on /fragments/. Notes are
exactly fragments with no book attached.
Practical notes
- Book without sections. Set
section = Noneon the Fragment; leave the Section inline on the Chapter empty. Solutions render directly under the chapter heading. - A "miscellany" solution that doesn't fit any chapter. Attach to the Book only, leave chapter and section null. Renders as an "orphan" at the book level — works but rare.
- Renaming a chapter or section. Edit it in
/cellar/. The solutions attached to it move with it; titles and links stay stable because the Fragment slug is independent. - Reordering sections. Edit each Section's
orderinteger. Lower numbers float up within a chapter.
What not to do
- Don't put problem numbers in the Fragment title. Use the title for
scope ("Section 3.2", "Problems 3.2.1–3.2.5") and put problem-by-problem
detail inside the body with
## Problem 3.2.1subheadings. The body is markdown — full math, code, references all work. - Don't write the same problem twice. If I'm extending a draft, append to the existing Fragment, don't create a new one. The progress marker exists so I can publish-then-extend.
- Don't forget to clear
progress_markerwhen done. It's the visual signal of WIP; leaving it stale gives the wrong impression.
Drafted by Claude (Anthropic) at my request, as a working reference for the Scriptorium feature added on 2026-05-19. Edits and additions are my own.
Welcome, or: notes on a feral mathematician
Why this blog exists, where the name comes from, and what to expect.
Markdown for this blog
A cheatsheet for me, since I will forget which underscore does what and
which fence wants a language tag. Most of this is plain Markdown plus the
extras from pymdown-extensions listed in blog/templatetags/markdown_extras.py.
Inline and display math
Inline with single dollars, display with doubles. Underscores inside math do not trigger italic.
$\mathfrak{sl}_2 = \operatorname{span}\{E, F, H\}$
$$[H, E] = 2E, \quad [H, F] = -2F, \quad [E, F] = H$$
Renders as \(\mathfrak{sl}_2 = \operatorname{span}\{E, F, H\}\), then
AMS environments live inside $$ ... $$:
$$
\begin{align}
\Delta(E) &= E \otimes 1 + K \otimes E \\
\Delta(F) &= F \otimes K^{-1} + 1 \otimes F
\end{align}
$$
cases, pmatrix, bmatrix, array, and so on all work the same way.
Equation tags are AMS-style (config in base.html).
Headings
## H2 and ### H3 for sections inside the body. The post title already
occupies # H1, so do not use that level.
Lists
- one item
- another
- sub-item by indent
1. first
2. second
- one item
- another
-
sub-item by indent
-
first
- second
Code blocks
Fence with a language tag and Pygments picks it up:
```julia
function bracket(L, A)
sum(s -> A^(a(s) - b(s)) * (-A^2 - A^-2)^(loops(s) - 1), states(L))
end
```
function bracket(L, A)
sum(s -> A^(a(s) - b(s)) * (-A^2 - A^-2)^(loops(s) - 1), states(L))
end
Inline code with single backticks: using LinearAlgebra.
Tables
| Generator | Action |
|-----------|-----------------------------------------|
| $E$ | raises weight by two |
| $F$ | lowers weight by two |
| $H$ | diagonal, eigenvalues are the weights |
| Generator | Action |
|---|---|
| \(E\) | raises weight by two |
| \(F\) | lowers weight by two |
| \(H\) | diagonal, eigenvalues are the weights |
Blockquotes
The miracle of the appropriateness of the language of mathematics for the formulation of the laws of physics is a wonderful gift which we neither understand nor deserve.
(Wigner, The Unreasonable Effectiveness of Mathematics in the Natural Sciences)
Footnotes
Drop [^name] inline, define at the bottom:
The bracket polynomial[^kauffman] is a state sum over crossings.
[^kauffman]: Kauffman, *On Knots*, Princeton, 1987.
Emphasis
*italic*, **bold**, ~~strikethrough~~ give italic, bold, strikethrough.
Links
[Anathem](https://www.nealstephenson.com/anathem.html) becomes
Anathem. Bare URLs are
linkified automatically.
Embedding a Pluto notebook
Raw HTML is allowed in the body:
<iframe src="/static/blog/notebooks/<slug>.html" class="notebook-embed" loading="lazy"></iframe>
The .notebook-embed class is theme-aware. Export with
bin/export-to-blog from ~/Projects/julia-math/.
Smart symbols
-> becomes →, <- becomes ←, (c) becomes ©, +/- becomes ±. Inside
math mode the proper TeX commands (\to, \copyright, \pm) are more
precise; the smart-symbol pass mostly helps in prose.
What not to do
- No
$math$in titles. Titles flow into<title>and feed metadata, neither of which run MathJax. - No AMS environments outside
$$ ... $$. They need math mode. - No heredocs when seeding posts from bash. Bash eats backslashes and
\fracbecomesrac. Drop the script intoscripts/and runpython manage.py shell < scripts/foo.py. - No raw HTML for math. The dollar delimiters are enough and MathJax catches them at render time.
This guide was drafted by Claude (Anthropic) at my request, as a working example of a Fragment and a permanent reference for myself. Edits and additions are my own as I go.