OpenLab Apprenticeship 2026

JOSA OpenLab

Week 06: Documentation as Code & Technical Writing

Week 06 of 10
Status Completed
Apprentice
Qutibah Ananzeh
Cohort
OpenLab 2026
Deadline
Jun 20, 2026
// 00

The Standard

The unifying principle: good docs are written from the reader's perspective ("you have a problem, here is what you do"), not the author's ("here is what I built"). For every page, decide which of the four Diátaxis kinds it is and ruthlessly cut anything that belongs to the other three.
Diátaxis, the four kinds of documentation
  • Tutorial. "I want to learn." A teacher walking you through your first success.
  • How-to guide. "I want to solve a specific problem." A recipe for one task.
  • Reference. "I want to look something up." An encyclopedia of the API surface.
  • Explanation. "I want to understand." An essay on the why behind a design.
Google style in 60 seconds
  • Active voice. "The parser reads the file", not "The file is read by the parser".
  • Present tense, second person. "Returns a list." "You can install with pip."
  • Short sentences, sentence-case headings. Two ands or a however means break it up.
  • No "simply", "just", "easy". They are either lies or condescending, the reader is stuck.
Docs as code
  • PR workflow. Doc changes get reviewed like code.
  • CI preview. Every PR builds the site with a preview URL (Cloudflare / Netlify / Vercel Pages).
  • Linting. Style violations fail CI, so a prose linter (Vale) does the nagging, not a human.
  • ADRs. Short, immutable Markdown files in docs/adr/ that record why a decision was made.
Suggested Repositories

mdn/content  ·  github/docs  ·  tldr-pages/tldr  ·  any tool whose README is bad.

// 01

Ship One Real Docs PR

Done
Repo: tldr-pages/tldr (55k+ stars)  ·  PR: #23074  ·  Answers: page request #23039
What I did
I answered an open page request for Apple's container CLI (Linux containers in lightweight VMs on Apple silicon, Apple's Docker Desktop alternative) with a new pages/osx/container.md. The writing was the small part; the real work was verification. Every one of the 8 examples comes from Apple's own command-reference.md for v1.0.0, not from memory, and that caught a real trap: the tool looks like Docker, but its Swift ArgumentParser CLI cannot group short flags, so the idiomatic docker -it must be written -i -t here. The page follows the tldr style guide: at most 8 examples, {{[-d|--detach]}} option placeholders so clients render short or long form, snake_case placeholders, and one user goal per example description. I claimed the issue with a comment before starting so nobody duplicates the work, rebuilt the branch on a freshly synced upstream main, and noted in the PR why the flags are ungrouped.
Verification
tldr-lint + PR checks
$ npx tldr-lint pages/osx/container.md
(no errors)
$ gh pr checks 23074 --repo tldr-pages/tldr
labeler      pass
codespell    pass
license/cla  pass  Contributor License Agreement is signed.
Style checklist
  • Active voice, present tense, one goal per example description.
  • Filename and title match the command exactly; page sits in osx since the tool is macOS-only.
  • No simply / just / easy anywhere in the page.
  • Linted with the same tldr-lint their CI runs, before pushing.
// 02

Set Up a Docs Site (MkDocs Material)

Done
Repo: Ti-03/MacDirStat  ·  PR: #9  ·  Live: ti-03.github.io/MacDirStat/guide
What I did
MacDirStat already had a GitHub Pages landing page (logo, screenshots) served by the legacy Jekyll build from docs/. Rather than replace it, I switched the repo's Pages source to an Actions-based build and wrote a workflow that assembles both outputs into one artifact: the landing page keeps serving from the site root, and the new MkDocs Material site lands at /guide/. The content is genuinely three separate Diátaxis modes, not just three labels: a tutorial (scan your first folder), a how-to guide (read the treemap's colors, change the color scheme), and reference docs for ByteFormatter and TreemapLayout written straight from their source, including the real 10-category color table and the exact arc-angle formula.
Verification
mkdocs build --strict
$ mkdocs build --strict
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: .../site
INFO    -  Documentation built in 0.16 seconds
$ ls _site && ls _site/guide
index.html  logo.png  privacy.html  screenshot1.png ...  guide/
how-to/  reference/  tutorial/  index.html  search/
// 03

Write My First ADR

Done
Repo: Ti-03/MacDirStat  ·  PR: #9  ·  docs/adr/0001-compile-time-guard-for-liquid-glass.md
What I did
I did not invent a decision to document; I had a real one from last week still worth writing down. The Week 5 CI matrix caught a bug where GlassCompat.swift's macOS 26 Liquid Glass calls compiled fine locally (only the macOS 26 SDK was installed) but failed on the macos-15 runner, because #available is a runtime check and does not stop the compiler from needing a symbol that only exists in a newer SDK. The fix was a compile-time #if compiler(>=6.2) guard wrapped around the existing #available check. Writing it as an ADR forced me to name the sharpest Consequence explicitly: any future Liquid Glass call site that copies a plain #available pattern from elsewhere in the codebase will silently reintroduce this exact bug, with no compiler warning to catch it.
Verification
docs/adr/0001-compile-time-guard-for-liquid-glass.md
# 0001. Guard Liquid Glass APIs with a compile-time check, not just #available

## Status
Accepted, 2026-06-29.

## Decision
Wrap every Liquid Glass call site with #if compiler(>=6.2)
around the existing #available(macOS 26, *) check.

## Consequences
+ A future contributor copying a plain #available-only
  pattern elsewhere will reintroduce this bug silently.
+ The macos-15/macos-26 CI matrix is now load-bearing.
// 04

Add Vale to a Repo + CI

Done
Repo: Ti-03/MacDirStat  ·  PR: #10  ·  Tool: Vale with the Microsoft style
What I did
I put Vale on MacDirStat, the same repo that already has the MkDocs site, the ADR, and the Week 5 CI matrix, so the whole week lives in one PR. The config uses the Microsoft style, the same voice the docs were already written in, which meant the fixes were real style tightening rather than fighting the linter: spaced em dashes became colons and commas, "do not" became "don't", and one quote got its period pulled inside. I turned off Vale.Spelling because the reference pages quote real API symbols (ByteFormatter, TreemapLayout), and set MinAlertLevel to error so clear-cut violations fail the build while advisory warnings still print but don't block. The styles are downloaded by vale sync, not committed, so CI stays reproducible from a clean checkout, which I verified by deleting the local styles dir and re-running the exact CI sequence before opening the change.
vale
$ brew install vale
$ vale sync
$ vale guide docs/adr README.md
# prove CI reproducibility from a clean checkout
$ rm -rf .github/styles && vale sync && vale guide docs/adr README.md
Definition of done
  • .vale.ini configured with the Microsoft style; findings fixed. ✓
  • A Vale prose-lint job added to the repo's CI so violations fail the build. ✓
  • Full sequence verified from a clean checkout; submitted as PR #10. ✓
// 05

Soft Skill, Empathy for the Reader

Done
The principle is theory of mind: the reader does not have the context I have. Every word that needs context they lack is a place they bounce.  ·  Outcome: MacDirStat PR #11
What I did
Name the audience: auditing the live guide showed this was already paid for by the week's docs work. Every page opens by saying who it is for: the guide home names macOS users who already have the app, the tutorial names first-time users, the how-to names users who have run a scan, and the reference names people reading the Swift source.

Read as a stranger: this one caught something real. Walking the live guide fresh, with no repo context, I got stuck at step zero: both the guide home and the tutorial's "Before you start" say you need MacDirStat installed, and neither links to where to get it. From inside the project that gap is invisible, because you always arrive from the README or the landing page, which have the download. A stranger landing on /guide/ from a search has no path to the app at all. That is exactly the class of bug this exercise exists to catch: the writer's context (I know where the download is) silently baked into the page. The fix is PR #11, two links: a "Not installed yet?" pointer on the guide home and an install link in the tutorial's prerequisites.

Watch someone use the docs: I did not get a live 20-minute session with another person this week; the fresh-context walkthrough stood in for it. The honest note is that a walkthrough by someone who knows the project is a weaker signal than a real stranger, it caught the dead end but would never catch a confusing sentence I wrote myself. Scheduling a real usability read is the habit to carry forward.
The takeaway
The docs said "you need MacDirStat installed" and stopped, because to the person who wrote them the download location was obvious. Empathy for the reader is not a tone, it is an audit: every sentence that assumes context the reader might not have is a bounce point, and the only reliable way to find them is to arrive at the page the way a reader does.