Our recipe index prints the word eight 29 times without typing it, and our homepage description still says seven
Munchable scans a food label and answers it against the gut condition you actually have. It covers eight of them. That number is a fact about a registry in the codebase, and it is also a word sitting in prose all over th
Munchable scans a food label and answers it against the gut condition you actually have. It covers eight of them. That number is a fact about a registry in the codebase, and it is also a word sitting in prose all over the product: on the pricing card, in the FAQ, in the terms, on the 404 page, in the mobile app's paywall.
Eight is a recent number. It was seven for months. Before that it was six.
So I went looking for every place the count is written down, and found two completely different habits living side by side in one repo.
The page that counts
The recipe index is at munchable.app/recipes. Thirty-eight recipes grouped by meal, each with a line underneath saying who it suits. Strip the tags off the live HTML and the word "eight" appears 31 times on that one page, 29 of them as the same phrase: "Suits all eight conditions", once per card.
Nobody typed any of them. The phrase comes out of this:
const CONDITION_IDS = Object.keys(RULE_SETS) as ConditionId[];
const COUNT_WORDS = [
'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
'nine', 'ten', 'eleven', 'twelve',
] as const;
export function countWord(n: number): string {
return COUNT_WORDS[n] ?? String(n);
}
export const ALL_CONDITIONS_LINE = `all ${countWord(CONDITION_IDS.length)} conditions`;
A lookup table of English number words, indexed by the length of the rule-set registry. It is not clever and it is not pretty, and the comment above it explains why it exists at all:
The count was the literal word "seven" here, and in the test that checked this line, and in a dozen pieces of copy besides. Adding a condition left every one of them wrong, and the test was wrong in the same direction as the code so it still passed.
That last clause is the part worth keeping. The test asserted that the rendered line equalled "all seven conditions". When the seventh condition became the eighth, the assertion and the string went stale together, in the same direction, so the suite stayed green and told me nothing. A test that hardcodes the same literal as the code is not a test of the code, it is a second copy of it.
By the way, 29 cards is not 29 recipes. A recipe that works as both a snack and a breakfast is carded twice. Nineteen of the thirty-eight recipes suit all eight conditions; the rest name their exceptions, from the same data, which is why a card can say "Suits every condition except reflux" without anybody deciding to write that sentence.
The fifteen places that type it
Then there is everywhere else. I grepped the repo for an English number word on any line that also mentions a condition or a rule set. Nineteen files, twenty-three lines. Seven of those lines are comments and test prose. Of the sixteen that a reader can actually see, fifteen say "eight":
- the
<h1>on munchable.app/conditions, which reads "The eight conditions" - that page's meta description, which also names all eight by hand
- the free-tier line at the bottom of every condition guide, for example the coeliac one
- a feature bullet on the pricing card
- the pricing FAQ answer
- a paragraph in the terms describing what the app does
- a sentence in the about page
- the title of the link our 404 page offers you instead
- a line on the cancelled-checkout page
- a bullet on the mobile paywall
- the publisher description we hand to store listings
- the structured-data description in the SEO helper
- "Every recipe is then run against all eight rule sets before it ships", on the recipe index
- "The eight conditions have a guide each", two paragraphs below it
- "the eight conditions and what Munchable checks for each", on all 38 recipe pages
There is at least one more that the grep could not see: the terms page also promises "five scans each calendar month, across all eight conditions", and the word "conditions" is on the next source line, so a line-oriented search walks straight past it. Which is its own small lesson about auditing prose with a regex.
Every one of those fifteen is currently correct. That is the trap. Nothing is broken, so nothing points out that a ninth condition means editing fifteen strings in thirteen files across two apps and a shared library, and that the failure mode of missing one is a sentence that is quietly wrong rather than a build that goes red.
The one that is already wrong
Except one of the sixteen is not currently correct. The homepage.
description:
'Scan a barcode. Get a clear Good fit, Caution, or Avoid answer for your gut, with the reasons behind it. Seven gut conditions, one scan.',
Seven. That is the meta description of munchable.app, which is the most-read sentence the site owns: it is what a search result prints under the title and what a link preview prints in a chat window. You do not have to take my word for it, view source on the homepage and search for name="description".
The visible page is fine. Scroll to the pricing card and it says "All eight conditions", because that card was edited when the eighth shipped. The description was not, because the description is never on screen while you work. It is twenty lines up in the same file, inside a metadata export, and nothing renders it anywhere a human will trip over it.
What I am actually taking from this
The tempting conclusion is "derive every number". I do not think that is right either. ALL_CONDITIONS_LINE works on the recipe index because the sentence there is formulaic: one clause, one number, repeated per card. The terms paragraph is not formulaic, it is an argument with a number in the middle of it, and threading a template through it would make a legal paragraph harder to read in exchange for saving one edit every few months.
What is wrong here is narrower than "stop typing numbers". It is that nothing in the test suite can see prose. The repo already has a copy-style test that walks the source and fails on an em dash, and a metadata test that reads page titles out of the source as string literals to check them against what a search result can display. Both prove the exercise is possible: read the strings, compare them against something that knows the truth.
What I did by hand was a grep plus a registry length. The next condition will arrive, and the grep should be the thing that fails, not me noticing in a blog post that the first sentence of our own homepage has been one short since the summer.
If you want to see the derived side working, the recipe index is the page to open: twenty-nine cards claiming all eight, each one a count rather than a claim.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.