---
title: A spotless website nobody could find
description: proba.baby passed every technical SEO check and was still invisible. A truth lock, a page factory with brakes, and the bugs a website found in the app.
url: https://secretocho.design/notes/a-spotless-website-nobody-could-find/
type: BlogPosting
published: 2026-10-11
---

# A spotless website nobody could find

> proba.baby passed every technical SEO check and was still invisible. A truth lock, a page factory with brakes, and the bugs a website found in the app.

2026-10-11 · 8 min

*Part 7 of 7 in the [Building ProbaBaby](#the-series) series.*

proba.baby is the website I built alongside the app. Its first commit is from 28 December 2025, and by October 2026 it had 187 commits, 186 of them co-authored by Claude. On 10 October an audit crawled all 155 URLs in its sitemap. Every one returned 200. Canonicals were clean, hreflang was reciprocal, and the text was rendered on the server, 600 to 4,000 words a page.

Bing’s own search returned nothing, even for the bare word “probababy”. Brave, Common Crawl and the Wayback Machine had no pages either. There were zero followed backlinks, and no analytics at all. The audit put it best: “‘Zero visitors’ is a guess, not a measurement.”

|  | result |
| --- | --- |
| sitemap | 155 URLs, every one 200 |
| canonicals | clean |
| hreflang | reciprocal |
| rendering | on the server, 600 to 4,000 words a page |
| Bing, for “probababy” | nothing |
| Brave, Common Crawl, Wayback | no pages |
| followed backlinks | 0 |
| analytics | none |

The diagram, step by step:

1. 10 Oct: an audit crawls all 155 URLs in the sitemap. Every one returns 200.
2. Canonicals clean, hreflang reciprocal, the text rendered on the server.
3. Bing returns nothing, even for the bare word “probababy”.
4. Brave, Common Crawl and the Wayback Machine have no pages. Zero followed backlinks, and no analytics.

*every technical check passed, and nobody could find it.*

This part is about what I did next. It is also the one part of this series without an ending yet.

## A site that kept changing its mind

The site went through as many looks as the app went through platforms. It started in December as a template. A v4 in March brought 35 static pages and a “full SEO overhaul”. In May came a blog on Supabase with its own editor, built in two days and replaced less than four months later by plain Markdown files. In July a redesign brief described what was live: Apple’s default blue as “brand”, and “not a single image of the product anywhere”. The site turned rose. Then, in September, “Precision”: ruled, document-like, with a Punnett square in the hero and the app’s eight PDF report sheets recreated in HTML as a slideshow. It went live on the homepage on 6 September and on every inner page on 3 and 4 October, and the rose theme was deleted with no way back.

None of that made anyone find it.

## My marketing copy was training data

In September I asked Gemini to check ProbaBaby. It described the app wrongly. When I traced each wrong sentence back, almost none of it was invented. Gemini was repeating me.

- **“241 countries.”** In February the website wrote “241 countries” into every stat and translation, and the number went into the App Store description, which is where Gemini read it. The app has vaccination schedules for 240 selectable countries, and support resources for 128.
- **Photo deletion.** Five public places said it five different ways. The App Store said “immediately”, `llms.txt` said “within hours”, the site said “48 hours by default”, the privacy policy said “not retained after analysis”, and the app itself said “20 minutes”, “never stored” and “24 hours”. Only the site came close to what the code does.
- **“No account required.”** Even the code-verified info bank I built in July said so. The app requires a free account. I caught it the day after the new fact sheet went live, which taught me that a source of truth still needs a sceptic.
- **Widgets.** “11+” on the App Store, “16” in the app, “7+” on the old site. There are 17.

The same truth pass found older errors too, such as LiDAR: the app uses the TrueDepth camera and never used LiDAR.

Gemini also offered a fix: an “LLM & Search Engine Optimization Specification”. Its JSON-LD was unreadable, with markdown links inside JSON strings. It said iOS 18, listed 11 of the 32 languages, and asked for things the site already had. The useful move wasn’t its spec. It was tracing every wrong sentence to its source.

## The truth lock

So the site got one source of public truth. A fact sheet lists each claim with its source in the code, in English and Turkish, with a “never say” list beside it, and it has a machine-readable twin the pages render from. A claims check scans the messages, the content, the blog and every rendered page for 44 banned patterns, in both languages, and the rules require running it before every push. Anything allowed through has to name an owner.

1. **the fact sheet** · each claim with its source in the code, in English and Turkish, beside a “never say” list
2. *mirrors* · **its machine-readable twin** · the pages render from it
3. *renders* · **the press page** · **llms.txt** · **the structured data**
4. *scanned* · **the claims check** · 44 banned patterns, both languages, before every push

The diagram, step by step:

1. One source of public truth: a fact sheet, each claim with its source in the code, in English and Turkish.
2. It has a machine-readable twin, and the pages render from it.
3. The press page, llms.txt and the structured data render from that one file.
4. A claims check scans every rendered page for 44 banned patterns, in both languages. The rules say to run it before every push.

*one source of public truth, and a check the rules say to run before every push.*

The press page, `llms.txt` and the structured data now render from that one file, and markdown copies of the key pages sit beside them for AI crawlers. In the app, 619 translated cells were corrected, shipping with the next version; fifteen languages had invented “AES-256” encryption in a translated privacy section.

Two honest caveats. The loudest source is still wrong: until version 1.0.5 ships, the App Store description still says “241”. And the twenty-question read-back, where four AI assistants get asked about ProbaBaby and scored, has never been run.

## Breakages no audit saw

- **No page ever had a share image.** An `og:image` file existed from the first commit in December. In Next.js, a page’s own Open Graph settings replace its parent’s wholesale, so the image was dropped on every page. Lighthouse doesn’t check for it.
- **The touch icon was a 404,** because the locale middleware redirected every path without a dot in it.
- **Blog posts were served to browsers as raw Markdown** for up to four weeks. A server-side translation call in the blog’s 404 page made the post route dynamic, and Vercel then answered with the post’s Markdown copy, the one made for AI crawlers. Locally, `next start` was fine. The surface I built for machines had broken the one built for people. Now I check production with a browser’s `Accept` header and look at the `content-type`, not just the status code.

## Faster by sending less

Mobile Lighthouse scored 68 on the old site. The redesign, with fewer preloaded font files, reached 86. Then the real cause turned up: the whole translation catalog, 55% of every page, shipped to every browser. Sending only the strings each page’s interactive parts use took the homepage’s HTML from 187 KB to 86 KB compressed, inner pages from about 131 KB to about 30 KB, and the score from 88 to 91.

- **mobile Lighthouse score**
- **old site**: 68
- **the redesign, fewer font files**: 86
- **before the catalog fix**: 88
- **after it**: 91
- **HTML, compressed**
- **homepage, before**: 187 KB
- **homepage, after**: 86 KB
- **inner pages, before**: ≈131 KB
- **inner pages, after**: ≈30 KB

The diagram, step by step:

1. Mobile Lighthouse on the old site: 68.
2. The redesign, with fewer preloaded font files: 86.
3. The real cause: the whole translation catalog, 55% of every page, shipped to every browser.
4. Sending only the strings each page’s interactive parts use: homepage HTML 187 → 86 KB, inner pages about 131 → 30 KB.
5. And the score: 88 → 91.

*faster by sending less.*

## Analytics as a privacy bug

The site has free tools: due dates, baby percentiles, corrected age for twins. Their inputs lived in the URL’s query string, so the links could be shared. A test with the real Google Analytics tag showed what that meant: its automatic events would have sent a baby’s date of birth and weight to Google. GA can redact only 30 parameter names, and the tools used about 54.

So on 10 October, Vercel’s cookieless analytics went on and Google Analytics shipped switched off. Every tool moved its state after the `#` in the URL, which never reaches the analytics request, and real hits were captured to prove it. GA4 went on the next day, consent-gated. Privacy-safe analytics turned out to be a code design problem, not a dashboard setting.

## The website audited the app

Putting the app’s data on the open web forced checks the app had never had.

- A Turkish number listed as a 24-hour mental-health crisis line was a hospital appointment line.
- The UK vaccine schedule was missing a primary dose.
- Week-by-week baby weights ran 10–17% below WHO’s.
- In a sample of 30 entries from the names database, 23% were fully correct and 63% were unusable.
- The eye-colour model, with no grandparent data, treated every brown-eyed parent as carrying two brown copies, so brown × blue came out as “100% green”.

On the web, the week weights go through a corrections layer, and the UK schedule and most of the names are held back. In the app, the crisis line and the eye-colour model are fixed; the rest are filed as app tasks. Publishing your own data is a free audit.

## A page factory, with brakes

A new domain with no links can’t win “due date calculator”, a search with about 301,000 a month where the biggest pregnancy publishers hold the top spots. So the October plan, the “traffic hub”, builds pages from the app’s own data instead: calculators, official data tables, week-by-week pages, Turkish first, where the results are weakest and often years old.

The brakes matter as much as the engine. Google’s spam policies count scaled content, translated pages included, so the site has a URL budget: no more than 40 new indexable URLs in the first four weeks, more only for page families whose pilots earn impressions, and never two new families in one week. The first draft would have taken the site from about 155 URLs to about 900 in thirteen weeks.

Health pages come in tiers, enforced in code:

- **Tier 0:** deterministic pages, such as calculators checked against reference values, can be indexed straight away.
- **Tier 1:** pages can be indexed only after a logged human read.
- **Tier 2:** pages about early scans, tests or postnatal depression stay out of the build until a named clinician signs them.

There is no clinician yet, so Tier 2 is off. The editorial policy says plainly that drafts are AI-assisted and that no page is clinician-reviewed yet.

After three adversarial critiques, the plan’s central forecast for day 365 fell from 30,000 visits a month to about 12,000, with a range of 5,000 to 30,000. Pages now carry their own launch dates, and a scheduled job rebuilds the site at 05:00 UTC on each release day, so it publishes itself through 19 December.

## Turkish, honestly

Turkey is my home market, and Turkish copy is written natively, not translated. The review list grew to about 2,630 numbered lines. I read about half of the first batch and wrote back: “Some are good enough, please make it live. If I see something wrong I will write you.” The plan records it exactly as it happened: about half of that batch went live unread by me, and later batches go live by default unless I correct them.

## What I don’t know yet

Whether any of this works. There is no Search Console baseline on record yet. The first scheduled page family goes live on 17 October, and the first pilot gate is on 13 November. There are still no backlinks, no clinician reviewer, and no scorecard for what AI assistants say about the app. I’ll know more by December.

## What I’d pass on

1. Install measurement before you diagnose. Without it, “no traffic” can’t be told apart from “not indexed”.
2. Technical SEO is table stakes. A young domain’s problem is discovery and links, not markup.
3. Everything you publish is input to AI answers. Fix the loudest source first, then make one sentence per fact a check that runs before every push.
4. Treat machine-facing pages as production pages, and test them on the real host with real headers.
5. On a young health site, pace content with a budget and human-read gates.
6. Your own app’s data isn’t web-ready. Publishing it is the cheapest audit you’ll get.

## The series

1. [Four platforms in four months](https://secretocho.design/notes/four-platforms-in-four-months/)
2. [Rules born from mistakes](https://secretocho.design/notes/rules-born-from-mistakes/)
3. [The sheet that closed itself](https://secretocho.design/notes/the-sheet-that-closed-itself/)
4. [A newborn app, with a newborn](https://secretocho.design/notes/a-newborn-app-with-a-newborn/)
5. [What Apple, Postgres and 32 languages taught me](https://secretocho.design/notes/apple-postgres-and-32-languages/)
6. [Twins found us](https://secretocho.design/notes/twins-found-us/)
7. A spotless website nobody could find

[cd ..](https://secretocho.design/notes/)
