Skip to content
POLARGATE
Hotels and hospitality

A bilingual hotel website that crawlers and AI assistants can read

A 4-star city hotel in Castilla-La Mancha had a website that search engines received as an empty container. Polargate rebuilt it as 16 pre-rendered bilingual URLs and now runs it on a monthly Care retainer with a recurring audit loop.

Home page of hoteltalavera.com: the Talavera Hotel logo with four stars over a hotel room with a double bed, red cushions and a wide window onto the city.
hoteltalavera.com
16
indexable URLs, Spanish and English
48
audit findings confirmed, none refuted
27
published FAQs with FAQPage schema
20
automated tests guarding SEO coherence
0
console errors with the security policy in enforce mode

The problem

The hotel's website was a single page rendered in the browser. Search engines and AI assistants received an almost empty HTML container, every subroute answered 404, and the language tags pointed back at themselves, so the English version had no separate existence. There were no security headers. The contact form wrote into a database table that any anonymous visitor could read, and it delivered nothing to reception. Room types, prices, venues and opening hours only existed after JavaScript ran, which meant they existed for nobody who was not a browser.

What we built

Polargate rebuilt the site on Vite, React and TypeScript with vite-react-ssg, so every route ships real HTML. The content became 16 indexable URLs, seven in Spanish and seven in English plus a FAQ page in each language, each with its own title, description, canonical and hreflang with return tags. One TypeScript file holds the hotel data and feeds the visible page, the schema.org graph and the llms.txt files. The contact form moved to a Supabase Edge Function with server-side validation and rate limiting, and mail leaves through Resend on a dedicated sending subdomain.

The outcome

Twenty URLs answer 200 in production, the content security policy runs in enforce mode with no console errors, and both room types with their prices are readable in the served HTML. A 55-agent adversarial audit produced 48 findings, all confirmed and all fixed, among them a robots.txt group inheritance bug and English pages served with a Spanish language tag. Twenty automated tests now guard Spanish and English parity, unique metadata, and structured data against visible text. Traffic and booking effects are not measured yet, so Polargate does not claim them.

Stack

  • Vite
  • React
  • TypeScript
  • Tailwind CSS
  • shadcn/ui
  • React Router
  • Vercel
  • Supabase
  • PostgreSQL
  • Deno
  • Resend
  • GA4
  • Search Console
  • Google Maps
  • Vitest
  • GitHub
hoteltalavera.com

What we found

An external audit and a code review on the same day reached the same verdict. The site was one page rendered in the browser, so a crawler received a container and nothing else. The English version had no URLs of its own, subroutes returned 404 and no security headers were sent. The contact form wrote into a Supabase table that any anonymous visitor could read, a personal data exposure we closed the same day.

  • Content in the served HTML: empty
  • Indexable URLs: one
  • Security headers: none
  • Contact form: stored the message, delivered nothing

What we built

We kept the design and rebuilt the delivery. The site runs on Vite, React 18 and TypeScript with Tailwind and shadcn/ui, pre-rendered at build time by vite-react-ssg and deployed on Vercel. The route carries the language: Spanish at the root, English under /en/, each page pre-rendered in its own language with its own title, description, canonical and hreflang, including return tags and x-default.

A single file, src/lib/schema.ts, holds the hotel's facts. From it we generate the visible page, the JSON-LD graph (Hotel, Organization, WebSite, HotelRoom, EventVenue, FAQPage, BreadcrumbList and a ReserveAction pointing at the hotel's Paraty Tech booking engine) and the llms.txt and llms-full.txt files. Twenty-seven real questions from reception are published in six groups using native details elements, so an assistant reads them without executing JavaScript.

The contact form is a Deno Edge Function on Supabase: honeypot, timing check, server-side validation, rate limiting by hashed IP address, insert through the service role with no grants for the anonymous role, and delivery through Resend from a dedicated sending subdomain, which leaves the hotel's Microsoft 365 mail untouched. Analytics run on GA4 with Consent Mode v2 denied by default, and the map only loads after consent.

How it runs now

The site sits on a monthly Care retainer, and that retainer includes an audit loop rather than patches alone. In August 2026 we ran a multi-agent audit across six areas, with a second agent trying to refute every finding before we accepted it: 48 findings, 48 confirmed, none refuted, 16 of them real bugs in production.

  • Only one of the two room types reached the pre-rendered HTML
  • English pages were served with lang="es"
  • The hero image stayed hidden until hydration, behind a 4.5 second curtain
  • A group inheritance bug in robots.txt
  • Hotel coordinates about 430 metres off

Everything was fixed and verified live from outside the client's network. The content security policy moved from report-only to enforce with zero console errors, 66 orphan files and 33 unused dependencies were deleted, and 20 vitest tests now fail the build if Spanish and English drift apart, if two pages share a title, or if the structured data stops matching what a visitor reads.

FAQ

Questions about this project

How long does a rebuild like this take?
The work ran in phases inside a monthly retainer rather than as one launch. The first version, with the booking engine integration, the brand and the analytics setup, was delivered as a fixed-price project. The move to 16 pre-rendered bilingual URLs went live in July 2026 and the AI visibility work closed in August 2026. A comparable rebuild starts with a paid Discovery Sprint, which fixes scope and sequence before anyone writes code.
Can you do this with our existing booking engine?
Yes. This hotel books through Paraty Tech and we kept it. Polargate treats the booking engine as a fixed point: the site links to it, and the structured data carries a ReserveAction pointing at the same URL, so an assistant reading the page knows where reservations happen. The same approach works with a PMS, a channel manager or a chain engine. We build around what you already pay for instead of replacing it.
Will this get our hotel into ChatGPT and Google's AI answers?
It makes the hotel readable and quotable, which is the part anyone can control. We serve real HTML for every route, put the facts in visible text, keep a schema.org graph that mirrors that text, allow the search and answer crawlers in robots.txt and publish llms.txt. Nobody, Polargate included, can guarantee a citation or a ranking, so we report what is verifiable: what a crawler receives and whether it is correct.
What does the monthly Care retainer actually cover?
Maintenance, the Google services (Business Profile, Search Console, Analytics), content and SEO work, and an audit loop. Every few months we re-audit the live site across security, SEO, accessibility, performance and content, and a second pass tries to refute each finding before we fix anything. In August 2026 that produced 48 confirmed findings and 16 real bugs. Twenty automated tests run on every build so the same regressions cannot return quietly.

Related work

INITIATE

Start the engine

Tell us what you are building in a few short questions. A senior engineer answers in writing within 48 business hours, with a first take on scope, timeline and price.