You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Everything a crawler or a shared link needs: title and description, canonical, Open Graph and Twitter tags, favicons, one static share image, and structured data.
Structured data is Organization, not LocalBusiness. The local-business types exist for places people visit and effectively require a postal address to earn rich results; with only region and country publishable, they would be both wrong and ineffective. The brand is Execile; the registered entity appears as legalName.
Fields without real values are omitted, never placeholdered — structured data carrying a bracketed placeholder is worse than an absent field, because it can be flagged.
The share image is a hand-made static asset. A build-time generator would be a rendering pipeline and two dependencies to produce one file that never changes.
robots.txt and sitemap.xml hard-code the domain, so they are written at provisioning rather than now.
Acceptance criteria
Title, description, canonical, and the full Open Graph and Twitter tag set render from Messages on the root route
The share image URL is absolute, built from the site URL variable
A 1200×630 share image, favicon and touch icon are committed
Organization JSON-LD with name Execile and legalName the registered entity
The postal address carries region and country only
telephone and sameAs are omitted while no real values exist
The JSON-LD validates against a structured-data testing tool
The site ships indexable
robots.txt and sitemap.xml are present with the domain left as an explicit provisioning placeholder
The canvas's landmark structure is preserved: one h1, section headings as h2, each section labelled by its heading
Organization, not LocalBusiness — the local-business types need a postal address to earn rich results, and only region and country are publishable. Verified from the served page:
Both absent fields are omitted, not placeholdered — structured data carrying [phone] is worse than no field, since Google can flag it.
The OG image
Generated once by scripts/og-image.py and committed; not a build step. It renders in the canvas's language with the same two headline emphases.
The first render overflowed the canvas — the headline ran off the right edge. It now breaks into three lines and reduces the size until the widest line clears the padding, so a copy change cannot silently produce a broken share card.
One note: Pillow cannot read WOFF2, so the render uses the variable TTF from the same Fontshare kit. That font is gitignored and nothing converted is shipped — the site still serves the untouched WOFF2, so the licence position is unchanged.
Domain-dependent files
robots.txt and sitemap.xml hard-code the domain, so both carry an explicit REPLACE_AT_PROVISIONING marker and a comment. Better a visible gap than a plausible-looking wrong URL.
Verified
10 og: tags, 5 twitter: tags, canonical, index, follow, and all four assets serving with correct content types (image/png, image/svg+xml, text/plain, application/xml). vp check passes on 51 files.
Activity
[-]Footer[/-][+]SEO, structured data and sharing assets[/+]Abuubkar commentedon Sep 5, 2026
Done on branch
ticket/30-seo.Structured data
Organization, notLocalBusiness— the local-business types need a postal address to earn rich results, and only region and country are publishable. Verified from the served page:Both absent fields are omitted, not placeholdered — structured data carrying
[phone]is worse than no field, since Google can flag it.The OG image
Generated once by
scripts/og-image.pyand committed; not a build step. It renders in the canvas's language with the same two headline emphases.The first render overflowed the canvas — the headline ran off the right edge. It now breaks into three lines and reduces the size until the widest line clears the padding, so a copy change cannot silently produce a broken share card.
One note: Pillow cannot read WOFF2, so the render uses the variable TTF from the same Fontshare kit. That font is gitignored and nothing converted is shipped — the site still serves the untouched WOFF2, so the licence position is unchanged.
Domain-dependent files
robots.txtandsitemap.xmlhard-code the domain, so both carry an explicitREPLACE_AT_PROVISIONINGmarker and a comment. Better a visible gap than a plausible-looking wrong URL.Verified
10
og:tags, 5twitter:tags, canonical,index, follow, and all four assets serving with correct content types (image/png,image/svg+xml,text/plain,application/xml).vp checkpasses on 51 files.Abuubkar commentedon Sep 5, 2026
Done. Organization JSON-LD with omitted rather than placeholdered fields; OG image auto-fits so copy changes cannot break it.
Footer
SEO, structured data and sharing assets
Use the real phone number