A real, live leasing site — one developer, ~9,500 lines changed across 51 files. This turned a single-file prototype into a modular platform non-technical staff can publish from, with AI-crawler discoverability baked into the pipeline itself.
The entire backend lived in a single index.js: routes, auth logic, mailer setup, database queries, and validation all interleaved. What that actually cost:
Structured data, a machine-readable llms.txt, and an agent-facing discoverability file — regenerated automatically from the same content staff publish through, so the AI-search surface never drifts out of sync with the site.
Create, edit, schedule, and preview posts — including an image pipeline that resizes and cleans up header images automatically — without touching code.
Routes and shared logic separated into routes/ and lib/ — the precondition for everything above, and the refactor that surfaced and closed the auth gap.
By 2026, a growing share of apartment search starts inside an AI assistant — "find me a pet-friendly 2-bedroom in Chubbuck under $X" — not a Google results page. A site optimized only for classic crawlers is invisible to that traffic. This rebuild treats AI discoverability as a first-class requirement, not something bolted on after launch.
llms.txt — a dense, FAQ-style brief on the property (address, pricing structure, pet policy, voucher acceptance, office hours, and a linked index of every page) generated from the live posts table, so it can never go stale the way a hand-written file would.robots.txt — signaling explicit intent to be legible to agentic traffic ahead of most small-business sites even attempting this.ApartmentComplex + FAQPage schema tuned for answer-extraction — geo-coordinates, price range, and opening hours in the exact shape an assistant needs to answer "is it open Saturday" without visiting the page; the FAQ schema mirrors the six most common leasing questions as literal Q&A pairs an assistant can lift and cite directly.BlogPosting + BreadcrumbList schema on every post, with an explicit, consistent author entity — the authorship signal generative engines weight for trust, aimed at LLM retrieval rather than classic ranking.llms.txt both regenerate from the same posts table on request, so publishing a post updates the classic-SEO surface and the AIGEO surface simultaneously. No second workflow, no drift between the two.sitemap.xml and llms.txt rebuild from the same posts tableBlogPosting schema attaches with author + breadcrumb dataEvery page of new content is published once and simultaneously indexed for Google, structured for AI assistants to cite correctly, and attributed to a consistent, named author — without a second manual step.
app.get("/", ...)
app.post("/contact", ...)
app.get("/staff/login", ...)
app.post("/staff/login", ...)
app.get("/staff/contact/:id", ...)
app.post("/staff/contact/:id", ...) // no auth check
app.delete("/staff/contact/:id", ...) // no auth check
// mailer setup inline
// db queries inline
// validation inline
// ...
const { app } = require("./lib/app");
app.use("/", require("./routes/home"));
app.use("/blog", require("./routes/blog"));
app.use("/author", require("./routes/author"));
app.use("/", require("./routes/seo"));
app.use("/contact", require("./routes/contact"));
app.use(
"/staff",
requireAuth,
require("./routes/staff")
);
Auth middleware now applies uniformly to every route under /staff/*, instead of being repeated (and occasionally missed) route by route.
Pulling auth into a single piece of shared middleware and applying it uniformly across every staff route surfaced a gap: two staff endpoints had been missing the same auth check every neighboring route already enforced. It's the kind of thing a monolith with logic repeated route-by-route makes easy to miss — and the kind of thing a proper refactor catches as a side effect, not a follow-up patch.
Four weeks post-launch, AI assistants are already a distinct, trackable referral channel — not a hypothetical one. It's a small number next to organic search, but it's traffic that would have been literally invisible to a site without structured data and an llms.txt for an assistant to draw from in the first place.
GA4 shows 106 organic users against Search Console's 981 clicks over different, overlapping windows — a gap partly explained by attribution differences and deep-linking, and worth continuing to watch rather than reconciling into one number. The homepage still accounts for the large majority of landing traffic (171 of 178 active users); the blog guides (Moving to Chubbuck, Pet-Friendly Apartments) are early and currently ranking page 2–3 — the clearest next target, since they're new pages this platform made possible to ship at all.
View live site ↗