Six months ago I got tired of doing hydration math on a napkin. So I built SourdoughCalc - a free calculator with 34 SEO-friendly articles.
Six months ago I got tired of doing hydration math on a napkin every time I baked sourdough at home. So I built SourdoughCalc - a free hydration calculator with 34 SEO-friendly articles. Here is what I learned shipping a zero-cost indie project.
The Stack
- Next.js 14 App Router (TypeScript + Tailwind)
- Cloudflare Pages for hosting ($0/mo, global CDN, sub-second TTFB)
- Playwright for e2e tests
- 34 hand-written articles targeting sourdough keywords
Total monthly cost: $0.
The SEO Strategy That Worked
I did not try to rank for "sourdough" (impossible for a new site). Instead I targeted long-tail:
| Keyword | Monthly Volume | Position |
|---|---|---|
| "65% hydration sourdough" | ~7,200 | Top 5 |
| "sourdough hydration calculator" | ~4,500 | Top 3 |
| "high vs low hydration sourdough" | ~2,000 | Top 10 |
Every article follows the same template:
- Answer the question in the first 100 words
- Add a FAQ schema block (FAQPage JSON-LD)
- Link to 3-5 other articles in the cluster
What I Would Do Differently
- GSC indexing speed: Do not batch-submit. Submit URL individually for faster pickup.
- FAQ schema: Mandatory. Google shows FAQ rich snippets, which doubles CTR.
- Comparison tables: I added 3-column comparison tables in 6 articles. They get featured snippets.
The Real Win
The calculator is the hook. 34 articles are the asset. SEO compounds. Six months in, I am getting 5x more organic traffic than the launch day spike ever was.
Try It
Free, no signup: sourdough-hydrationcalculator.com
If you have questions about the SEO or the build, drop a comment. I will answer.
Top comments (5)
I like the emphasis on a source of truth. The same approach prevents local sites from drifting when CMS copy, schema, sitemaps, and Google Business Profile details are maintained by different people.
You nailed the real pain point. The drift problem is exactly why I
ended up rewriting the sitemap twice in the first month - the source
of truth was in the TypeScript file, but the static XML had already
shipped to Cloudflare with stale URLs.
For local sites, the Google Business Profile piece is one I hadn't
thought about - do you sync it programmatically or treat it as
manual? I've seen small businesses where it's updated 4 different
times a year and the addresses/categories silently drift from the
site copy. Feels like the kind of thing where the schema.org
LocalBusiness JSON-LD should be the source and the GBP dashboard
should ingest, but Google's tools don't make that easy.
Thanks — and that local drift point is exactly what I was designing
against. The failure mode I didn't expect: schema drift is easy to
catch, but GBP (Google Business Profile) drift is the silent killer.
NAP inconsistencies across GBP, schema, and CMS footer slowly erode
local pack rankings over months.
What I started doing: a weekly cron that hashes the canonical NAP +
hours + categories from the source of truth, diffs it against GBP
via the API, and emails me if anything moves. Caught 2 silent GBP
edits by Google itself in the first month.
Curious what your source of truth looks like for local SEO specifically
— Notion, single CMS field, or a YAML in the repo?
I use a canonical structured record rather than a free-text doc: business identity, phone, address, hours, categories, services, and evidence fields. The CMS and schema should render from it; GBP is a separately observed surface. Your hash/diff is exactly the useful separation: it catches both accidental drift and a provider-side change without pretending the API is the source of truth. I’d also log the previous/new value and actor where possible, so the alert becomes an audit trail rather than just a warning.
Audit trail is the missing piece — agreed. My current diff just shows
current vs canonical, no actor or timestamp. Was about to add this
when I move from a one-off cron to a real audit log, but the harder
question is attribution: when Google itself standardizes a category
or merges two GBP entries without warning, who's the "actor" in your
audit trail?
On the evidence field — I trust whoever edits the YAML right now,
which is fine when it's just me but breaks the moment you have a VA
or marketing person touching the source. How are you capturing
evidence at scale without the record becoming a wiki?