Repository navigation
Conversation
…ts.txt The code half of pre-launch SEO (#38) covered the search crawlers. This covers the answer engines, which read different things. Structured data was two disconnected islands: Organization from the root, a FAQPage from the home route, neither carrying an @id, so nothing referred to anything. Now every page emits Organization and WebSite with stable @ids, and each route adds its own nodes referencing them — the home page a WebPage, the Service with the Services section as a nested OfferCatalog, and the FAQ; the legal pages a WebPage with dateModified and a BreadcrumbList. Consumers merge a graph by @id across script tags, so the publisher is described once. Every value is derived from messages.json, including Organization.knowsAbout, which is the specialty list — the thing an engine asked "who bills for dermatology practices" has to match on. public/llms.txt restates the page as plain text an answer engine can quote: services, specialties, the comparison table, the FAQ. Generated by scripts/llms-txt.mjs and run from `build`, because a second hand-kept copy of these facts is the same drift the brand assets already taught us about. The output is committed so a copy change shows up in the diff. robots.txt names the AI crawlers. Cloudflare's managed robots.txt is prepended at the edge and disallows GPTBot, ClaudeBot, Google-Extended and five others by default; the real fix is the dashboard toggle, but repeating a user-agent merges the groups and an equal-specificity Allow wins the tie-break. FAQ answers get an id each, so one answer can be cited on its own.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
execil | 8239be7 | Commit Preview URL Branch Preview URL |
Sep 13 2026, 05:05 AM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The search half of SEO was done in #38. This is the answer-engine half — what
ChatGPT, Perplexity, Gemini and AI Overviews read, which is not the same set of
things Googlebot reads.
Structured data is now one graph
It was two islands:
Organizationfrom the root on every page,FAQPagefromthe home route, neither carrying an
@id, so no node referred to any other.Now the root emits
Organization+WebSitewith stable@ids, and each routeadds its own nodes pointing at them:
/WebPage,Service(with the Services section as a nestedOfferCatalog),FAQPage/privacy,/terms,/hipaaWebPagewithdateModified,BreadcrumbListConsumers merge a graph by
@idacross separate<script>tags, so thepublisher is described once and everything else refers to it.
New fields, all derived from
messages.json— nothing invented:Organization.knowsAbout— the specialty list. This is the field an engineasked "who bills for dermatology practices" has to match on.
Organization.contactPoint,emailService.hasOfferCatalog— the four Services cards, nested by stage of therevenue cycle, each line item as an
OfferService.audienceWebPage.dateModifiedon the legal pages, parsed from the one date already inlegal.jsonrather than stored a second timeTwo keys added to
messages.json:meta.serviceTypeandmeta.audience.public/llms.txtThe landing page restated as plain text an answer engine can quote: the
positioning bullets, services with every line item, the four steps, specialties,
supported EHRs, the full Why Us comparison table, what gets reported monthly,
the fit/not-fit lists, all eight FAQ answers, and the four pages.
Generated by
scripts/llms-txt.mjs, run frompnpm build. Generated ratherthan written because a second hand-kept copy of these facts is exactly the drift
that put a wrong logo in the WhatsApp preview. The output is committed, so a
copy change shows up in the diff.
robots.txtnames the AI crawlersThis is the finding worth reading.
https://execil.net/robots.txtdoes notserve the file in
public/— Cloudflare prepends a managed block thatdisallows GPTBot, ClaudeBot, Google-Extended, Applebot-Extended,
meta-externalagent, Amazonbot, CCBot and Bytespider, and sets
ai-train=no.Default-on, not a decision anyone made here.
Everything else in this PR is decoration while that stands. Filed as #43 with
the dashboard steps — it needs the Cloudflare account, so no agent can do it.
public/robots.txtnow names each of those crawlers in an explicitAllowgroup. Repeating a user-agent merges the groups and an equal-specificity
Allowwins the tie-break, so for crawlers that follow it the block is already
reversed. A fallback, not the fix.
FAQ anchors
Each answer gets
id="faq-<slug>"and a matching@idon itsQuestionnode,so one answer can be linked and cited on its own.
Verified
pnpm checkclean,pnpm buildprerenders all four pages@ids resolve, noduplicated
OrganizationdateModified: "2026-09-08"on/privacy, matching the page's own dateOAI-SearchBot, Googlebot and bingbot all get 200 and the full page — the
block is in robots.txt only, nothing at the edge
https://www.execil.net/still answers 200, not 301 (SEO: the three items no agent can do #39 item 2, unchanged)