Claude Code로 프리미엄 예약 웹사이트 만들기
미용실, 바버샵, 마사지 스튜디오를 위한 단 하나뿐인 예약 웹사이트를 만듭니다. 실제 예약, 예약 이메일, 사장님 대시보드까지 갖췄습니다.
로드맵과 자료
준비물
Claude Desktop
Claude Code가 데스크톱 앱에서 웹사이트를 만듭니다. 전체 빌드는 긴 세션이므로 여유가 있는 유료 Claude 플랜를 사용하세요.
Claude Desktop 다운로드하기
https://claude.ai/download
Node.js
LTS 버전을 다운로드하세요. Claude가 이것으로 웹사이트를 빌드하고 점검합니다.
Node.js 다운로드하기
https://nodejs.org/en/download
GitHub 계정
무료입니다. 웹사이트 코드가 여기에 저장되고, Hostinger가 여기서 배포합니다.
GitHub 계정 만들기
https://github.com/signup
Supabase 계정
Free 플랜이면 충분합니다. 활성 프로젝트는 2개까지 허용되므로, 이미 2개가 있다면 쓰지 않는 하나를 일시 중지하세요. 서비스, 영업시간, 예약, 대시보드 로그인 정보를 저장합니다.
Supabase 계정 만들기
https://supabase.link/r4gdwhi
Resend 계정
Free 플랜은 하루 100통, 한 달 3,000통의 이메일을 보냅니다. 예약 한 건마다 코드, 요청 접수, 내게 오는 알림, 확정 이메일 등 여러 통이 발송됩니다.
Resend 계정 만들기
https://resend.com/signup
내 도메인
웹사이트가 이 도메인에서 운영되고, 예약 이메일도 이 도메인에서 발송됩니다. Gmail 같은 무료 주소로는 보낼 수 없습니다. Hostinger 플랜과 함께 도메인을 구매하나요? 그렇다면 3단계 전에 플랜을 준비하세요.
Hostinger 호스팅
웹사이트를 공개하는 5단계에서 호스팅이 필요합니다.
Hostinger 플랜 선택하기
Business(Unlimited) 플랜이나 Cloud 플랜을 사용하세요. Node.js Web Apps는 이 플랜에서만 실행되며 Business는 최대 5개, Cloud는 10개입니다.
예약 비즈니스 선택하기
비즈니스 유형 선택하기
내가 할 일. Booking Engine은 세 가지 모두 같습니다 — 디자인, 문구, 샘플 서비스가 선택한 업종에 맞춰 만들어집니다.
어떤 비즈니스인가요?
미용실
커트, 염색, 스타일링. 엔진에 준비된 미용실 서비스를 사용합니다.
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.
바버샵
커트, 페이드, 수염 정리, 면도를 휴대폰으로 빠르게 예약합니다.
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.
마사지 & 웰니스 스튜디오
마사지와 케어를 차분한 예약 경험으로 제공합니다.
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.
프롬프트 맞춤 설정 후 복사하기
내가 할 일.
위 프롬프트에서 Customize Prompt 열기 비즈니스 이름과 도시 입력하기 — 시간대는 처음에 내 시간대로 설정되어 있으니, 비즈니스가 다른 곳에 있을 때만 바꾸세요 스타일 방향 고르기 — 스타일마다 웹사이트의 분위기가 달라집니다 프롬프트 복사하기 — 2단계에서 Claude에게 보냅니다
Warm editorial — 에스프레소, 코퍼, 크림 색상에 우아한 세리프체와 잡지 같은 레이아웃
Modern minimal — 흰색에 가까운 색과 차콜에 존재감 있는 포인트 컬러 하나, 엄격한 그리드
Bold urban — 깊은 블랙, 콘크리트 그레이, 강렬한 포인트 컬러 하나에 강한 대비
Soft natural — 세이지, 샌드, 블러시 색상에 둥근 서체, 차분하고 산뜻한 느낌
Heritage modern — 따뜻한 종이 위의 보틀 그린, 옥스블러드, 황동색, 클래식하지만 결코 과장되지 않음
Industrial clean — 블랙, 스틸, 콘크리트 그레이에 시그널 컬러 하나와 큰 숫자
Neighbourhood warm — 크림, 테라코타, 잉크 색상에 친근한 서체와 여유로운 간격
Quiet Nordic — 따뜻한 흰색 위의 오트, 스톤, 부드러운 세이지, 넓은 여백과 은은한 움직임
Warm earth — 클레이, 테라코타, 짙은 올리브 색상에 둥근 헤드라인과 유기적인 형태
Night calm — 깊은 잉크 블루와 따뜻한 촛불 톤, 어둑하고 아늑한 분위기
프롬프트는 이 가이드에서 테스트한 버전인 2.0.0-beta.1 버전의 Booking Engine을 정확히 설치합니다. latest로 바꾸지 마세요.
Claude Code로 웹사이트 생성하기
빈 폴더 열기
내가 할 일.
Claude Desktop Code Local
Documents 등에 웹사이트용 새 빈 폴더 만들기 Local 세션을 시작하고 그 폴더 선택하기 Claude Desktop이 물으면 폴더를 신뢰하기
프롬프트 보내기
Claude Code가 할 일 — 나는 작업을 승인하고 기다립니다.
1단계에서 복사한 프롬프트를 붙여 넣고 보내기 Claude가 명령 실행을 요청하면 Allow 클릭하기 작업하도록 두기 — 전체 빌드는 긴 세션이므로 열어 두세요
웹사이트 프로젝트를 만들고 Booking Engine을 설치합니다
사이트를 디자인합니다: 내 비즈니스에 맞춘 폰트, 색상, 레이아웃, 문구
무료로 사용할 수 있는 라이선스 사진을 찾아 웹용으로 준비합니다
예약 흐름과 사장님 대시보드 페이지를 만듭니다
npm run build와 npx booking-engine doctor로 모든 것을 점검합니다
사용량 한도에 도달해 Claude가 멈추면, 한도가 초기화될 때까지 기다린 뒤 같은 세션에서 continue를 입력하세요.
웹사이트 확인하기
Claude Code가 할 일, 그다음 내가 할 일 — Claude가 미리보기를 시작하고, 나는 확인합니다.
내 웹사이트 보여 주기
내 컴퓨터에서 웹사이트를 실행하고 주소를 알려 줍니다.
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.
Claude Desktop의 Browser pane에서 미리보기를 보거나, Claude가 알려 준 주소를 브라우저에서 열기 넓은 창과 좁은 창에서 디자인 확인하기 Book 버튼 클릭하기: 예약 흐름이 열리고 이메일 코드를 묻는 단계까지 진행됩니다 /admin/ 열기 — 주소 끝에 붙이거나 Claude에게 열어 달라고 요청: Connect your backend가 표시됩니다
상단 배너에 Preview라고 표시됩니다: 샘플 데이터이며, 아직 예약은 저장되지 않습니다. 바꾸고 싶은 부분이 있나요? 다음으로 넘어가기 전에 같은 세션에서 Claude에게 요청하세요.
Supabase와 Resend 연결하기
Supabase 프로젝트 만들기
내가 할 일 — 내 Supabase 계정에서.
이 단계는 세 부분으로 나뉩니다. Supabase, 그다음 이메일, 마지막으로 모든 것을 연결하는 프롬프트 하나입니다. 입력한 값은 이 가이드에 저장되고 5단계에서 다시 사용되므로, 각 값은 한 번만 입력하면 됩니다.
Supabase 대시보드 열기
https://supabase.com/dashboard
New project를 클릭하고, 비즈니스와 가까운 지역과 Free 플랜 선택하기 데이터베이스 비밀번호를 비밀번호 관리자에 저장하기 — Claude에게는 절대 보내지 마세요 프로젝트가 준비되면 Connect를 클릭하고 Project URL과 Publishable key를 아래에 붙여넣기
대시보드 로그인 만들기
내가 할 일 — 내 Supabase 계정에서.
Supabase Authentication Users
Add user를 클릭한 다음 Create new user 클릭하기 이메일과 강력한 비밀번호 입력하기 Auto Confirm User는 체크된 상태로 두고 사용자 만들기
Supabase Authentication Sign In / Providers
Allow new users to sign up을 끄고 저장하기 — 대시보드에는 나만 로그인합니다
Supabase CLI에 로그인하기
내가 할 일 — 연결하기 전에 한 번만.
세션 제목 표시줄의 Terminal 클릭하기 아래 명령 실행하기 열린 브라우저 창에서 로그인 승인하기
npx supabase@2 login
Claude가 프로젝트 연결을 직접 하라고 하면, 알려 준 명령을 여기서 실행하고 데이터베이스 비밀번호를 Terminal에 입력하세요 — 채팅에는 절대 입력하지 마세요.
발신 도메인 인증하기
내가 할 일 — Resend와 내 도메인의 DNS에서.
예약 이메일은 내 도메인에서 발송됩니다 — 5단계에서 웹사이트에 사용할 바로 그 도메인입니다. 아직 도메인이 없나요? Hostinger에서 구입한 뒤 돌아오세요:
Hostinger Domains
Resend Domains 열기
https://resend.com/domains
Add domain을 클릭하고 위에 표시된 발신 도메인 입력하기 고객과 가장 가까운 지역 선택하기 DNS 레코드가 표시된 페이지를 열어 두기
Hostinger Domains DNS / Nameservers
내 도메인을 선택하고, Resend에 표시된 레코드를 같은 유형과 값으로 하나씩 추가하기 Resend로 돌아가 Verify DNS records 클릭하기
인증은 보통 15분 안에 끝나지만, 최대 72시간까지 걸릴 수 있습니다. 기다리는 동안 다음 단계를 계속 진행하세요. 도메인을 다른 곳에서 관리하나요? 그곳에 같은 레코드를 추가하고, 기존 이메일 레코드는 그대로 두세요.
이메일 비밀 값을 Supabase에 추가하기
내가 할 일 — 키는 Supabase에만 넣고, 채팅에는 절대 넣지 않습니다.
Resend에서 API Keys를 열고 Create API key 클릭하기 Sending access와 인증된 도메인을 선택한 뒤 키 복사하기 — Resend는 키를 한 번만 보여 줍니다 Supabase에서 Edge Functions, Secrets를 차례로 열고 다음 두 항목 추가하기
RESEND_API_KEY
Resend 키는 비밀로 유지하기
Supabase의 Edge Function 비밀 값에만 붙여 넣으세요. Claude에게 보내거나, 웹사이트 파일이나 프롬프트에 넣거나, Hostinger에 추가하지 마세요.
Claude에게 전체 연결 요청하기
Claude Code가 할 일 — 내가 해야 할 일이 있으면 그때마다 멈춥니다.
같은 Claude 세션에서 이 프롬프트를 복사해 보내세요:
Claude는 작업할 때마다 먼저 물어봅니다 — Allow를 클릭하세요. 내 차례가 되면 Claude가 멈춥니다.
Claude가 Connected라고 하면 완료입니다. 예약 이메일은 Resend에 내 도메인이 Verified로 표시되면 발송되기 시작합니다 — 4단계의 테스트 이메일로 확인할 수 있습니다.
대시보드 설정 및 예약 테스트하기
대시보드 열기
Claude Code가 할 일, 그다음 내가 할 일 — Claude가 웹사이트를 시작하고, 나는 로그인합니다.
연결된 내 웹사이트 실행하기
Supabase에 연결된 웹사이트를 실행하고, 사이트와 대시보드 주소를 알려 줍니다.
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.
대시보드를 열고 3단계에서 만든 로그인 정보로 로그인하세요. 웹사이트는 아직 내 컴퓨터에서 실행되지만, 여기 있는 모든 것은 이미 실제입니다. 대시보드, 예약, 이메일은 내 Supabase 프로젝트를 사용하고, 5단계의 라이브 웹사이트도 같은 데이터를 사용합니다.
설정 마무리하기
내가 할 일 — 대시보드에서.
먼저 새 요청 알림을 받을 곳 정하기
알림 주소가 없으면 새 요청을 아무도 알 수 없고, 온라인 예약도 켤 수 없습니다.
대시보드 상단의 Finish setting up 따라가기 — 비즈니스 정보, 서비스, 영업시간, 이메일 설정을 차례로 안내합니다 Email & online booking에서 Send new-request alerts to를 내 받은편지함으로 설정한 뒤, Send test email을 클릭하고 도착했는지 확인하기
예약을 켜기 전에 웹사이트의 Book 버튼을 하나씩 모두 클릭해 보세요: 예약 섹션으로 이동하고 연락처 정보가 보여야 합니다. 아무 반응이 없는 버튼은 버그입니다 — Claude에게 수정을 요청하세요.
온라인 예약 켜기
테스트 예약하기
내가 할 일 — 먼저 고객으로, 그다음 사장님으로.
내 웹사이트에서 내 이메일 주소로 서비스를 예약하세요. 그런 다음 각 항목이 실제로 일어나는 것을 확인할 때마다 체크하세요:
6자리 코드가 도착했고, 요청이 접수되었다고 사이트에 표시됨
새 요청 알림이 알림 주소로 도착함
대시보드에서 Confirm request를 클릭했고, 확인 이메일이 도착함
같은 시간이 더 이상 웹사이트에서 예약 가능한 시간으로 표시되지 않음
이메일이 오지 않나요? 먼저 스팸함을 확인한 다음, 대시보드에서 Email & online booking을 여세요: 각 이메일의 상태와 고칠 점이 표시됩니다.
웹사이트 문구와 사진 바꾸기
내가 할 일 — 대시보드에서, 코드 없이.
대시보드에서 Website 열기 메인 헤드라인이나 메인 사진 바꾸기 Preview를 클릭해 확인한 다음 Publish 클릭하기 웹사이트 새로고침하기 — 변경 사항이 반영되어 있습니다
사이트는 Claude가 디자인했고, 대시보드에서는 Claude가 편집 가능하게 만든 문구, 사진, 브랜드 색상을 수정합니다. 새 섹션이나 다른 레이아웃이 필요하면 Claude에게 요청하세요.
Hostinger에 배포하기
비공개 GitHub 저장소 만들기
내가 할 일 — 내 GitHub 계정에서.
웹사이트가 내 컴퓨터에서 작동합니다. 이제 온라인에 공개할 차례입니다. GitHub은 코드를 보관하고, Hostinger는 웹사이트를 빌드해 제공합니다 — 방금 테스트한 것과 같은 Supabase 데이터를 사용합니다.
GitHub 저장소 만들기
https://github.com/new
비즈니스 이름으로 저장소 이름을 정하고 Private 선택하기 README, .gitignore, license는 끈 상태로 두어 저장소를 비워 두기 Create repository를 클릭하고 저장소 주소 복사하기
웹사이트를 GitHub에 푸시하기
Claude Code가 할 일 — 나는 푸시를 승인합니다.
내 웹사이트를 GitHub에 푸시하기
비밀 값이 포함되지 않았는지 확인한 뒤, 웹사이트를 커밋하고 새 저장소에 푸시합니다.
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.
내 저장소 주소
https://github.com/your-name/your-booking-website
Web App 만들기
내가 할 일 — Hostinger에서. 아직 호스팅이 없나요? 준비물에서 플랜을 준비하세요.
Hostinger Websites Create site Web App
Hostinger에서 도메인을 선택할 수 있다면 내 도메인을 고르세요. 그렇지 않으면 앱이 임시 도메인에서 시작됩니다 Import Git Repository 선택하기 GitHub를 승인하고 Claude가 방금 푸시한 저장소 선택하기
설정 및 배포하기
내가 할 일 — Hostinger에서.
Hostinger가 감지한 Vite 설정은 그대로 두기 Node.js 22 이상 선택하기 빌드 명령이 npm run build이고 출력 디렉터리가 dist인지 확인하기
배포하기 전에 Review build settings에서 Environment variables를 찾아 Edit를 클릭하고 다음 두 항목을 추가하세요 — 3단계에서 입력한 값으로, 바로 복사할 수 있습니다. 웹사이트에 포함되는 값이므로 나중에 바꾸면 다시 배포해야 합니다.
공개 값만
Supabase Secret key나 Resend 키는 여기에 절대 추가하지 마세요. VITE_로 시작하는 값은 모두 브라우저에서 보이며, 이메일 비밀 값은 Supabase에만 둡니다.
Finish, 이어서 Deploy를 클릭하고 빌드가 끝날 때까지 기다리기
빌드가 멈추고 변수 이름이 표시되면, Hostinger에서 그 변수의 값을 고친 뒤 다시 배포하세요.
사장님 알림에 공개 주소 추가하기
Claude Code가 할 일.
공개 웹사이트 확인하기
내가 할 일.
도메인 열기 — 자물쇠가 표시되고 Preview 배너가 없어야 합니다 서비스, 가격, 영업시간 확인하기 휴대폰으로 테스트 예약을 하고 코드 입력하기 공개 사이트에서 /admin/을 열고 로그인해 요청 확정하기 알림과 확인 이메일이 모두 도착했는지 확인하기
이제부터 서비스, 가격, 영업시간, 웹사이트 문구와 사진은 대시보드에서 바꾸세요 — 바로 반영됩니다. 디자인이나 코드 변경은 Claude에게 요청하고 푸시를 승인하세요: Hostinger는 main에 푸시할 때마다 사이트를 다시 빌드합니다. 새 페이지 제목이나 설명은 다음 빌드 후에 검색 엔진에 반영됩니다.