The problem
The scheme’s cap is per child, per three-month eligibility period, and each child’s period starts on their own date rather than a shared calendar quarter. A family with two children is tracking two staggered caps at once, and anything deposited above a cap gets no top-up at all.
What it does
Add each child once, then type in what childcare costs. It returns what to deposit, what the government adds, how much of that child’s cap is left, and how many days until it resets — and when a period expires it says so and asks for the new start date rather than quietly continuing with figures that no longer apply.
How it's built
One policy package, so two platforms cannot drift
Every scheme rule lives in a dependency-free workspace package imported by both the web and mobile apps. All money arithmetic is integer pence, converted only at the boundary, and dates are parsed date-only into local values rather than through a timezone-sensitive path.
A two-week production outage caused by one generated line
Blog posts were generated into MDX. A generated LaTeX fragment containing braces was evaluated by MDX as JavaScript, so prerendering threw a reference error for an identifier that appears nowhere in the codebase, and aborted the entire 133-page build. Diagnosing that meant realising the content format was executable code.
A Markdown converter built on a real syntax tree
The replacement walks a CommonMark tree rather than scanning lines, specifically because a sibling project’s hand-rolled converter could not represent a link at all — run over this archive it would have turned all 93 links across 41 posts into literal bracket syntax and glued nested lists into paragraphs.
A generator that fails closed on read errors
The covered-topics lookup throws when the CMS cannot be read rather than returning an empty array, because empty reads as "nothing written yet" and would let the job republish everything it had already covered. Writes use a deterministic document id inside a transaction so a retry cannot duplicate.
The hard part
The build outage. Deploys failed at page 33 of 133 with a reference error for a name that did not exist anywhere in the repo; tracing it to a generated maths expression that MDX parsed as a JSX expression is genuinely non-obvious. The follow-up mattered more than the fix: the write-up records that the obvious narrow detection regex misses this exact case, specifies a broader one, and argues the general rule — a prompt instruction is a request, a validation guard is the wall, so do both and never rely on the prompt alone.
Stack
- Next.js
- React Native
- Expo
- RevenueCat
- PostHog
Built, shipped and maintained by me. Try TFC Calculator, or see the rest of the work.
