The reader-facing version of this is /submit/ on the site, generated from
pages-src/submit.md. That page explains what the series publishes and what
happens after a pull request; this file is the mechanics for someone already
in the repository. Keep them consistent — if the process changes, both move.
Give it its own working tree. Writing and building are the same repository
doing two things at once, and they collide over generated files — myst.yml
holds the toc, and a production build run in another terminal takes notes at
draft and review out of the toc that myst start is watching. The dev server
then reports File is not in project for the file you have open. Nothing is
lost; it just stops updating, which is worse, because it looks like your
editor.
pixi run worktree create particle-level-sets # branch note/particle-level-sets
cd ../underworld-technical-notes-worktrees/particle-level-sets
pixi install # its own environment, once
pixi run new --slug particle-level-sets --title "…" --author louis
pixi run start # localhost:3000, hot reloadThree cycles, three tools, and they do not interfere:
| Writing | pixi run start |
instant, shows drafts |
| Review | push the branch → link on the pull request | ~3 minutes |
| Publishing | merge to main |
the live site |
pixi run worktree list shows what is in flight; remove takes the working
copy away and leaves the branch, since those are different decisions.
Picking up a note that already exists — one somebody started on the web, or that you left a fortnight ago — is the same command. It adopts the branch rather than creating one, and tells you which note is on it:
pixi run worktree create binder-note # adopts note/binder-note
cd ../underworld-technical-notes-worktrees/binder-note
git pull
pixi install # first time only
pixi run startEditing on GitHub is fine for a typo and no worse than doing it locally. It is a poor way to fix formatting, because you cannot see the built page — and formatting is exactly what the local server is for.
Looking for something to write? WRITING-PLAN.md holds the planned notes,
what each is meant to explain, and which of them are grouped into a candidate
paper. Notes are written as micro-preprints: two or three related ones become
the basis of a peer-reviewed modelling paper, so a note that will feed a paper
should carry its own evidence — figures generated by a script in the note's
examples/, not screenshots of a run nobody can repeat.
pixi run new --slug my-note-slug --title "My note" --author louisThat creates articles/<slug>/ from templates/article-template, allocates an
article ID that cannot collide with an existing note or with one the legacy
backfill will later claim, and fills in your details from authors.yml. Add the
file to the toc in myst.yml, then:
pixi run build # HTML site + archival PDF
pixi run test # metadata validation + the DOI URL test
pixi run myst startThis is the correction that gets made most often, and it is worth knowing why. A heading is read as a label for what follows — a thing to skim, or to skip. It is not read as the opening words of the paragraph under it. So a paragraph that continues from its heading arrives, for the reader, with its first sentence missing.
The test is to cover the heading and read the first sentence alone. If it leans on the heading for its subject, for a pronoun's referent, or for the verb it never got, rewrite it.
### The leak, measured
An annulus, no slip on the inner radius, the treatment under test on the
outer, driven by a degree-four density anomaly.Covered up, that is a list of parts with nothing to attach them to. It reads as though the heading were the start of the sentence, which is how it was written and not how it is read.
### The leak, measured
The leak is measured on an annulus, with no slip on the inner radius and the
treatment under test on the outer, driven by a degree-four density anomaly.Every paragraph introduces itself. The cost is a few repeated words; the benefit is that any section can be entered at any point, which is how a technical note is actually read.
The same section, twice:
## The container: just what we need and no less !
## The launcher: an almost empty repository## The container image
## The launcher repositoryA heading is a label on a drawer. It tells a reader what is inside so they can open it or walk past. The first pair instead makes a claim the section then has to earn, and holds back the point so it can be revealed a paragraph later. Read down a contents list of them and every entry sounds like it is about to surprise you, which is tiring at ten headings and says nothing about where to find anything.
Colons are not banned — UWTN 2026-014: Setting Up Full Multigrid is a label.
The test is whether the words after the colon name something or assert
something. And an exclamation mark in a heading is always the wrong instinct.
Two habits creep in, and both cost a reader time.
Announcing the writing. Written plainly, the link says…; three limits, stated plainly…; the honest framing is… — the prose is either plain or it is not, and saying so does not make it so. Delete the frame and keep the sentence.
Withholding, then revealing. …and then does the thing that matters:; the word to notice is frozen; the consequences are the useful part:; the interesting parts are not entirely obvious. Each of these tells the reader that something important is coming instead of just saying it. Every one is deletable with no loss: and then does the thing that matters: is and then dispatches to the launcher:.
The related tic is not-X-but-Y — it is not a container for a Python package; it ships the means of production, not just the product. One is a useful correction of an expectation a reader really holds. Five in a note is a rhythm, and it reads as though the argument is with a sceptic who is not in the room.
None of this is an argument for flat prose. A dry aside is welcome — why writing one by hand is a poor use of an afternoon — and so is a personal remark, because this audience is colleagues, not customers. The distinction is that those comment on the world. What to cut is commentary on the writing, and instructions about what the reader ought to find interesting.
- "I" reports what the author did and what they found. Two authors make that "we".
- "we" is the author and the reader, together, working through something: we can now measure the leak directly.
- "you" addresses the reader directly. Right where the note is telling someone how to do something; out of place where it is reporting a result.
The two senses of "we" collide in a co-authored note, so if a sentence could be read either way, name who did the work.
Do not strip second person out of instructions. An earlier version of this section said to use "you" sparingly, full stop, and that was wrong: applied to a note that is half how-to, it took the second person down to 2.5 per thousand words where the 2020 cloud note — the register several of these notes are aiming at — sits at 5.6. Across the corpus the notes run 0–8 per thousand and the install guides reach 25–62, correctly. A note that is partly instruction belongs between those, and the sentence that reads naturally with "you" should keep it.
pixi run check-style reports the habits above that a regular expression can
find — it names the convention, quotes the line, and leaves the judgement to
the author. Second person it reports as a density rather than a limit, for the
reason just given, and it is not part of pixi run test, because several of
its checks are densities whose right value depends on what the document is.
A note's examples/ scripts are read, not only run, so they are held to the same
standard as the prose. Underworld3's own guides are the authority and should not
be restated here — the
Style Charter
and the
notebook style guide
— but four of their clauses decide most of what a reviewer will ask for.
Write the plain version. The Charter's founding rule is that any working geodynamicist must be able to read the code and understand it, and that it applies to the scripts and notebooks as much as to the library. A clever construction that saves ten lines and costs the reader a detour has made the script worse.
Use Underworld's own machinery rather than hand-rolled equivalents.
uw.Params for options — notebook-editable defaults, units aware, with
-uw_name value overrides — not argparse and not a config dict at the top of
the file. uw.print and uw.timing rather than bare prints and stopwatches.
A reader should never meet an MPI call in a note's example.
Name the parameters, once, at the top. A number a reader has to hunt for in the middle of a loop is a number they cannot change with any confidence. This is also what makes a figure reproducible: the script that made it carries the settings that made it.
Comments carry intent, not mechanics. Why this term is in the weak form, why
this tolerance, why this ordering — not # loop over cells. Delete
commented-out code and debugging scaffolding before the note is published; git
remembers, and the reader should not have to.
The tone matches too: direct, unshowy, and not congratulatory. We report how something works, not how hard it was to make work.
-
Plain declarative prose. No antithesis pairs, no aphoristic closing line. See Who is speaking and Say the thing below.
-
A published note carries results, not the route to them. False steps, bugs found on the way and issue numbers belong in the tracker. What survives is the method and the measurement.
-
A note stands on what is published. Do not motivate it with a method of ours that has not been written up yet, and do not lean on a note that is still to come: a reader can follow neither. Where a machinery of our own is the reason the question matters — a particular free-surface scheme, say — that is the reason to write that note, not to reference it from this one. Say the general thing the reader can check, and leave the specific one to its own note.
-
Every figure and table ships the script that made it, in the note's
examples/. A number a reader cannot regenerate is an assertion. -
Alt text describes what the image shows, including the numbers. It is read by people who never see the figure, and by anyone reading the markdown.
-
Citations are pinned in the note's
references.biband cited in one form,[@Key]. Letting the build fetch citation data means a page can publish with a broken reference on the day doi.org is slow — and a deposited PDF cannot be repaired afterwards. -
Say which quantity, on which mesh, against what. "Converges" and "agrees well" are not measurements.
-
Write display maths as a
mathdirective, not as$$. Both build, but the fenced form survives an editor that is not a MyST editor — Typora, which several of these notes are written in, rewrites a$$ ... $$ (label)block and moves the label onto a line of its own, which silently breaks it. A fence is left alone.```{math} :label: eq-free-slip \mathbf{u}\cdot\hat{\mathbf{n}} = 0 ```With
$$, two things are then load-bearing and neither is reported by the build. The label belongs on the CLOSING delimiter —$$ (eq-free-slip)— and on its own line it renders as literal text while every{eq}reference to it fails the Typst build. And a$$block that opens on the line straight after a paragraph is a lazy continuation: fine for one-line arithmetic, but a line inside it beginning-,*,>or#is claimed by markdown, the maths never closes, and the page publishes raw LaTeX with half an equation in a bullet.pixi run test-unitguards both.
- The article file must be named
<slug>.md. MyST takes a page's URL from the filename, not the path, so this is what publishes the note at/<slug>/. Renaming it toindex.mdchanges the URL.pixi run validaterejects that. - Never change the slug of a published note. Fifty legacy notes carry
Crossref DOIs that resolve to
/<slug>/and cannot be re-pointed;pixi run test-doisfails the build if any would 404. - Article IDs are permanent. Once an ID appears in a deposited PDF it must not move, which is why they are allocated across the whole corpus rather than per batch.
- State the intent for images. A numbered figure, a badge and an inline
graphic are three different things; see the template and
templates/pdf/README.mdfor the two mystmd limitations worth knowing.
Add them to authors.yml with their ORCID. ORCIDs are left null rather than
guessed — attaching a wrong one attributes someone's work to a stranger — and
pixi run validate warns about any that are missing on a DOI-bearing article.