Central Security Chauffeurs
Central Security Chauffeurs provides SIA-licensed security chauffeurs and close protection. We built a nine-page Astro site where every page emits one @id-linked JSON-LD graph, each service has its own page and FAQ markup, social cards are generated at build time, and a plain-text llms.txt guide makes the business quotable by AI assistants.
- Location
- London
- Year
- 2025
- Built with
- Astro · GSAP & Lenis · Content collections · llms.txt
The problem
Close protection is a high-trust purchase researched discreetly, often late at night and often on a phone. The site had to answer the real questions - licensing, discretion, availability - without a sales call, and it had to be findable both in conventional search and in the AI assistants people increasingly ask first.
What we built
- A page per service, each with Service and FAQPage markup and its own quotable answer paragraph
- One @id-linked JSON-LD graph per page, so the business is described once and referenced everywhere
- A robots.txt endpoint that explicitly allows sixteen named AI crawlers
- llms.txt and llms-full.txt plain-text guides, excluded from indexing so they cannot duplicate the pages
- Twelve social cards generated at build time with headless Chrome, each compressed under 300KB
- GSAP and Lenis motion inside a single matchMedia block, skipped entirely under reduced-motion
A high-trust purchase, researched quietly
Nobody fills in a form to ask whether a close protection officer is licensed. They read, they decide whether the operation looks serious, and they either call or they do not. So every service page opens with a direct, quotable answer to what the service is and who it is for, then answers the licensing and availability questions in FAQ markup underneath.
One graph per page
Rather than scattering structured data through templates, the whole site emits a single JSON-LD
@graph per page from one module. The business and website nodes are always present; the page adds
its own. Everything cross-references by @id, so the phone number and service area exist in exactly
one place.
Unconfirmed facts are explicitly undefined with a TODO(client) marker and spread conditionally,
so the markup never ships an empty property waiting to be filled in.
Built to be quoted by assistants
Being citable by ChatGPT, Claude and Perplexity was in the brief. The
robots.txt endpoint names sixteen AI crawlers and allows each explicitly. Two plain-text guides,
llms.txt and llms-full.txt, describe the services in a form assistants can lift, and both carry
X-Robots-Tag: noindex so they never compete with the real pages as duplicate content.
Motion that knows when to stop
GSAP, ScrollTrigger, SplitText and Lenis all live inside one gsap.matchMedia() block gated on
prefers-reduced-motion: no-preference and a desktop width, with a cleanup function. Under reduced
motion, none of it is created at all. Scroll positions are recalculated after document.fonts.ready,
because font swap changes line breaks and therefore every measurement.
Tell us what you need built.
A short call, a straight answer on scope and cost, and a fixed quote. No retainer, no monthly fee, no commission on your orders.