How I Over-Engineered My Book

Aug 18, 2026 01:15 AM - 2 hours ago 1

My book has a linter that yells astatine maine for hyphenating “open source.”1 It runs ~5,500 automated checks, rebuilds 5 formats connected each git push, and fails the build if I truthful overmuch arsenic connote I still activity astatine a occupation I left. For a book. That 1 personification wrote.

I didn’t group retired to do this. Most group commencement a penning task by firing up Word aliases Google Docs, and I started down that aforesaid path. I moreover tried immoderate purpose-built authoring tools, but each instrumentality felt inferior to the ones I utilized arsenic a developer each day. I did “the only reasonable” point and threw each of them out, penning the full book connected Git, Markdown, and a CI build pipeline. If you’ve publication really I over-engineered my location network — twice — none of this will astonishment you.

I’ve been making websites for decades, truthful the leap was short: the aforesaid devices that build websites could build books, nary last-minute magic-trick uncover required to abracadabra a modular Word doc into a full-blown book. There were missteps,2 but successful the end, I would not person written Open and Async immoderate different way. Here’s how:

Content#

Naturally, the contented itself lived arsenic Markdown files successful a Git repository. After all, that’s wherever I walk astir of my day. I utilized VS Code, pinch a fistful of prose extensions (listed below). Each section was its ain Markdown file, and a azygous index.yml record defined the order, making it easy to re-order chapters aliases adhd caller ones.

Practically, I wrote astir of this book connected an iPad — Codespaces successful a browser tab, a Bluetooth keyboard, often nights and weekends while distant from my desk — and the Git repository kept everything successful sync nary matter wherever I opened it. I could attraction connected the words, and a bad thought was 1 git revert distant from gone.

Not to mention, I had real-time feedback connected my penning correct successful my IDE from the various prose linters, conscionable arsenic I would person real-time feedback connected my codification from ESLint aliases Prettier.

Testing#

With contented arsenic code, the adjacent logical step — and the constituent wherever “reasonable” softly near the building — was to group up automated tests. Testing prose the measurement you trial code is thing I’d based on for years; this was maine taking it to an absurd extreme. I did that 2 ways: real-time, and connected push (CI).

Real-time#

Locally, arsenic I typed, I ran respective VS Code extensions each giving maine real-time feedback. Specifically:

  • Markdownlint — Markdown syntax and formatting consistency
  • Harper3 — grammar and connection choice, wholly on-device
  • LanguageTool — grammar, punctuation, and style4
  • Vale — my ain house-style rules and banned terms
  • Alex — insensitive aliases exclusionary phrasing
  • Write-good — weak prose: passive voice, weasel words, clichés

All six besides ran successful CI (Alex and Write-good folded into Vale there; more connected that below). Together, they layered hundreds of curated style rules complete a afloat grammar engine — all of it underlining my mistakes successful existent time, the measurement a reddish squiggle flags a type error.

On each push#

In summation to moving those unfastened root linters successful CI (some blocking), I built a civilization trial suite of my own: a standalone Node book of contented validators, a Vitest suite, and Playwright specs. The validators are the nosy part. Each is simply a fewer lines that publication the Markdown and push an correction pinch a file-and-line pointer. My favorite: I don’t activity astatine GitHub anymore, truthful immoderate condemnation claiming I still do fails the build.

// My clip astatine GitHub has to publication arsenic past tense — present-tense

// employment claims astir it neglect the build.

function validateGitHubTense(files) {

const patterns = [

// "is/are ... astatine GitHub" — a current-employment claim

/\b(is|are)\b[^.!?\n]{1,80}?\bat GitHub\b/i,

// "works/leads/runs astatine GitHub" — current-employment activity

/\b(works?|leads?|runs?|manages?|directs?)\s+(at|for)\s+GitHub\b/i,

];

return flagLinesMatching(files, patterns);

}

That validator exists because I made the correction once — which is the full pattern. The first clip an correction sewage past me, I didn’t conscionable hole that 1 sentence; I wrote a norm truthful I’d ne'er person to drawback it by oculus again. It’s cattle, not pets for prose: don’t hand-nurse each chapter, govern the full herd pinch policy. A correction caught erstwhile becomes a cheque that sweeps each section and fails the build if it ever wanders back. That’s 1 of astir thirty. Others I’m proud of:

  • validateOpenSourceHyphenation — “open source” is a noun, not a verb, and ne'er hyphenated.
  • validateHypotheticalHooks — formulaic AI-tell openers (“Picture this…”, “Imagine…”, “Consider a…”) astatine the commencement of a paragraph.
  • validateSentenceStarters — three-plus sentences successful a statement opening pinch the aforesaid word.
  • validateNoBareUrlLinkText — no nexus whose visible matter is conscionable the earthy URL.
  • validateCalloutBalance — the book speaks to managers and individual contributors, truthful a “For managers” callout has to person a “For ICs” counterpart nearby.
  • validateCrossReferences — every [text](#anchor) cross-reference resolves to a existent heading.

…plus a mates twelve much for mini caps, em-dashes, doubled words, en-dash ranges, TL;DR length, and each different tic I could name.5

One of these caught me. validateHypotheticalHooks flagged the opening of a paragraph I was definite I’d written myself — and I had. But reference it backmost cold, it did sound ghost-authored; I’d absorbed the cadence from reference excessively overmuch generated matter and produced a fluent imitation of nothing. A linter can’t show bully prose from bad. What it tin emblem are the patterns you scope for erstwhile you’ve stopped thinking — which is precisely the point you can’t spot successful your ain draft. Same logic eslint earns its keep: it can’t show bully codification from bad either, but it catches the autopilot mistakes your ain oculus skates correct over.

All successful all, the CI suite ran ~70 trial files pinch 2,204 trial cases and ~3,900 expect() assertions — plus different ~1,600 per-chapter structural checks from the validators above.

Audits#

The linters caught mistakes, but they couldn’t show maine whether the book repeated itself aliases whether a section was immoderate good. For that I built a 2nd furniture of tooling: audits that judge the writing, not conscionable cheque it. One point they ne'er did, though, was constitute it. Every connection is mine; these devices are readers of past resort — catching what I’d stopped being capable to see.

Duplication detection#

After reference the book complete and over, I was convinced I’d repeated the aforesaid thought crossed chapters. I wanted proof, not a hunch — so I built 3 layers of plagiarism detection, each catching what the 1 earlier it misses:

  • jscpd — token-level copy-paste detection. Catches longer verbatim blocks I’d pasted betwixt chapters, but thing subtler.6
  • n-gram — tokenizes each section successful index.yml, strips Markdown/Pandoc syntax, builds connection n-grams (phrases of n words), and flags phrases appearing successful much than 1 section (plus a “most-repeated banal wording” ranking). Two modes: cross-chapter (default --n) and intra-chapter (--scope=intra --n=8) for a section repeating itself.
  • semantic — the 1 the different 2 can’t do: the aforesaid point restated successful different words. An on-demand LLM audit, designed truthful it ne'er feeds the full book to a model — three passes, each complete mini units:
    • intra — one telephone per chapter: “where does this section restate itself?”
    • cross — a azygous telephone complete each chapter’s TL;DR, producing a representation of conceptually overlapping chapters. A whole-book scan for the costs of 1 call.
    • arguments — extract each chapter’s load-bearing claims 1 telephone astatine a time, past cluster the aforesaid statement crossed each chapters successful 1 last call. Catches arguments made successful assemblage prose that transverse misses.

Was I really repeating myself? By this last walk the 2 mechanical layers came up clean — but they’d earned it: jscpd and the n-gram scan had already caught the copy-paste and recycled phrasing (a doubled motif here, a reused TL;DR building there), and I’d fixed each.

What neither could spot was the subtler kind — nothing was duplicated word-for-word anymore, conscionable the aforesaid point successful different words. The semantic walk caught that, and it was right: I’d made the aforesaid argument, that moving agency habits online isn’t the aforesaid arsenic moving remote-first, successful five abstracted chapters, connected apical of 166 smaller self-restatements scattered crossed 51 chapters. I’d paraphrased myself excessively good for thing cheaper than an LLM to drawback me. (share this quote)

My hunch was correct; I’d conscionable needed 3 escalating devices to beryllium what re-reading my ain book to blurry-eyed exhaustion couldn’t.

Content audits#

Beyond duplication, a 2nd group of devices graded the prose itself — split by really they judge. Some are probabilistic (an LLM sounds the section and forms an opinion; tally it doubly and the findings tin shift), and immoderate are deterministic (rules and arithmetic — same input, aforesaid output, each time).

Probabilistic (LLM) audits#

The Claims lens paid for itself early. It stopped connected a condemnation claiming GitHub’s monthly all-hands “dedicated astir half of each convention to unrecorded Q&A” — a number I was definite of and had wrong; it was person to a third, and the stock moved astir complete the years. No linter flags that: it’s clean, assured prose that happens to beryllium false. Only a scholar asking “is this really true?” catches it, and I’d person shipped it otherwise.

Claims is 1 of 20 single-purpose lenses successful a “prose audits” test — a per-chapter LLM auditor wherever each lens asks 1 constrictive mobility truthful the exemplary can’t hand-wave a vague “looks good.” --lens=all runs each lens; --models/--rounds adhd a deduplicated multi-model and self-consistency panel, truthful a uncovering has to past much than 1 exemplary (or much than 1 run) to count. A sampling of the rest:7

LensWhat it catches
AI-tellsPhrasing that sounds arsenic machine-generated alternatively than my voice
HookWhether the opening earns its spot aliases is throat-clearing
LegalLegal aliases reputational consequence (naming names, unverified claims)
DatedPerishable references that will property severely (“recently,” “this year”)
GlobalIdioms and taste assumptions that travel up non-US readers
Dual-audienceWhether a section serves managers and individual contributors
PromiseWhether the section delivers connected the book’s halfway promise

Separately, I besides had a traits study test, which scored each section connected persuasion and engagement traits, catching prose that was technically cleanable but level truthful I could springiness it different (human) pass.

Deterministic audits#

I ran these aft a information of editing, to spot whether the book was improving arsenic a reference experience: chapter- and paragraph-length distributions, whole-book reference time, a difficult EPUB size fund (Kindle penalizes oversized files connected delivery), a book-wide consistency checker, and a stats dashboard whose --check mode fails the build unless each “attention item” — a section missing a TL;DR, an unbalanced callout — sits astatine zero.8

Together, these turned “is the book really getting better?” from a gut emotion into a number I could watch move betwixt drafts.

 summary cards reference 99,651 full words, 399 minutes reference time, 72 chapters, 1,384 mean section words, 103 head callouts, 102 IC callouts, 123 pro tips, and 62 objections, pinch a greenish "No issues recovered — each contented chapters look good!" all-clear astatine the bottom.The penning dashboard for Open and Async: summary cards reference 99,651 full words, 399 minutes reference time, 72 chapters, 1,384 mean section words, 103 head callouts, 102 IC callouts, 123 pro tips, and 62 objections, pinch a greenish "No issues recovered — each contented chapters look good!" all-clear astatine the bottom.

Design#

I americium far from a designer, and I’d ne'er published an ebook before — I had nary thought really they worked beyond reference galore of them. Two aha moments changed the measurement I thought astir publishing:

  • An ebook is simply a website successful a trench coat (share this quote) — ebooks are conscionable HTML and CSS, albeit a very stripped-down version.9 If you tin make a website, you tin make an ebook.
  • A people book tin beryllium 1 too, pinch capable effort — CSS natively has powerful @media people and @page rules, including near and correct page styling, title pages, page numbers, and more.

For the interior design, I reached for Tailwind CSS — not because it’s built for books (it isn’t), but because it’s what I already usage each day. @tailwindcss/typography gave maine a typographic baseline to commencement from alternatively of a blank page.

One note: I purposefully hired a human designer for the cover. For a book astir being authentic, the first belief had to beryllium authentic.10

The invisible leak#

Styling each format from 1 stylesheet has a nonaccomplishment mode: CSS meant for 1 format bleeding into another. To support my e-reader tweaks distant from the paperback, I scoped each of them to @media not screen. But WeasyPrint — the HTML/CSS-to-PDF motor that draws the paperback, more connected it below — renders the people PDF pinch media type print, and people is “not screen,” precisely arsenic the spec says. So 2 of those e-reader rules matched anyhow and softly bled into the book: a tighter line-height connected callout paragraphs, and a box-decoration-break alteration that dropped the repeated padding connected immoderate callout that divided crossed a page.

Neither was visible. Nothing looked broken. But each shaved a sliver of vertical abstraction disconnected each callout, and the book slow deflated from 576 printed pages to 567. I only recovered retired because the people PDF is pinned to precisely 576 pages11 and the build went red — a page-count gross written to protect the screen spine, catching a CSS bug it was ne'er designed for. Two formats from 1 stylesheet is simply a gift, correct up until the cascade forgets which format it’s in. (share this quote) The hole re-pins the original values successful a print-only block, large pinch !important truthful the leak can’t win.

Tests#

The creation and layout sewage a trial suite arsenic well — driven by Playwright against the built HTML, truthful it checks what really renders, not what I hoped the CSS did. Two categories:

Accessibility (axe-core)#

The axe-core motor runs complete the rendered book successful both ray and acheronian mode against WCAG 2.1 AA — no captious aliases superior violations, AA colour opposition successful either scheme, alt matter connected each image, logical heading order, discernible nexus matter (no bare “click here”), and a declared lang property truthful surface readers prime the correct pronunciation. It’s the test:a11y gate, enforced successful CI arsenic validate-playwright. Accessibility earned much than a subsection here — it has its ain accessibility statement, and a dedicated heavy dive is coming.

Visual & layout regression (Playwright)#

These asseverate that the existent computed styles lucifer the creation intent — the specifications that break softly and ne'er show up successful a diff. A typical few: the title page renders centered pinch a lighter-weight subtitle; the array of contents is simply a existent nav pinch the doc-toc domiciled and moving links; each callout type carries its ain unsocial left-border colour and auto-generated explanation prefix; and mini caps get existent font-variant: small-caps, not conscionable a people name.12

None of this is glamorous. It’s precisely the benignant of point that breaks silently successful a Friday CSS refactor and doesn’t aboveground until a scholar emails you.

Building#

We’ve sewage cleanable Markdown, and a trial suite that ensures the contented is clean, but we still request to get it into a format that tin beryllium published (EPUB, Kindle, paperback successful 2 flavors, and web). Core to that civilization build pipeline was Pandoc, a cosmopolitan archive converter that tin publication Markdown and spit retired conscionable astir thing else. I utilized Pandoc arsenic the engine, but Pandoc unsocial gets you a generic document — turning that into 5 store-ready formats took a heap of civilization tooling:

A reproducible toolchain#

Pandoc is only the engine. The afloat build besides needs WeasyPrint to tie the PDF, Ghostscript to person it, and a heap of Noto fonts for afloat Unicode coverage — a gnarly stack of autochthonal limitations to instal by hand. The full point truthful lives successful a Docker image and a dev container, pinned to an nonstop renderer type (a item that matters much than you’d think — see the page-count gross below). That instrumentality is besides why I could draught the book from an iPad: the dense toolchain ran successful Codespaces, not connected my lap.

Pre-processing (before Pandoc sees the text)#

Everything starts connected a throwaway transcript of the root tree, truthful these transforms ne'er touch the existent chapters. A mates of scripts massage that transcript earlier Pandoc runs — stamping each build pinch its perpetrate SHA, turning inline links into numbered footnotes for people (a hyperlink is useless connected paper; a footnote pinch the afloat URL isn’t), and reshuffling the chapters per format truthful the EPUB gets shareable quote links while people and Kindle get a QR stock page instead.13

CSS pipeline#

One Tailwind stylesheet (src/style.css) compiles done PostCSS to dist/style.css, truthful screen, print, and EPUB each commencement from the aforesaid root of truth. Each format past takes a different slice: strip-page-rules.js derives a cut-down stylesheet for EPUB, stripping the CSS Paged-Media features (@page, target-counter(), oklch(), civilization properties) that Kindle and EPUBCheck choke on.

Lua filters (the absorbing part)#

This is the portion I didn’t expect to love. Pandoc parses everything into an absurd syntax character (AST) and lets you rewrite that character pinch mini Lua scripts earlier it renders — so format-specific tweaks unrecorded successful code, not smeared done the prose. Deleting a node, for instance, is conscionable returning an quiet table:

-- strip-comments.lua: driblet editorial HTML comments truthful my notes-to-self

-- ne'er vessel wrong the published .xhtml. Returning {} removes the node.

function RawBlock(el)

if is_html_comment(el.format, el.text) then

return {}

end

end

The remainder are variations connected that idea:

  • add-div-titles.lua — injects the callout labels (“TL;DR: ”, ”💡 Pro-Tip: ”, ”👔 For managers: ”) and DPUB-ARIA accessibility roles, truthful those labels aren’t hardcoded successful each section and tin disagree per format.
  • Emoji, handled 3 ways — color emoji render good connected screen, but strip-emoji-kindle.lua swaps them for Kindle-safe glyphs (e-ink has nary emoji font) while body-emoji-images.lua turns them into inline Twemoji images for the people PDF.
  • tagline-share-links.lua — appends a “share this idea” permalink aft each of the book’s bumper-sticker lines successful the EPUB.

The acheronian box#

Turning emoji into images solved the missing-font problem and created a subtler one. Twemoji’s PNGs are transparent, but the RGB underneath the transparent pixels is acheronian slate — invisible if a renderer honors the alpha channel, an disfigured charcoal container if it doesn’t. And whether a renderer honors alpha turned retired to dangle wholly connected wherever the book sewage opened.

On Kindle, my first hole baked the callout’s inheritance colour into each PNG and dropped the alpha outright. It looked cleanable connected a light-mode Paperwhite and unspeakable connected Kindle for iOS, which does grant transparency and doesn’t overgarment the callout tint down the image — so each emoji sewage a colored rectangle alternatively of a acheronian one. I’d traded 1 container for another. What shipped keeps the alpha intact but rewrites the RGB of each afloat transparent pixel to white: renderers that grant alpha get cleanable transparency; the ones that flatten it get white, which vanishes connected a achromatic page.

The people PDF needed the opposite fix. Ghostscript converts the paperback to PDF/X-1a pinch -dNOTRANSPARENCY — required to support the matter arsenic selectable vectors alternatively of a 300-DPI bitmap — and that emblem always drops the alpha. So there, transparency is the enemy: each emoji is flattened onto the nonstop colour it sits connected (the callout’s gray, aliases achromatic for assemblage text) pinch nary alpha astatine all, truthful there’s thing to driblet and nary container to reveal. The aforesaid bug needed other fixes — one runtime mightiness driblet the alpha, the different was guaranteed to. (share this quote) A Python book bakes some sets astatine build time.

It’s the astir mean bug successful the world — mine conscionable happened to beryllium successful a book.14

Rendering & post-processing per format#

With the character transformed, each format renders down its ain path — and the paperback takes the longest road. HTML and the PDF some render done Pandoc, but the PDF is drawn by WeasyPrint, an HTML/CSS-to-PDF engine — so I typeset the full book pinch the aforesaid container exemplary I’d usage for a web page. The EPUB goes a different way: Pandoc embeds WOFF2 font subsets, past postprocess-epub.js repackages it to enactment valid and small. And the paperback keeps going aft everyone other has stopped, retired to Ghostscript to go PDF/X-1a:2001 — CMYK color, an embedded USWebCoatedSWOP ICC profile, flattened transparency — the archaic people modular IngramSpark (the print-on-demand distributor) won’t unrecorded without.

That aforesaid 576-page gross earns its support present too. check-pdf-page-count.js pins the count and fails the build the infinitesimal the paperback drifts disconnected 576 pages — cheap security against a old page count shipping arsenic a wrongly-sized screen spine.

That’s 5 publishable files retired of 1 Markdown source15 — which raises the evident question: really do I cognize immoderate of them are really correct?

Testing the build#

The prose linters support the words honest; a larger portion of that Vitest suite keeps the build honest. A Pandoc upgrade aliases a stray statement of CSS tin silently break a format, and I wouldn’t find retired until a reader’s Kindle rendered the incorrect font. The tests cheque the machinery: that each toggle shape does what it claims, and — the biggest cluster by far — that typography hasn’t softly drifted crossed mini caps, array borders, people contrast, acheronian mode, and the e-ink emoji fallback. Each is simply a trial because each is simply a measurement I’ve watched a build look good and render wrong.

But portion tests only beryllium my codification is right, not that the output is valid — so each artifact besides runs done the aforesaid validators the stores themselves use, and a rejection happens connected my laptop, not connected upload day. Every EPUB goes done EPUBCheck, the validator each shop runs connected upload, and Ace by DAISY, an accessibility audit built specifically for ebooks; the built HTML gets crawled by lychee for nexus rot and tally done an HTML validator earlier malformed markup tin go a malformed ebook.

None of this is thing I person to retrieve to run. Every push to main fans retired into 14 parallel CI jobs — build the CSS, past the EPUB, Kindle EPUB, people PDF, PDF/X-1a, HTML, and DOCX broadside by side, and validate each arsenic its artifact comes ready. A greenish cheque intends each format built and passed each gate; a reddish X intends something’s disconnected earlier I’ve moreover alt-tabbed away.

# build.yml — mostly independent jobs, truthful CI runs them successful parallel

jobs:

build-epub: # → dist/book.epub

build-kindle: # → Kindle-specific EPUB

build-pdf: # → 6"×9" paperback PDF

build-pdf-ingramspark: # → PDF/X-1a for IngramSpark

build-html: # → web preview

validate-epubcheck: { needs: build-epub }

validate-ace: { needs: build-epub }

validate-playwright: { needs: build-html }

A GitHub Actions tally of build.yml fanning retired into fourteen jobs — lint-and-test, detect-duplicates, build-css, build-epub, build-kindle, build-pdf, build-html, build-docx, and Build PDF/X-1a, past validate-epubcheck, validate-ace, validate-links, validate-html, and validate-playwright — each 1 passing green, full long 5 minutes 8 seconds.A GitHub Actions tally of build.yml fanning retired into fourteen jobs — lint-and-test, detect-duplicates, build-css, build-epub, build-kindle, build-pdf, build-html, build-docx, and Build PDF/X-1a, past validate-epubcheck, validate-ace, validate-links, validate-html, and validate-playwright — each 1 passing green, full long 5 minutes 8 seconds.

And because each build stamps its perpetrate onto the title page, the book is versioned for illustration software. I’m connected merchandise 1.0.1 — with a tag and a changelog, not a graveyard of final_v3_revised_ACTUALLY_FINAL.docx files. A typo hole is simply a constituent release.

Publishing#

Here’s the irony: aft automating everything up to this point, the existent publishing is almost wholly click-ops. There’s nary git push to production. Each store — Amazon’s KDP, IngramSpark for bookstores and libraries, Draft2Digital for Apple Books and Kobo — wants you to log into a web dashboard, upload the EPUB and the people PDF by hand, and re-enter the aforesaid metadata (title, description, BISAC categories, keywords, price) into a somewhat different shape each time. My pipeline builds a flawless artifact, and past I upload it for illustration it’s 2009. (share this quote)

A fewer things kept moreover that portion honest:

  • I’m my ain publisher. I formed an LLC and bought my ain ISBNs — one per format — so the catalogs database maine arsenic the publisher, not a free level ISBN pinch the retailer’s sanction connected it — and nary of the vendor lock-in that rides on pinch one, since a free ISBN only publishes done the level that handed it out.
  • Wide, not exclusive. I skipped Amazon’s KDP Select, which pays a spot much successful speech for locking the book to Amazon, truthful the book could beryllium disposable everyplace astatine once.
  • The metadata is versioned too. The description, categories, and keywords unrecorded successful the repo — a azygous root of truth I tin diff — and an ONIX provender is generated from it for the channels that judge one. I still paste it into web forms by hand, but astatine slightest I’m pasting from a record nether type control.

Looking forward#

The bully point astir a book that builds for illustration software: the aforesaid machinery keeps paying disconnected aft launch.

  • Translations. Because the contented is system Markdown, translating it is person to localizing an app than retyping a manuscript. I’ve sewage a pipeline (Brazilian Portuguese, Latin American Spanish, German) that drafts a translator of the vanished English book, pins each heading ID truthful cross-references don’t break, enforces a glossary truthful cardinal position enactment consistent, and back-translates the consequence to cheque it against the original — the aforesaid trust-but-verify small heart arsenic the prose linters, conscionable crossed languages.16
  • An audiobook. If I grounds one, turning 100,000 words into narration opens a full caller people of bug: mispronunciations — so the audiobook has its ain QA suite. It transcribes the generated audio backmost to matter and diffs that against the script, checks phonemes connected the tricky words, and audits pronunciations — all wired into their ain CI workflows. It’s a snapshot test, aimed astatine my ain voice.17
  • Releasing the tools. Almost nary of this is circumstantial to my book — the validators, the Lua filters, the full pipeline. I’d for illustration to cleanable them up and put them retired arsenic unfastened root (a noun, nary hyphen), truthful the adjacent personification doesn’t person to build it from scratch. And nary of it would beryllium without the unfastened root projects it already stands on — the full book is different people’s generosity, compiled.18

Conclusion#

One Markdown source, a linter pinch opinions, and a build that yells erstwhile I’m wrong — here’s what each that over-engineering added up to.

By the numbers#

MetricCount
Words~100,000 crossed ~70 chapters and sections
Print length576 pages (6”×9”)
Published formats5 (plus a DOCX I don’t ship)
Tests~70 files, 2,204 cases, ~5,500 automated checks
CI jobs per push14, successful parallel
Style rules~300 covering 500+ banned terms, complete a 5,000-rule grammar engine
Commits5,000+ to get here
Books1 (frankly over-engineered, but fun)

The tooling outgrew the book, too. I pointed the full servants of the state astatine this blog’s fifteen-year archive and caught a 2011 station that had been saying “its clear” wherever it meant “it’s clear” the full time — the nonstop missing apostrophe my linter now flags connected each keystroke. Thousands of group publication it; cipher ever mentioned it. You don’t find out. You person to spell looking. (share this quote)

And it wasn’t only the tooling that transferred — the habits did. The instincts I sharpened here — treat a correction caught erstwhile arsenic a norm that catches it forever, support a quality successful the loop connected thing a instrumentality drafts, make the build the root of truth — have already recovered their measurement into really I tally my different projects, this tract included.19

I’m not going to show you to constitute 5,500 tests for your novel. For astir books, astir of this is wildly disproportionate — and that’s the point. I did it because the marginal costs of 1 much check, 1 much format, 1 much validator was a fewer minutes and a small curiosity, and because doing it the developer measurement meant I could constitute from an iPad distant from my table and spot that main was ever shippable. If you walk your days shipping software, the devices you already cognize will return you further than you’d expect. The publishing manufacture starts pinch a connection processor. I started pinch a Git repository (share this quote) — and I’d commencement location again.

Open & Async book cover

Out now

Open&Async

The collaborative package improvement playbook for distant and distributed teams. Drawing connected a decade astatine GitHub — connected Kindle, Apple Books, Kobo & more.

Buy it — $9.99

What would you over-engineer, if you pointed your ain devices astatine it?

More