Crea un sitio web de reservas premium con Claude Code

Crea un sitio web de reservas único para una peluquería, una barbería o un estudio de masajes, con citas reales, emails de reserva y un panel para el propietario.

Hoja de ruta y recursos

Requisitos

Claude Desktop

Claude Code crea tu sitio web en la app de escritorio. Un build completo es una sesión larga, así que usa un plan de pago de Claude con margen de sobra.

Descarga Claude Desktop

https://claude.ai/download

Node.js

Descarga la versión LTS. Claude la usa para crear y comprobar tu sitio web.

Descargar Node.js

https://nodejs.org/en/download

Cuenta de GitHub

Gratis. El código de tu sitio web vive aquí, y Hostinger lo despliega desde aquí.

Crear cuenta de GitHub

https://github.com/signup

Cuenta de Supabase

El plan gratuito es suficiente. Permite dos proyectos activos: si ya tienes dos, pausa uno que no uses. Guarda tus servicios, horarios, reservas y tu acceso al panel.

Crear cuenta de Supabase

https://supabase.link/r4gdwhi

Cuenta de Resend

El plan gratuito envía 100 correos al día y 3,000 al mes. Cada reserva envía varios: el código, la solicitud recibida, tu alerta y la confirmación.

Crear cuenta de Resend

https://resend.com/signup

Tu propio dominio

Tu sitio web vive en él, y los emails de reserva se envían desde él. Una dirección gratuita como Gmail no puede enviarlos. ¿Vas a comprar el dominio con tu plan de Hostinger? Consigue el plan antes del paso 3.

Hosting de Hostinger

Necesitas hosting en el paso 5, cuando tu sitio web se publica.

Elige un plan de Hostinger

Usa el plan Business (Unlimited) o un plan Cloud: solo esos ejecutan Node.js Web Apps, hasta 5 en Business y 10 en Cloud.

Elige tu negocio de reservas

Elige tu tipo de negocio

Tu parte. El Booking Engine es el mismo para los tres: el diseño, los textos y los servicios de ejemplo se crean para el que elijas.

¿Qué tipo de negocio es?

Peluquería

Cortes, color y peinados, con los servicios de peluquería ya preparados del motor.

Build a complete, premium booking website for **{{BUSINESS_NAME}}**, a hair salon in {{CITY}}, in this empty folder. The booking system is an installed package — the **Profit Studio Booking Engine**. It owns availability, bookings, booking emails and the owner's dashboard. You design and build the public website around it, and nothing the engine provides. ## 1. Set up 1. Scaffold a Vite + React + TypeScript app **in the current folder**: `npm create vite@latest . -- --template react-ts --no-interactive`, then `npm install`. create-vite stops without an error when the folder is not empty — a `.DS_Store` or a `.claude/` folder is enough — so check that `package.json` now exists. If it does not, scaffold into a new subfolder the same way, move all of its files (dotfiles included) up into this folder without overwriting or deleting anything already here, and remove the empty subfolder. Remove the template's demo content. 2. `npm install --save-exact @profitstudio/booking-engine@2.0.0-beta.1`, then `npx booking-engine init --preset hair-salon`. 3. Read `node_modules/@profitstudio/booking-engine/docs/BUILD-A-SITE.md` once: it has every file to wire, the booking API and the error table. Open `docs/INTEGRATION.md` only at a section it names, and nothing else in the package. 4. Wire the engine as BUILD-A-SITE §1 shows, with the engine's `hairSalonPreset` as `preview.preset`; in `preview.business` use `{{BUSINESS_NAME}}`, the time zone `{{TIMEZONE}}` and a plausible placeholder `contact` in {{CITY}}. The dashboard on `/admin/` mounts `<BookingAdmin engine={engine} siteUrl="/" content={siteContent} />` and gets only your brand accent (light and dark) in `src/admin-theme.css`. One public page (sections and an in-page booking flow), no client-side routes. No backend yet: no Supabase project, no `supabase` commands, no `.env.local` — the site runs in preview mode with a visible “Preview — sample data, bookings are not saved” banner. ## 2. Design — the creative part Make it feel like a real, distinctive hair salon, not a template: - **Style direction:** {{STYLE_DIRECTION}} - **Audience:** Local clients, mostly 25–55, booking cuts, color and styling — most of them on a phone, often in a hurry. - **Tone:** Confident, warm and expert. Never clinical, never luxury cliché. - **Sections:** - Hero with the salon's personality and one clear “Book an appointment” action - Services and prices loaded from the engine (duration, price, “from” prices), grouped sensibly — with the owner's optional service photos (cut, colour, styling work) shown in the site's own style when a service has one, and a complete typeset menu without them - The team / stylists — placeholder bios and names the owner will edit, clearly marked - The salon space and approach (what makes this salon different) - Testimonials — clearly marked as placeholder examples, never presented as real reviews - Opening hours (from the engine) and location / contact (from the engine's business contact) - The booking flow - Footer with a discreet “Staff login” link to /admin/ - **Booking experience:** - Service first, then the date and time together, then details, then the email code, then confirmation - A real month calendar with month and year navigation that shows each day's status from the engine — open, only a few times left, fully booked, closed or past — loaded with one getAvailability call per visible month (INTEGRATION.md §8 and the calendar helpers in §9); on phones a week strip with the same statuses and a “Month” view - Times grouped as Morning / Afternoon / Evening (a segmented switch with counts when there are many); the chosen time continues inline (“1:30 PM — Continue”), and a “soonest time” shortcut comes from data already loaded - Keep the chosen service, duration, price, date and time visible at every step — a summary beside the calendar on wide screens, a sticky bar on phones - The code step feels like part of the salon's flow: the masked address the code went to, one large code field, “Send a new code”, “Choose another time”, and a reminder to check spam - Designed states, not error dumps: times loading, times that could not load (Try again), a time just taken by someone else (fresh times), a fully booked day (the next available day), a closed day, and online booking switched off (contact details) - Pending wording: “Request received — we'll confirm your appointment shortly.” Confirmed wording: “You're booked.” - **Imagery:** Real, coherent photography is part of the design, not an extra: the hero, the salon space, details of the work (hands, tools, colour, texture) and the storefront, all in one photographic direction. Show hair and craft, never posed stock smiles. Never present a photographed person as one of the salon's stylists: sample team cards show work, not faces, and stay labelled as samples until the owner adds real portraits. Motifs (scissor, comb, hair-texture curves) frame the photos; they do not replace them. Service photos are the owner's (added per service in the dashboard): present them as part of the menu's design, never as stock fillers. - **Avoid:** - A generic SaaS landing page look, purple gradients, glassmorphism everywhere - Invented awards, certifications, review counts or ratings - Medical or clinical styling - Hard-coded services, prices or opening hours (they come from the engine) - **Words:** call customers “clients” and bookings “appointments”. How: - **Identity first.** A short `DESIGN.md`: the concept in one sentence, a display face with character and a readable text face (both self-hosted with `@fontsource`), colour tokens with every text/background pair at 4.5:1 or better, a type and spacing scale, how motion behaves. Every value lives in one CSS file of custom properties. Two businesses in this niche with different style directions must not look like the same layout recoloured. Plain CSS, no UI kit. - **Composition.** Varied rhythm — full-bleed moments, asymmetric grids, one focal point per screen; designed for phones first, from 320 px to wide screens; keyboard-accessible with visible focus; motion of 150–600 ms with a purpose, off under `prefers-reduced-motion`. - **Engine data, never hard-coded:** services, prices, opening hours, contact details and availability (BUILD-A-SITE §3). “Open now” lines come from `getOpeningTimes`. Show each service's optional `image` in your own style when it has one, and make the services section complete with none. - **Owner-editable copy.** Declare the texts, photos, logo, brand colours and heading style the owner may change in `src/content/site.ts` (BUILD-A-SITE §2), with your copy and photos as defaults, render the page from it as text, and bake it in with the Vite plugin. - **Photos.** Free, properly licensed photographs (Unsplash or Pexels licence), at most six, downloaded into `photos/source/` and recorded in `PHOTOS.md` — never hot-linked, never a photographed person presented as staff (sample team cards show the work and say “Sample photo”; content-list images cannot have defaults, so sample cards may be text-only or share one site image). Search terms that work: “hair salon interior”, “hairdresser cutting hair close up”, “hair colour bowl brush”, “salon chair mirror”. Prepare them with `npx booking-engine photos` (BUILD-A-SITE §5): AVIF + WebP at two or three widths, `width`/`height` on every `<img>`, fixed `aspect-ratio` frames with `object-fit: cover`, the hero eager with `fetchpriority="high"`, everything else lazy. When no fitting photo exists, design the frame without one. - **The booking flow** follows BUILD-A-SITE §4 with the calendar helpers: server slots only, the business time zone, the two steps (`requestBooking`, then the code and `verifyBooking`), every error in the table, contact details when online booking is off, success only after `verifyBooking` returned `ok: true`. On a phone: the step's name always visible, the choice and price in view, 44 px targets, the right input types, inline validation, a loading state on the control that waits, a code field that accepts a pasted code, focus on each new step's heading. - **Every “Book” button always answers.** Whatever the booking section is showing — loading, the flow, online booking off, no services, a calendar that failed to load — each Book/CTA button on the page scrolls to the booking section and moves focus to its heading, so the visitor sees that state's message and the shop's contact details. Never route a CTA only through the flow component (it is not on the page in those states), and never leave a click that does nothing. Check it with online booking off as well as on. ## 3. Work efficiently The viewer's Claude plan pays for every step, so keep the session lean: - Read BUILD-A-SITE.md once; don't re-read files you wrote or explore the package. - Photos: start from the leads above or spend at most about ten minutes searching; judge candidates on one contact sheet of small thumbnails, not one by one at full size. - Screenshots: about eight in all — desktop and a 390 px phone (device emulation), downscaled to at most 1280 px wide. Don't capture very long pages at full resolution. - Don't simulate the engine's error answers to see every state: build each state from the error table and check it in the code. - `npm run build` and `npx booking-engine doctor --dist dist` once midway and once at the end; afterwards fix and rerun only what failed. ## 4. Finish - `CLAUDE.md` in the project root: the engine's boundaries (from `BOOKING_ENGINE.md`), where the design lives, and that new booking features need a new engine version, never custom database code. - Done when: `npm run build` and `npx booking-engine doctor --dist dist` pass; every field in `src/content/site.ts` is used and the page looks as designed with the defaults; the key sections show real photos (`PHOTOS.md`, AVIF/WebP with dimensions; `DESIGN.md` matches the tokens); `npm run dev` serves `/` with the preview banner and a booking flow that reaches the code step and the honest preview message, and `/admin/` shows “Connect your backend”. Stop the dev server. - End with a short summary: what you built, the design choices, and anything in the engine's documentation that was unclear or wrong.

Barbería

Cortes, degradados, arreglo de barba y afeitados, reservados rápido desde el móvil.

Build a complete, premium booking website for **{{BUSINESS_NAME}}**, a barbershop in {{CITY}}, in this empty folder. The booking system is an installed package — the **Profit Studio Booking Engine**. It owns availability, bookings, booking emails and the owner's dashboard. You design and build the public website around it, and nothing the engine provides. ## 1. Set up 1. Scaffold a Vite + React + TypeScript app **in the current folder**: `npm create vite@latest . -- --template react-ts --no-interactive`, then `npm install`. create-vite stops without an error when the folder is not empty — a `.DS_Store` or a `.claude/` folder is enough — so check that `package.json` now exists. If it does not, scaffold into a new subfolder the same way, move all of its files (dotfiles included) up into this folder without overwriting or deleting anything already here, and remove the empty subfolder. Remove the template's demo content. 2. `npm install --save-exact @profitstudio/booking-engine@2.0.0-beta.1`, then `npx booking-engine init`. 3. Read `node_modules/@profitstudio/booking-engine/docs/BUILD-A-SITE.md` once: it has every file to wire, the booking API and the error table. Open `docs/INTEGRATION.md` only at a section it names, and nothing else in the package. 4. Wire the engine as BUILD-A-SITE §1 shows, with this site's own preset as `preview.preset` — write it in `src/lib/preset.ts` and export it as `sitePreset` (BUILD-A-SITE §1) with the words “clients” and “appointments”; in `preview.business` use `{{BUSINESS_NAME}}`, the time zone `{{TIMEZONE}}` and a plausible placeholder `contact` in {{CITY}}. - Write `sitePreset` from this sample data (prices are US dollars: use the local currency at a plausible local price level; `id` "barbershop", `label` "Barbershop"): - Classic Cut · 30 min (+10 min buffer) · 40 · “Scissor or clipper cut, styled and finished with a neck shave.” - Skin Fade · 45 min (+10 min buffer) · 45 · “Tight fade blended to the skin, shaped on top, sharp line-up.” - Beard Trim & Line-up · 20 min (+5 min buffer) · 25 · “Shape, trim and a hot-towel line-up for the beard.” - Cut & Beard · 60 min (+10 min buffer) · 60 · “A full haircut and beard shape in one sitting.” - Hot Towel Shave · 40 min (+10 min buffer) · 45 · “Straight-razor shave with hot towels and a cool finish.” - Buzz Cut · 20 min (+5 min buffer) · 25 · “One length all over, cleaned up at the neck and ears.” - Kids Cut (under 12) · 30 min (+10 min buffer) · 28 · “A patient, quick cut for younger clients.” - Opening hours: Tuesday to Friday 10:00–19:00, Saturday 09:00–17:00; closed Sunday and Monday - Policies: 15-minute slot interval, at least 1 hour's notice, up to 30 days ahead, the owner confirms each request, a phone number is required; every other policy as in BUILD-A-SITE §1 The dashboard on `/admin/` mounts `<BookingAdmin engine={engine} siteUrl="/" content={siteContent} presets={[sitePreset]} />` and gets only your brand accent (light and dark) in `src/admin-theme.css`. One public page (sections and an in-page booking flow), no client-side routes. No backend yet: no Supabase project, no `supabase` commands, no `.env.local` — the site runs in preview mode with a visible “Preview — sample data, bookings are not saved” banner. ## 2. Design — the creative part Make it feel like a real, distinctive barbershop, not a template: - **Style direction:** {{STYLE_DIRECTION}} - **Audience:** Neighbourhood regulars and newcomers, mostly 18–50, who book a cut every three to five weeks — almost always on a phone, often the same day. - **Tone:** Easygoing, sharp and confident; plain-spoken and welcoming to everyone. No macho bravado, no “gentlemen's club” clichés. - **Sections:** - Hero with the shop's character and one clear “Book a chair” action, plus the soonest open time for the first service on the menu (named) when it is known - The menu: services, durations and prices loaded from the engine, readable at a glance like a board on the wall — with the owner's optional service photos (cuts, fades, beard work) shown in the site's own style when a service has one, and a complete menu without them - The barbers — placeholder names and short bios the owner will edit, clearly marked as samples (portraits come later from the owner) - The shop: the chairs, the music, the routine of a visit — what a first-timer can expect - Kind words — clearly marked as placeholder examples, never presented as real reviews - Opening hours (from the engine) and location / contact (from the engine's business contact), with directions - The booking flow - Footer with a discreet “Staff login” link to /admin/ - **Booking experience:** - Service first, then the date and time together, then details, then the email code, then confirmation — fast enough to finish standing in line for coffee - Make the soonest time obvious: a “Next open: today 4:15 PM” shortcut from data already loaded, and a week view that opens on today — on a closed day, say so and offer the next open time - Short services mean many times: group them Morning / Afternoon / Evening with counts, and keep the list scannable on a phone - There is one shared calendar: never offer “choose your barber” or show staff availability — the engine does not book per barber - Keep the chosen service, duration, price, date and time visible at every step — a summary beside the times on wide screens, a sticky bar on phones - The code step stays in the shop's voice: where the code went (masked), one large code field that accepts a pasted code, “Send a new code”, “Choose another time”, and a reminder to check spam - Designed states: times loading, times that could not load (Try again), a time just taken (fresh times), a fully booked day (the next open day), a closed day, and online booking switched off (call or message the shop) - Pending wording: “Request received — we'll confirm your chair shortly.” Confirmed wording: “You're booked. See you in the chair.” - **Imagery:** Real photography of the craft is part of the design: clippers and straight razors, the chair, the lather, the line-up, a door, window or street at dusk (no other shop's name, no barber pole, no identifiable people; if no such licensed photo exists, a designed frame such as a painted window sign) — one coherent photographic direction. Never present a photographed person as one of the shop's barbers: sample barber cards show tools or work, not faces, and stay labelled as samples until the owner adds real portraits. Graphic motifs (rules, numerals, signage lettering) frame the photos; they do not replace them. Service photos are the owner's (added per service in the dashboard): present them as part of the menu's design, never as stock fillers. - **Avoid:** - Barber-pole stripes, skulls, mustache icons and other stock barbershop clichés - A generic SaaS landing page look, purple gradients, glassmorphism - Invented awards, review counts, ratings or “best in town” claims - A “choose your barber” step or per-barber availability (not supported by the engine) - Hard-coded services, prices or opening hours (they come from the engine) - **Words:** call customers “clients” and bookings “appointments”. How: - **Identity first.** A short `DESIGN.md`: the concept in one sentence, a display face with character and a readable text face (both self-hosted with `@fontsource`), colour tokens with every text/background pair at 4.5:1 or better, a type and spacing scale, how motion behaves. Every value lives in one CSS file of custom properties. Two businesses in this niche with different style directions must not look like the same layout recoloured. Plain CSS, no UI kit. - **Composition.** Varied rhythm — full-bleed moments, asymmetric grids, one focal point per screen; designed for phones first, from 320 px to wide screens; keyboard-accessible with visible focus; motion of 150–600 ms with a purpose, off under `prefers-reduced-motion`. - **Engine data, never hard-coded:** services, prices, opening hours, contact details and availability (BUILD-A-SITE §3). “Open now” lines come from `getOpeningTimes`. Show each service's optional `image` in your own style when it has one, and make the services section complete with none. - **Owner-editable copy.** Declare the texts, photos, logo, brand colours and heading style the owner may change in `src/content/site.ts` (BUILD-A-SITE §2), with your copy and photos as defaults, render the page from it as text, and bake it in with the Vite plugin. - **Photos.** Free, properly licensed photographs (Unsplash or Pexels licence), at most six, downloaded into `photos/source/` and recorded in `PHOTOS.md` — never hot-linked, never a photographed person presented as staff (sample team cards show the work and say “Sample photo”; content-list images cannot have defaults, so sample cards may be text-only or share one site image). Free photos already checked for this niche, to start from (confirm the licence on each page; replace any): https://www.pexels.com/photo/barber-perfecting-a-fade-haircut-close-up-39559270/ (a fade being cut, close up (hero)); https://www.pexels.com/photo/vintage-barber-shop-interior-with-classic-chairs-37764947/ (a row of classic barber chairs); https://www.pexels.com/photo/customer-at-barber-16553361/ (a lathered shave in progress); https://www.pexels.com/photo/tools-at-barbershop-7697712/ (clippers and tools on a counter); https://www.pexels.com/photo/hairdresser-scissors-and-tools-10317439/ (scissors and combs); https://www.pexels.com/photo/gray-hand-tool-1319459/ (a brass shaving bowl and razors). Search terms that work: “barber fade close up”, “barbershop interior chairs”, “straight razor shave”, “barber tools clippers”. Prepare them with `npx booking-engine photos` (BUILD-A-SITE §5): AVIF + WebP at two or three widths, `width`/`height` on every `<img>`, fixed `aspect-ratio` frames with `object-fit: cover`, the hero eager with `fetchpriority="high"`, everything else lazy. When no fitting photo exists, design the frame without one. - **The booking flow** follows BUILD-A-SITE §4 with the calendar helpers: server slots only, the business time zone, the two steps (`requestBooking`, then the code and `verifyBooking`), every error in the table, contact details when online booking is off, success only after `verifyBooking` returned `ok: true`. On a phone: the step's name always visible, the choice and price in view, 44 px targets, the right input types, inline validation, a loading state on the control that waits, a code field that accepts a pasted code, focus on each new step's heading. - **Every “Book” button always answers.** Whatever the booking section is showing — loading, the flow, online booking off, no services, a calendar that failed to load — each Book/CTA button on the page scrolls to the booking section and moves focus to its heading, so the visitor sees that state's message and the shop's contact details. Never route a CTA only through the flow component (it is not on the page in those states), and never leave a click that does nothing. Check it with online booking off as well as on. ## 3. Work efficiently The viewer's Claude plan pays for every step, so keep the session lean: - Read BUILD-A-SITE.md once; don't re-read files you wrote or explore the package. - Photos: start from the leads above or spend at most about ten minutes searching; judge candidates on one contact sheet of small thumbnails, not one by one at full size. - Screenshots: about eight in all — desktop and a 390 px phone (device emulation), downscaled to at most 1280 px wide. Don't capture very long pages at full resolution. - Don't simulate the engine's error answers to see every state: build each state from the error table and check it in the code. - `npm run build` and `npx booking-engine doctor --dist dist` once midway and once at the end; afterwards fix and rerun only what failed. ## 4. Finish - `CLAUDE.md` in the project root: the engine's boundaries (from `BOOKING_ENGINE.md`), where the design lives, and that new booking features need a new engine version, never custom database code. - Done when: `npm run build` and `npx booking-engine doctor --dist dist` pass; every field in `src/content/site.ts` is used and the page looks as designed with the defaults; the key sections show real photos (`PHOTOS.md`, AVIF/WebP with dimensions; `DESIGN.md` matches the tokens); `npm run dev` serves `/` with the preview banner and a booking flow that reaches the code step and the honest preview message, and `/admin/` shows “Connect your backend”. Stop the dev server. - End with a short summary: what you built, the design choices, and anything in the engine's documentation that was unclear or wrong.

Estudio de masajes y bienestar

Masajes y tratamientos, con una experiencia de reserva tranquila.

Build a complete, premium booking website for **{{BUSINESS_NAME}}**, a massage & wellness studio in {{CITY}}, in this empty folder. The booking system is an installed package — the **Profit Studio Booking Engine**. It owns availability, bookings, booking emails and the owner's dashboard. You design and build the public website around it, and nothing the engine provides. ## 1. Set up 1. Scaffold a Vite + React + TypeScript app **in the current folder**: `npm create vite@latest . -- --template react-ts --no-interactive`, then `npm install`. create-vite stops without an error when the folder is not empty — a `.DS_Store` or a `.claude/` folder is enough — so check that `package.json` now exists. If it does not, scaffold into a new subfolder the same way, move all of its files (dotfiles included) up into this folder without overwriting or deleting anything already here, and remove the empty subfolder. Remove the template's demo content. 2. `npm install --save-exact @profitstudio/booking-engine@2.0.0-beta.1`, then `npx booking-engine init`. 3. Read `node_modules/@profitstudio/booking-engine/docs/BUILD-A-SITE.md` once: it has every file to wire, the booking API and the error table. Open `docs/INTEGRATION.md` only at a section it names, and nothing else in the package. 4. Wire the engine as BUILD-A-SITE §1 shows, with this site's own preset as `preview.preset` — write it in `src/lib/preset.ts` and export it as `sitePreset` (BUILD-A-SITE §1) with the words “guests” and “sessions”; in `preview.business` use `{{BUSINESS_NAME}}`, the time zone `{{TIMEZONE}}` and a plausible placeholder `contact` in {{CITY}}. - Write `sitePreset` from this sample data (prices are US dollars: use the local currency at a plausible local price level; `id` "massage-studio", `label` "Massage & Wellness Studio"): - Swedish Massage — 60 min · 60 min (+15 min buffer) · 95 · “Long, flowing strokes to ease tension and settle the mind.” - Swedish Massage — 90 min · 90 min (+15 min buffer) · 135 · “The full-body Swedish session with time for slower, deeper work.” - Deep Tissue — 60 min · 60 min (+15 min buffer) · 105 · “Firm, focused pressure for tight shoulders, back and legs.” - Deep Tissue — 90 min · 90 min (+15 min buffer) · 150 · “Unhurried deep work on the areas you choose.” - Hot Stone — 75 min · 75 min (+20 min buffer) · 125 · “Warm basalt stones and long strokes to release and soften.” - Pregnancy Massage — 60 min · 60 min (+15 min buffer) · 100 · “Side-lying comfort and gentle pressure, from the second trimester.” - Reflexology — 45 min · 45 min (+15 min buffer) · 70 · “Pressure-point work on the feet in a reclined chair.” - Opening hours: Monday to Friday 10:00–20:00, Saturday 09:00–17:00, Sunday 10:00–16:00 - Policies: 15-minute slot interval, at least 4 hours' notice, up to 60 days ahead, the owner confirms each request, a phone number is required; every other policy as in BUILD-A-SITE §1 The dashboard on `/admin/` mounts `<BookingAdmin engine={engine} siteUrl="/" content={siteContent} presets={[sitePreset]} />` and gets only your brand accent (light and dark) in `src/admin-theme.css`. One public page (sections and an in-page booking flow), no client-side routes. No backend yet: no Supabase project, no `supabase` commands, no `.env.local` — the site runs in preview mode with a visible “Preview — sample data, bookings are not saved” banner. ## 2. Design — the creative part Make it feel like a real, distinctive massage & wellness studio, not a template: - **Style direction:** {{STYLE_DIRECTION}} - **Audience:** Adults 25–65 looking for relief from everyday tension or simply an hour of quiet — often booking in the evening on a phone, sometimes for the first time. - **Tone:** Calm, warm and reassuring; clear and practical. Never clinical, never mystical, and never promise health outcomes. - **Sections:** - Hero that slows the visitor down, with one clear “Book a session” action - Treatments loaded from the engine — each length is its own service (e.g. 60 and 90 minutes), shown as a calm, readable list with durations and prices — with the owner's optional service photos in the site's own style when a service has one, and complete without them - What to expect: arriving, the room, comfort and pressure, privacy — written for a first-timer - The therapists — placeholder names and short bios the owner will edit, clearly marked as samples - Questions (what to wear, arriving early, cancelling) as plain text the owner can edit - Opening hours (from the engine) and location / contact (from the engine's business contact) - The booking flow - Footer with a discreet “Staff login” link to /admin/ - **Booking experience:** - Treatment and length first, then the date and time together, then details, then the email code, then confirmation - A calm calendar: the next open days first, times grouped Morning / Afternoon / Evening; never a countdown or scarcity pressure - There is one shared calendar: never offer “choose your therapist” or show per-therapist availability - The note field is optional and invites preferences (pressure, areas to avoid) — never ask for medical history or health details in the form - Keep the chosen treatment, length, price, date and time visible at every step - The code step is gentle and clear: where the code went (masked), one large code field that accepts a pasted code, “Send a new code”, “Choose another time”, a reminder to check spam - Designed states: loading, could not load (Try again), a time just taken, a fully booked day (the next open day), a closed day, online booking switched off (call or email the studio) - Pending wording: “Request received — we'll confirm your session shortly.” Confirmed wording: “Your session is booked.” - **Imagery:** Quiet, tactile photography: hands at work, linen, warm stones, oil, soft light across a treatment room — one coherent direction, little colour, lots of air. Never present a photographed person as one of the studio's therapists: sample therapist cards show the room or hands, not faces, and stay labelled as samples. No before/after imagery. Service photos are the owner's (added per service in the dashboard): present them as part of the design, never as stock fillers. - **Avoid:** - Spa clichés: orchids, Buddha statues, stacked stones, lotus icons - Medical claims, diagnoses, “cures” or before/after promises - Countdown timers, scarcity pressure or pushy upsells - A “choose your therapist” step or per-therapist availability (not supported by the engine) - Hard-coded services, prices or opening hours (they come from the engine) - **Words:** call customers “guests” and bookings “sessions”. How: - **Identity first.** A short `DESIGN.md`: the concept in one sentence, a display face with character and a readable text face (both self-hosted with `@fontsource`), colour tokens with every text/background pair at 4.5:1 or better, a type and spacing scale, how motion behaves. Every value lives in one CSS file of custom properties. Two businesses in this niche with different style directions must not look like the same layout recoloured. Plain CSS, no UI kit. - **Composition.** Varied rhythm — full-bleed moments, asymmetric grids, one focal point per screen; designed for phones first, from 320 px to wide screens; keyboard-accessible with visible focus; motion of 150–600 ms with a purpose, off under `prefers-reduced-motion`. - **Engine data, never hard-coded:** services, prices, opening hours, contact details and availability (BUILD-A-SITE §3). “Open now” lines come from `getOpeningTimes`. Show each service's optional `image` in your own style when it has one, and make the services section complete with none. - **Owner-editable copy.** Declare the texts, photos, logo, brand colours and heading style the owner may change in `src/content/site.ts` (BUILD-A-SITE §2), with your copy and photos as defaults, render the page from it as text, and bake it in with the Vite plugin. - **Photos.** Free, properly licensed photographs (Unsplash or Pexels licence), at most six, downloaded into `photos/source/` and recorded in `PHOTOS.md` — never hot-linked, never a photographed person presented as staff (sample team cards show the work and say “Sample photo”; content-list images cannot have defaults, so sample cards may be text-only or share one site image). Free photos already checked for this niche, to start from (confirm the licence on each page; replace any): https://unsplash.com/photos/massage-on-leg-with-white-towel-yBLLzNcA6GU (hands at work over a white towel (hero)); https://www.pexels.com/photo/settee-by-the-window-6628520/ (a treatment table by a tall window); https://unsplash.com/photos/hands-massaging-a-persons-forearm-with-gentle-pressure-YBfzGCJjLuI (hands working on a forearm). Search terms that work: “massage hands towel”, “treatment room window”, “spa linen stones”. Prepare them with `npx booking-engine photos` (BUILD-A-SITE §5): AVIF + WebP at two or three widths, `width`/`height` on every `<img>`, fixed `aspect-ratio` frames with `object-fit: cover`, the hero eager with `fetchpriority="high"`, everything else lazy. When no fitting photo exists, design the frame without one. - **The booking flow** follows BUILD-A-SITE §4 with the calendar helpers: server slots only, the business time zone, the two steps (`requestBooking`, then the code and `verifyBooking`), every error in the table, contact details when online booking is off, success only after `verifyBooking` returned `ok: true`. On a phone: the step's name always visible, the choice and price in view, 44 px targets, the right input types, inline validation, a loading state on the control that waits, a code field that accepts a pasted code, focus on each new step's heading. - **Every “Book” button always answers.** Whatever the booking section is showing — loading, the flow, online booking off, no services, a calendar that failed to load — each Book/CTA button on the page scrolls to the booking section and moves focus to its heading, so the visitor sees that state's message and the shop's contact details. Never route a CTA only through the flow component (it is not on the page in those states), and never leave a click that does nothing. Check it with online booking off as well as on. ## 3. Work efficiently The viewer's Claude plan pays for every step, so keep the session lean: - Read BUILD-A-SITE.md once; don't re-read files you wrote or explore the package. - Photos: start from the leads above or spend at most about ten minutes searching; judge candidates on one contact sheet of small thumbnails, not one by one at full size. - Screenshots: about eight in all — desktop and a 390 px phone (device emulation), downscaled to at most 1280 px wide. Don't capture very long pages at full resolution. - Don't simulate the engine's error answers to see every state: build each state from the error table and check it in the code. - `npm run build` and `npx booking-engine doctor --dist dist` once midway and once at the end; afterwards fix and rerun only what failed. ## 4. Finish - `CLAUDE.md` in the project root: the engine's boundaries (from `BOOKING_ENGINE.md`), where the design lives, and that new booking features need a new engine version, never custom database code. - Done when: `npm run build` and `npx booking-engine doctor --dist dist` pass; every field in `src/content/site.ts` is used and the page looks as designed with the defaults; the key sections show real photos (`PHOTOS.md`, AVIF/WebP with dimensions; `DESIGN.md` matches the tokens); `npm run dev` serves `/` with the preview banner and a booking flow that reaches the code step and the honest preview message, and `/admin/` shows “Connect your backend”. Stop the dev server. - End with a short summary: what you built, the design choices, and anything in the engine's documentation that was unclear or wrong.

Personaliza y copia tu prompt

Tu parte.

Abre Customize Prompt en el prompt de arriba Introduce el nombre y la ciudad de tu negocio: la zona horaria empieza siendo la tuya, así que cámbiala solo si el negocio está en otro lugar Elige una dirección de estilo: cada una le da a tu sitio web un aspecto diferente Copia el prompt: se lo envías a Claude en el paso 2

Warm editorial — espresso, cobre y crema, una serif elegante y maquetaciones de estilo revista

Modern minimal — casi blanco y gris carbón con un único acento decidido y una cuadrícula estricta

Bold urban — negro profundo, grises hormigón y un acento eléctrico, con un contraste fuerte

Soft natural — salvia, arena y rosa empolvado, tipografía redondeada, tranquilo y aireado

Heritage modern — verde botella, sangre de toro y latón sobre papel cálido, clásico pero nunca teatral

Industrial clean — negro, acero y grises hormigón con un color de señal y números grandes

Neighbourhood warm — crema, terracota y tinta, tipografía amable y espaciado relajado

Quiet Nordic — avena, piedra y salvia tenue sobre blanco cálido, márgenes amplios y movimiento suave

Warm earth — arcilla, terracota y oliva oscuro, titulares redondeados y formas orgánicas

Night calm — azul tinta profundo y tonos cálidos de vela, tenue e íntimo

El prompt instala el Booking Engine exactamente en la versión 2.0.0-beta.1, la versión con la que se probó esta guía. No la cambies a latest.

Genera tu sitio web con Claude Code

Abre una carpeta vacía

Tu parte.

Claude Desktop Code Local

Crea una carpeta nueva y vacía para tu sitio web, por ejemplo en Documentos Inicia una sesión Local y elige esa carpeta Si Claude Desktop lo pide, confía en la carpeta

Envía tu prompt

Parte de Claude Code: tú apruebas sus acciones y esperas.

Pega el prompt que copiaste en el paso 1 y envíalo Haz clic en Allow cuando Claude pida ejecutar un comando Déjalo trabajar: un build completo es una sesión larga, así que mantenla abierta

Crea el proyecto del sitio web e instala el Booking Engine

Diseña el sitio: tipografías, colores, maquetación y textos para tu negocio

Busca fotos gratuitas con licencia y las prepara para la web

Crea el flujo de reserva y la página del panel del propietario

Lo comprueba todo con npm run build y npx booking-engine doctor

Si Claude se detiene porque alcanzaste un límite de uso, espera a que se restablezca y luego escribe continue en la misma sesión.

Mira tu sitio web

Parte de Claude Code, luego la tuya: él inicia la vista previa y tú la revisas.

Muéstrame mi sitio web

Inicia tu sitio web en tu ordenador y te da su dirección.

Start the website's dev server with npm run dev and open it in the Browser pane. Then give me its local address. Don't change any files.

Mira la vista previa en el Browser pane de Claude Desktop, o abre en tu navegador la dirección que te da Claude Revisa el diseño en una ventana ancha y en una estrecha Haz clic en un botón Book: se abre el flujo de reserva y llega al paso que pide un código por email Abre /admin/: añádelo a la dirección o pídele a Claude que lo abra; muestra Connect your backend

El banner de arriba dice Preview: son datos de ejemplo y todavía no se guarda ninguna reserva. ¿Quieres cambios? Pídeselos a Claude en la misma sesión antes de continuar.

Conecta Supabase y Resend

Crea tu proyecto de Supabase

Tu parte: en tu cuenta de Supabase.

Este paso tiene tres partes: Supabase, luego el email y luego un prompt que lo conecta todo. Los valores que introduces se guardan en esta guía y se reutilizan en el paso 5, así que escribes cada uno una sola vez.

Abrir el panel de Supabase

https://supabase.com/dashboard

Haz clic en New project y elige una región cercana a tu negocio y el plan Free Guarda la contraseña de la base de datos en tu gestor de contraseñas; nunca se la envíes a Claude Cuando el proyecto esté listo, haz clic en Connect y pega abajo la Project URL y la Publishable key

Crea tu acceso al panel

Tu parte: en tu cuenta de Supabase.

Supabase Authentication Users

Haz clic en Add user y luego en Create new user Introduce tu email y una contraseña segura Deja marcada la opción Auto Confirm User y crea el usuario

Supabase Authentication Sign In / Providers

Desactiva Allow new users to sign up y guarda: solo tú inicias sesión en el panel

Inicia sesión en la Supabase CLI

Tu parte: una vez, antes de conectar.

Haz clic en Terminal en la barra de título de tu sesión Ejecuta el comando de abajo Aprueba el inicio de sesión en la ventana del navegador que se abre

npx supabase@2 login

Si Claude te pide que vincules el proyecto tú mismo, ejecuta aquí el comando que te da y escribe la contraseña de tu base de datos en la Terminal, nunca en el chat.

Verifica tu dominio de envío

Tu parte: en Resend y en el DNS de tu dominio.

Los emails de reserva se envían desde tu propio dominio: el mismo que usará tu sitio web en el paso 5. ¿Aún no tienes dominio? Compra uno en Hostinger y luego vuelve:

Hostinger Domains

Abrir los dominios de Resend

https://resend.com/domains

Haz clic en Add domain e introduce el dominio de envío que aparece arriba Elige la región más cercana a tus clientes Deja abierta la página con los registros DNS

Hostinger Domains DNS / Nameservers

Elige tu dominio y añade cada registro que muestra Resend, con el mismo tipo y valor De vuelta en Resend, haz clic en Verify DNS records

La verificación suele tardar menos de 15 minutos y puede tardar hasta 72 horas. Sigue con los siguientes pasos mientras esperas. ¿Tu dominio se gestiona en otro sitio? Añade allí los mismos registros y conserva tus registros de email existentes.

Añade tus secretos de email a Supabase

Tu parte: la clave va solo en Supabase, nunca en el chat.

En Resend, abre API Keys y haz clic en Create API key Elige Sending access y tu dominio verificado, y luego copia la clave: Resend solo la muestra una vez En Supabase, abre Edge Functions, luego Secrets, y añade estos dos

RESEND_API_KEY

Mantén en secreto la clave de Resend

Pégala solo en los secretos de Edge Functions de Supabase. Nunca se la envíes a Claude, nunca la pongas en un archivo del sitio web ni en un prompt, y nunca la añadas a Hostinger.

Pide a Claude que lo conecte todo

Parte de Claude Code: se detiene cada vez que algo te toca a ti.

En la misma sesión de Claude, copia este prompt y envíalo:

Claude pregunta antes de cada acción: haz clic en Allow. Se detiene cuando te toca a ti.

Has terminado cuando Claude dice Connected. Los emails de reserva empiezan a enviarse cuando Resend muestra tu dominio como Verified: el email de prueba del paso 4 lo confirma.

Configura tu panel y prueba una reserva

Abre tu panel

Parte de Claude Code, luego la tuya: él inicia el sitio web y tú inicias sesión.

Inicia mi sitio web conectado

Inicia tu sitio web, ya conectado a Supabase, y te da las direcciones del sitio y del panel.

Stop any dev server that is still running, so the new .env.local is read. Then start the website with npm run dev, open /admin/ in the Browser pane, and give me two addresses: the website and its /admin/ dashboard. Don't change any files.

Abre el panel e inicia sesión con el acceso que creaste en el paso 3. Tu sitio web todavía se ejecuta en tu ordenador, pero todo aquí ya es real: el panel, las reservas y los emails usan tu proyecto de Supabase, y tu sitio web en vivo del paso 5 usa los mismos datos.

Termina la configuración

Tu parte: en el panel.

Elige primero adónde van las alertas de nuevas solicitudes

Sin una dirección para las alertas, nadie se entera de las nuevas solicitudes y no se puede activar la reserva online.

Sigue Finish setting up en la parte superior del panel: te guía por los datos de tu negocio, los servicios, el horario de apertura y el email En Email & online booking, configura Send new-request alerts to con tu propia bandeja de entrada y luego haz clic en Send test email y comprueba que llegó

Antes de activar las reservas, haz clic en cada botón Book de tu sitio web: debería saltar a la sección de reservas y mostrar tus datos de contacto. Un botón que no hace nada es un error: pide a Claude que lo arregle.

Activa la reserva online

Reserva una cita de prueba

Tu parte: como cliente y luego como propietario.

En tu sitio web, reserva un servicio con tu propia dirección de email. Luego marca cada punto a medida que lo veas ocurrir:

Llegó el código de 6 dígitos y el sitio indicó que se recibió tu solicitud

La alerta de nueva solicitud llegó a tu dirección de alertas

Hiciste clic en Confirm request en el panel y llegó el email de confirmación

Ese mismo horario ya no se ofrece en tu sitio web

¿No llega ningún email? Revisa primero el spam y luego abre Email & online booking en el panel: muestra el estado de cada email y qué hay que corregir.

Cambia los textos y las fotos de tu sitio web

Tu parte: en el panel, sin código.

Abre Website en el panel Cambia el titular principal o la foto principal Haz clic en Preview para revisarlo y luego en Publish Actualiza tu sitio web: el cambio ya está ahí

Claude diseñó el sitio; el panel edita los textos, las fotos y los colores de marca que hizo editables. Para una sección nueva o una maquetación diferente, pídeselo a Claude.

Despliega en Hostinger

Crea un repositorio privado en GitHub

Tu parte: en tu cuenta de GitHub.

Tu sitio web funciona en tu ordenador. Ahora se publica: GitHub guarda el código y Hostinger lo compila y lo sirve, con los mismos datos de Supabase que acabas de probar.

Crear repositorio en GitHub

https://github.com/new

Ponle el nombre de tu negocio y elige Private Deja desactivados README, .gitignore y license, para que el repositorio quede vacío Haz clic en Create repository y copia su dirección

Sube tu sitio web a GitHub

Parte de Claude Code: tú apruebas el push.

Sube mi sitio web a GitHub

Comprueba que no se incluya ningún secreto, hace commit de tu sitio web y lo sube a tu nuevo repositorio.

Put this website on GitHub at {{REPOSITORY_URL}}, on the main branch. Stop the dev server first. Before committing, check that .gitignore keeps node_modules, dist, .env, .env.local and supabase/.temp/ out of Git, and run npx booking-engine doctor. Show me the list of files you will commit and make sure no secret, key or password is in any of them. Then initialise Git if needed, commit everything with a clear message and push it to main. Never push to any other repository. If GitHub needs me to sign in, tell me exactly what to do, and never ask me to paste a password or token into the chat. When it's done, tell me the commit you pushed.

La dirección de tu repositorio

https://github.com/your-name/your-booking-website

Crea tu Web App

Tu parte: en Hostinger. ¿Aún no tienes hosting? Consigue un plan en Requisitos.

Hostinger Websites Create site Web App

Si Hostinger te ofrece elegir dominio, elige tu propio dominio; si no, tu app empieza en un dominio temporal Selecciona Import Git Repository Autoriza GitHub y selecciona el repositorio que Claude acaba de subir

Configura y despliega

Tu parte: en Hostinger.

Mantén la configuración de Vite que detecta Hostinger Elige Node.js 22 o posterior Asegúrate de que el comando de build sea npm run build y el directorio de salida sea dist

Antes de desplegar, busca Environment variables en Review build settings, haz clic en Edit y añade estas dos: tus valores del paso 3, listos para copiar. Van integrados en el sitio web, así que cambiar uno más adelante requiere volver a desplegar.

Solo valores públicos

Nunca añadas aquí la Secret key de Supabase ni la clave de Resend. Todo lo que empieza por VITE_ es visible en el navegador, y tus secretos de email se quedan en Supabase.

Haz clic en Finish, luego en Deploy, y espera a que termine el build

Si el build se detiene y nombra una variable, corrige el valor de esa variable en Hostinger y vuelve a desplegar.

Añade tu dirección en vivo a las alertas del propietario

Parte de Claude Code.

Verifica tu sitio web en vivo

Tu parte.

Abre tu dominio: aparece el candado y no hay banner Preview Revisa tus servicios, precios y horario de apertura En tu móvil, reserva una cita de prueba e introduce el código Abre /admin/ en tu sitio en vivo, inicia sesión y confirma la solicitud Comprueba que llegaron tanto la alerta como el email de confirmación

A partir de ahora, cambia los servicios, los precios, el horario y los textos y fotos de tu sitio web en el panel: se publican al instante. Para cambios de diseño o de código, pídeselos a Claude y aprueba el push: Hostinger vuelve a compilar tu sitio en cada push a main. Los buscadores ven un nuevo título o descripción de página después del siguiente build.