cd /news/generative-engine-optimization/building-foxyinvoice-chapter-11-reac… · home › topics › generative-engine-optimization › article
[ARTICLE · art-139962] src=dev.to ↗ pub= topic=generative-engine-optimization verified=true sentiment=↑ positive

Building FoxyInvoice — Chapter 11: Reach — SEO, AI crawlers, and being the machine-readable answer

A developer building the FoxyInvoice invoicing app documented a distribution stack that serves crawler-ready static HTML for its Angular SPA, publishes an llms.txt file for AI answer engines, and pushes sitemap updates via IndexNow. The build-time prerendering script generates per-route titles and meta descriptions, while robots.txt allowlists public routes and edge proxy headers enforce noindex on private ones. Access logs analyzed by a script confirmed search crawlers reading robots.txt and template pages within days of launch.

by read3 min views1 publishedSep 26, 2026

This series is written in the open, from a real production system. This chapter is the reach stack: prerendering, robots.txt, llms.txt, IndexNow, and measuring it all with access logs. [All chapters and diagrams live in the public repo.]

Somewhere between "launched" and "learned people exist," every product

discovers distribution. Ours arrived with a twist that defines this

chapter: half your future traffic now arrives via machines that never render your app — search crawlers that mostly cope, and AI answer

The FoxyInvoice app is an Angular SPA: the server ships an empty shell

and JavaScript builds the page. Human browsers: fine. Googlebot:

tolerant, eventually. AI crawlers: blind. Fetch the marketing page

with curl — which is exactly what a crawler does — and you got:

<title>Invoicing</title>
<app-root></app-root>

One word and an empty div. To every machine reader, our entire free

invoice-template business was the word "Invoicing."

Our robots.txt doesn't list what's forbidden — it lists what's

allowed, then disallows everything else:

User-agent: *
Allow: /$ /pricing /privacy /terms /templates /templates/*
Disallow: /

Every future route — admin consoles, /upgrade, QA harnesses — is

non-indexable by default until deliberately made public. The same

policy is enforced server-side with X-Robots-Tag: noindex, nofollow

headers at the edge proxy, per URL: private pages carry it; public

pages don't. Belt and suspenders, because robots.txt disallow alone

never guarantees de-indexing.

Full server-side rendering means an always-on SSR server — violating

our boringness constraint — for pages that are 95% app shell. Instead,

a post-build script generates static, crawler-ready copies of every

public route when the SPA compiles:

<title> and meta description per page ("Free Plumbing Invoice Template — FoxyInvoice") The edge proxy's try_files serves these static files to anything that

fetches the URL; real browsers still get the app (Angular replaces the

static body on boot). No new server, no SSR framework, crawler-complete

pages.

llms.txt — a menu for answer engines The emerging convention: a markdown file at the root telling AI systems

what the product is and linking its key pages, in their vocabulary.

Ours lists the product, every template page with a one-line

description, and contact points. Cheap, human-readable, and exactly

the artifact a "recommend an invoicing tool" query wants.

Crawlers traditionally rediscover content on their own schedule.

IndexNow flips it: on every deploy, the pipeline POSTs all sitemap

URLs to the alliance endpoint (Bing-powered — which feeds several AI

answer engines) with a key file proving domain ownership. Our first

ping returned HTTP 202 — accepted — and the pages were in Bing's queue

the same evening.

"You can't improve what you can't see," so the edge now logs every

request as JSON (rotated, bounded). The analysis is one script:

user-agents, paths, crawler classes. Within days we could see search

crawlers reading robots.txt and template pages — and, just as

valuable, probe-noise (stray /wp-admin scans) being correctly

absorbed. Pair this with Google Search Console + Bing Webmaster

registration (a five-minute runbook lives in the repo) for the

indexing-and-impressions view logs can't give you.

Reach is only worth building if it lands somewhere. The template

gallery — now crawlable — is the top of a three-slice funnel we shipped

in order:

Each slice was verified in a real browser before shipping — the funnel

is the one place where "should work" is banned.

Recap. Serve machines real HTML (prerendered at build), allowlist

what's public (default-closed), publish llms.txt, push updates via

IndexNow, and measure with access logs + Search Console. The era of

"GEO" — being the machine-readable answer — is just SEO where the

reader never renders your JavaScript.

Reading this and want to be found the way this series was? Create a free workspace at foxyinvoice.com, then redeem founding code U8B4Z8S87X on the Upgrade page — 6 months of Pro, free, no card. If anything breaks, there's a feedback button in the app. I read every one.

Next: Chapter 12 — Engagement & automation: UI first, then automate.

── more in #generative-engine-optimization 4 stories · sorted by recency
── more on @foxyinvoice 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/building-foxyinvoice…] indexed:0 read:3min 2026-09-26 · —