2 cases built from this template
Same prompt, different [VARIABLES]. Click one to preview it above.About this template
A three-page website for an independent coffee shop: a home page with signature drinks and the roasting story, a menu page with dietary filters and three cup sizes, and a visit page with opening hours, an illustrated neighborhood map and an order-ahead pickup form. The default content follows an invented corner cafe in Portland that roasts its own beans, but the structure suits any small cafe, espresso bar or bakery counter: change the brand, city, street, bean origin and founding year and every section still reads true. The home page opens on a full-bleed photograph of the room in morning light, moves through three large alternating drink cards, the bean story told with real numbers, a four-photo strip, three customer quotes and a dark order-ahead band. The menu page lists every drink with 8, 12 and 16 oz prices, dietary badges and filter chips for dairy-free, gluten-free and decaf, plus pastries and retail beans. The visit page has an hours table with a live open-now indicator, transit, bike and parking notes, a hand-drawn SVG map of the block, a three-step pickup builder that ends in a printed-ticket-style confirmation stored in the browser, and a plain-spoken FAQ. The palette is cream and latte with espresso-brown text and a single terracotta accent; Fraunces sets the headlines and Nunito Sans the body, both self-hosted. Nothing is submitted anywhere: the pickup order, milk choices and time slot all live in the browser, so the site works as static files. To adapt it, swap the variables and rewrite the copy in one content file; the menu, map labels and order builder all read from it.
The template prompt
The live demo was built from exactly this text — nothing added. The other cases only change the values of the [VARIABLES].
# Coffee Shop Website
Build this website exactly as described below. Replace the [VARIABLES] with your own values; keep everything else.
## Brief
A three-page website for [BRAND], an independent coffee shop on [STREET] in [CITY], roasting beans from [BEAN_ORIGIN] since [FOUNDED]. It must feel like a real neighborhood cafe: full-bleed photography of the room, the counter and the drinks, three signature drinks with tasting notes, the roasting story with concrete numbers, a menu with category tabs, dietary filters and 8/12/16 oz pricing, opening hours with a live open-now indicator, transit notes, an SVG-drawn map of the block, and an order-ahead pickup builder that ends in a client-side confirmation ticket. Pages: index.html (home), menu.html (menu), visit.html (visit and order). Everything runs in the browser; nothing is sent anywhere.
- Audience: People who live or work within walking distance of [STREET] deciding where to get their morning coffee, remote workers looking for a seat and an outlet, and weekend visitors hunting for good pastries. Mostly 22–55, phone-first, impatient with fancy coffee jargon but appreciative of good beans.
- Goal: Get locals through the door and let regulars skip the line with order-ahead pickup. Within ten seconds a visitor should know what the shop smells like, what a small latte costs, whether it is open right now, and how to order ahead.
- Tone: Warm, plain and a little playful, like the person behind the counter who remembers your order. Short sentences, concrete numbers (sizes, prices, hours, grams), no coffee-snob vocabulary without a plain-word gloss, no exclamation marks.
## Stack
- Framework: Vite 5 + React 18 + TypeScript
- Styling: Tailwind CSS 3.4
- Libraries: react (MIT), react-dom (MIT), motion (motion.dev, import from 'motion/react') (MIT), lucide-react (ISC), tailwindcss (MIT), postcss (MIT), autoprefixer (MIT), vite (MIT), @vitejs/plugin-react (MIT), typescript (Apache-2.0), @fontsource-variable/fraunces (OFL-1.1), @fontsource/nunito-sans (OFL-1.1)
- Build: `npm run build` → static files in `dist/`. No backend, no server code, no external APIs.
- Setup:
- Scaffold with npm create vite@latest using the react-ts template. Three real HTML pages at the project root: index.html (entry src/main-home.tsx), menu.html (entry src/main-menu.tsx) and visit.html (entry src/main-visit.tsx).
- vite.config.ts: base './', plugins [react()], build { outDir 'dist', sourcemap false, assetsInlineLimit 0, rollupOptions { input { index: resolve(__dirname, 'index.html'), menu: resolve(__dirname, 'menu.html'), visit: resolve(__dirname, 'visit.html') } } }. Do not copy src/ into dist/.
- Tailwind 3.4 through PostCSS (tailwindcss + postcss + autoprefixer), content ['./index.html', './menu.html', './visit.html', './src/**/*.{ts,tsx}']. In tailwind.config.ts add every color under Design to theme.extend.colors with kebab-case keys (cream, latte, foam, espresso, crema, rule, terracotta, terracotta-deep, terracotta-light, grounds, olive, caramel) and fontFamily display ['Fraunces Variable', 'Georgia', 'serif'], sans ['Nunito Sans', 'system-ui', 'sans-serif']. Set borderRadius DEFAULT to 14px and add maxWidth { container: '1200px' }.
- In src/fonts.ts import '@fontsource-variable/fraunces' and '@fontsource/nunito-sans/400.css', '@fontsource/nunito-sans/600.css', '@fontsource/nunito-sans/700.css'; import src/fonts.ts and src/index.css from all three entry files.
- File layout: src/content.ts (every string, number, drink, pastry, bag, hour, slot rule, review, map label and FAQ answer for all three pages, typed), src/lib/brand.ts (brandSlug = [BRAND] lowercased with every run of non-alphanumeric characters replaced by '-', brandInitials = first letter of each word of [BRAND] uppercased, emailDomain = brandSlug without hyphens + '.com'), src/lib/storage.ts (safe localStorage get/set wrapped in try/catch, keys prefixed with brandSlug + ':'), src/lib/useOpenNow.ts (open-now from the hours table, client clock), src/lib/useReducedMotion.ts (re-export of Motion's useReducedMotion).
- State: src/store/order.ts is a tiny external store (useSyncExternalStore) holding the pickup draft { drinkId, size, milk, extras[], decaf, slot, name, note } and the confirmed ticket, persisted to localStorage key brandSlug + ':pickup'. The menu page and the visit page builder share it, so a drink added on menu.html ('Order this' on a row) is preselected in the builder on visit.html.
- Components in src/components/: Header.tsx, MobileMenu.tsx, Reveal.tsx (Motion whileInView wrapper), Eyebrow.tsx, Badge.tsx (dietary badges), Footer.tsx, CtaBand.tsx, PriceCols.tsx (8/12/16 oz columns); home: Hero.tsx, SignatureDrinks.tsx, BeanStory.tsx, PhotoStrip.tsx, Reviews.tsx; menu: MenuMasthead.tsx, FilterBar.tsx (tabs + chips), MenuList.tsx, MenuRow.tsx, BeansRetail.tsx; visit: HoursCard.tsx (with OpenNowPill.tsx), GettingHere.tsx, BlockMap.tsx (inline SVG), OrderBuilder/ (OrderBuilder.tsx, DrinkPicker.tsx, MilkChips.tsx, ExtraChips.tsx, SizeToggle.tsx, SlotPicker.tsx, NameStep.tsx, Ticket.tsx), Faq.tsx. src/pages/Home.tsx, Menu.tsx and Visit.tsx compose them; every page renders Header and Footer.
- Before the first build, download every image listed under Assets into public/images/ with curl -L -o using the exact file names given. The build itself never fetches anything.
- public/favicon.svg as described under Assets. All three HTML files: lang en, <meta name='theme-color' content='#FAF5EC'>, <link rel='icon' href='./favicon.svg' type='image/svg+xml'>. Titles: index.html '<title>[BRAND] — Coffee on [STREET], [CITY]</title>', menu.html '<title>Menu — [BRAND]</title>', visit.html '<title>Visit & order ahead — [BRAND]</title>'.
- Write ASSETS.md at the project root as described under Assets.
- dist/ holds the three HTML files, hashed JS/CSS, the woff2 fonts, favicon.svg and the six images. Keep it under 10 MB.
## Variables
- [BRAND] — Cafe name (default: "Marigold Coffee House"). Invented cafe name. Used in the wordmark, titles, footer, email (hello@ + brandSlug without hyphens + .com), localStorage keys and pickup order numbers (initials, e.g. MCH-1042). Never a real cafe or chain.
- [CITY] — City (default: "Portland, Oregon"). Where the shop is. Used in the hero eyebrow, getting-here copy and the footer. The street and every landmark stay invented-sounding; only the city may be real.
- [STREET] — Street (default: "Alder Row"). The invented street the shop sits on ('14 Alder Row'). Drives the address, the SVG block map (street names), the transit and parking copy and the house blend's name '[STREET] Blend'. Keep it two common English words, not a real address.
- [BEAN_ORIGIN] — Bean origin (default: "Huila, Colombia"). The current single origin the shop roasts. Drives the bean story, the menu's single-origin section, the retail bag and the FAQ. Real growing regions are fine; farms and importers stay invented.
- [FOUNDED] — Year opened (default: "2016"). Four-digit year. Drives the hero eyebrow, the wordmark line 'Est. [FOUNDED]' and the first line of the bean story; the roaster and the blend timeline shift to fit.
- [CREDIT] — keep a small "Template by VibeFather" link to https://vibefather.ai/t/coffee-shop-website in the footer (default: yes; delete this line to remove it)
The copy under Pages & Sections is written for the default values. If your values differ, rewrite every headline, paragraph, label and image for them — same length, tone and structure. Layout, colors, type and motion stay as described.
Keep all copy, image paths and links in one content file (for example `src/content.ts`), keyed by section, so the content can be swapped later without touching components.
## Design
### Colors
- Cream `#FAF5EC` — Page background on all three pages, header background after scroll.
- Latte `#F1E7D6` — Alternate section background (Signature drinks, Bean story, FAQ), image wells, hover fill for rows and chips.
- Foam `#FFFDF8` — Card surfaces (drink cards, hours card, ticket), input fill, mobile menu background.
- Espresso `#2B211B` — Headlines and body text on light backgrounds, primary outline buttons, icon color.
- Grounds `#241A14` — Order teaser band, footer, ticket header, photo overlays (as rgba(36,26,20,x)).
- Crema `#7A6A5C` — Secondary text, captions, eyebrows, disabled slot chips (at 45% opacity).
- Rule `#E3D5BE` — 1px hairlines, card borders, input borders, map street lines.
- Terracotta `#C05A2E` — The one accent: primary buttons, prices, badges, selected tab and chip states, map pin, focus ring, timeline dots.
- Terracotta Deep `#A2481F` — Primary button hover and pressed state.
- Terracotta Light `#E9A275` — Terracotta replacement for text and lines on Grounds backgrounds (prices, active chip border).
- Olive `#67784B` — Quiet second color: open-now dot and 'open' text, vegan and dairy-free badges, park block on the map, decaf badge.
- Caramel `#B98A4E` — Small numerals, years in the bean story, roast-day marks, window bench highlight on the map. Never for body text.
### Typography
- Display: H1, H2, H3, drink and pastry names, prices in large sizes, the wordmark, ticket totals: Fraunces (OFL), weights 500/600
- Text and UI: body, eyebrows, buttons, nav, form fields, menu descriptions, captions, numbers (font-variant-numeric tabular-nums for prices, hours and totals): Nunito Sans (OFL), weights 400/600/700
### Layout & motion
- Spacing: 8px base unit. Container max-width 1200px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 112px desktop, 80px under 1024px, 64px under 640px. Type scale: H1 clamp(44px, 6.4vw, 96px) Fraunces 500, line-height 1.0, letter-spacing -0.01em; H2 clamp(34px, 4.2vw, 60px) Fraunces 500, line-height 1.06; H3 26px Fraunces 600, line-height 1.2; italic phrases in headings use Fraunces 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Nunito 400 18px / 1.65 Espresso at 85% opacity; body Nunito 400 16px / 1.7 (max-width 62ch); eyebrow Nunito 700 12px uppercase letter-spacing 0.16em Crema, preceded by a 24px x 1px Terracotta line with 12px gap; caption Nunito 400 13px Crema. Buttons: height 50px, padding 0 26px, Nunito 700 14px uppercase letter-spacing 0.1em. Primary: Terracotta fill, Foam text. Secondary: 1px Espresso border, Espresso text, transparent (on photos: 1px Foam border, Foam text). Small buttons 38px high, padding 0 16px, 12px text. Inputs: height 50px, 1px Rule border, Foam fill, 16px Nunito, focus border Terracotta. Focus ring everywhere: 2px Terracotta outline with 3px offset.
- Radius: 14px on cards, buttons, inputs, chips, photos and the ticket. 999px only for badges, the open-now dot, dietary badge pills, size-toggle dots and the map pin.
- Motion: Easing: --ease-out cubic-bezier(0.22, 0.61, 0.36, 1) for reveals and drawers; --ease-io cubic-bezier(0.65, 0, 0.35, 1) for tabs, accordions and builder steps. Nothing bounces.
- Motion: Reveal: blocks wrapped in <Reveal> start at opacity 0, translateY(18px) and animate to rest over 700ms --ease-out when 15% visible (Motion whileInView, viewport once). Siblings in a list stagger by 80ms (index prop).
- Motion: Hero photo: on load the image scales from 1.07 to 1.0 over 2200ms --ease-out; while scrolling, the image translates 0 to 10% of its height as the hero scrolls out (Motion useScroll on the hero, offset ['start start', 'end start']), and the headline block fades to opacity 0.25 and moves -32px over the same range. H1 lines rise from translateY(26px) and opacity 0 with 120ms stagger, starting 150ms after load.
- Motion: Signature drink cards: on hover the photo scales to 1.04 over 700ms --ease-out and the card border turns Espresso; the price ticks up 4px and settles. 'Order this' click: the button crossfades to a Check icon and 'Added' for 1400ms.
- Motion: Menu filtering: rows use Motion layout with AnimatePresence mode 'popLayout'; leaving rows fade and slide 8px left over 200ms, remaining rows glide to position over 380ms --ease-io. Tab switch slides a 2px Terracotta underline between tabs with Motion layoutId.
- Motion: Order builder: step changes crossfade with a 16px horizontal slide, 280ms --ease-io (AnimatePresence mode 'wait'). Selecting size, milk or extras fills the chip over 150ms; the running total counts to the new value over 400ms; the ticket replaces the form with a fade and a dashed border draw, and the order number types in character by character over 800ms.
- Motion: Hours: the open-now dot pulses (scale 1 to 1.25, 1600ms loop) only while open; 'Opens at 6:30am' lines crossfade when the day changes at midnight.
- Motion: Block map: on entering view the streets draw (stroke-dashoffset to 0) over 900ms, then the park block fills, then the shop pin drops from scale 0.6 with a soft overshoot and the transit, bike and parking markers pop in with 120ms stagger.
- Motion: Header: transparent over the photo hero with Foam text; after 40px of scroll it gets Cream at 94% opacity, backdrop-filter blur(10px), Espresso text and a 1px Rule bottom border, 250ms transition. On menu.html and visit.html it is solid from the start.
- Motion: FAQ accordions: height 0 to auto and opacity 0 to 1 over 300ms --ease-io; the Plus icon rotates 45 degrees into an X.
- Motion: Links: .link-draw grows a 1px currentColor underline from 0% to 100% width over 300ms --ease-out on hover and focus-visible.
- Motion: prefers-reduced-motion: reduce — disable the hero scale and parallax, H1 rise, street draw, pin drop, count-ups, pulse and layout animations (render at rest; tabs and accordions switch instantly). Color and border hover changes stay. Use CSS @media in index.css plus Motion's useReducedMotion in components.
- Imagery: Real photography only, warm and natural, all six made for this template in one consistent style: morning window light, oak and terracotta palette, documentary editorial look, fine grain. No people, no faces, no hands, no readable text, logos, cup branding or menu boards with writing. Every photo uses object-fit cover with the object-position given under Assets, 14px corners, no shadow; photos on Cream get a 1px Rule outline. Captions below photos in Nunito 13px Crema. Drawn in code: the favicon, the wordmark (type only), the illustrated block map, size dots, dietary badge icons, the ticket and dividers. Icons: lucide-react only, stroke width 1.5.
## Pages & Sections
### Home (`index.html`)
1. **Content file and copy rules** — All copy below is written for the default values ([BRAND] = Marigold Coffee House, [CITY] = Portland, Oregon, [STREET] = Alder Row, [BEAN_ORIGIN] = Huila, Colombia, [FOUNDED] = 2016). Put every string, number and list in src/content.ts and render from it; the three pages share one content file. If any variable value differs, rewrite every headline, drink, tasting note, price, review, hour, direction, map label and FAQ answer so it is specific and believable for the new cafe, keeping the same structure, counts and lengths. All people, drinks, streets and figures are invented. Shop facts used throughout: address 14 [STREET], [CITY]; phone (503) 555-0148; email hello@ + emailDomain ([email protected]); 26 seats; 6 window stools; 1 roaster (a 5 kg drum, installed [FOUNDED] + 2); roast day Tuesday; 9-day bean rest; house blend named '[STREET] Blend'. Hours (client clock): Mon–Fri 6:30–18:00, Sat 7:00–18:00, Sun 7:00–16:00. Prices: espresso drinks start $3.00, drip $3.50, pastries $4.00–7.00, retail bags $17–19.
Layout: n/a
Motion: n/a
2. **Header (all pages)** — Left: wordmark '[BRAND]' (Fraunces 600, 20px, uppercase, letter-spacing 0.16em) with a second line 'Est. [FOUNDED] · Roasted in-house' (Nunito 600, 10px uppercase, letter-spacing 0.22em), linking to ./index.html. Center nav (Nunito 600 14px): 'Menu' → ./menu.html, 'Visit & order' → ./visit.html, 'Our story' → ./index.html#story. Current page link has a 1px underline. Right: small primary button 'Order pickup' → ./visit.html#order (hidden under 1024px) and the hamburger (Lucide Menu 22px, shown under 820px) opening MobileMenu: full-screen Latte panel, links at Fraunces 500 32px, the order button at the bottom, close icon top right.
Layout: Fixed top, height 76px, container-aligned. Over the home hero only it starts transparent with Foam text (see Motion). Mobile menu covers the viewport with a 300ms slide from the right.
3. **Hero** — Background photo hero-interior.webp. Eyebrow (Foam, line in Foam at 60%): '[STREET] · [CITY] · Est. [FOUNDED]'. H1 in two lines: 'Slow mornings,' / '*strong coffee.*' Lead (Foam at 88%, max-width 560px): '[BRAND] opened on [STREET] in [FOUNDED] with one grinder, six stools and a promise: proper espresso, real milk, nothing rushed. We roast single origins from [BEAN_ORIGIN] in the back room every Tuesday and pour them seven days a week.' Buttons: primary 'See the menu' → ./menu.html (Lucide ArrowRight 16px), secondary on-photo 'Order pickup' → ./visit.html#order. Bottom ledger of four items, each a big value (Fraunces 500 30px Foam) over a label (Nunito 700 12px uppercase letter-spacing 0.12em Foam at 70%): 'Est. [FOUNDED]' / 'Roasted in-house'; '7 days' / '6:30am – 6pm'; '[BEAN_ORIGIN]' / 'This month''s single origin'; '26 seats' / 'Outlets at every window stool'. On mobile the paragraph sits on a stronger Grounds gradient overlay and is shortened; the stats stack in a 2x2 grid with breathing room.
Layout: Height 92svh, min-height 640px, max-height 980px. Image object-fit cover, object-position 50% 60%. Overlay linear-gradient(180deg, rgba(36,26,20,0.46) 0%, rgba(36,26,20,0.10) 35%, rgba(36,26,20,0.24) 60%, rgba(36,26,20,0.80) 100%). Content block anchored bottom-left inside the container, 120px above the ledger, max-width 780px. Ledger: absolute bottom 0, full container width, a 1px Foam/25% top border, 4 equal columns with 1px Foam/25% vertical dividers, padding 24px 0 32px. Under 768px: H1 at 44px, ledger becomes a 2x2 grid, buttons stack full-width.
4. **Signature drinks** — Section eyebrow 'The signatures' and H2 'Three cups we''d walk across town for.' Three large cards, alternating image/text sides: 1) latte-signature.webp, alt 'Honey lavender latte with latte art in a ceramic cup on an oak table' — name 'Honey Lavender Latte', copy 'House lavender syrup made from the flower shop next door''s cuttings, a spoon of local honey, your choice of milk. The cup that pays our rent.' — prices '8oz $4.75 · 12oz $5.25 · 16oz $5.75' — badge 'Dairy-free with oat'. 2) espresso-pour.webp, alt 'Espresso pouring from an unbranded machine into a small cup below the counter' — name 'Maple Cortado', copy 'A double ristretto cut with steamed whole milk and a half-measure of dark maple. Four ounces, no lid, no hurry.' — price 'One size $4.50'. 3) beans-scoop.webp, alt 'Freshly roasted coffee beans scooped from a plain hessian sack' — name '[STREET] Batch Brew', copy 'Our house blend, roasted Tuesdays and rested nine days. Chocolate, toasted almond, and a finish that forgives you for drinking it in a car.' — prices '8oz $3.50 · 12oz $4.00 · 16oz $4.50'. Each card has a small secondary button 'Order this' → ./visit.html#order that saves the drink to the pickup draft.
Layout: Latte background. Header block left-aligned, max-width 640px. Cards: 12-column rows alternating image (5 cols, aspect 4:3, 14px radius) and text (6 cols, offset 1); text side has badge, name (H3 32px Fraunces), copy, prices in Fraunces 600 22px Terracotta, button. 96px between cards. Under 860px cards stack (image on top) with 72px gaps.
5. **Bean story** — Section id='story'. Eyebrow 'Since [FOUNDED]' and H2 'One roaster, one row of shelves, one long Tuesday.' Two columns: left, the story in three short paragraphs: 'The roaster came second-hand from a cafe in the hills — a 5 kg drum that had already seen ten years of mornings. We stripped it, re-wired it, and installed it where the storage room used to be, close enough to the bar that the first crack of [BEAN_ORIGIN] smells better than any candle we could buy.' / 'We roast every Tuesday, rest the beans nine days, and bag them on Monday nights. What we don''t sell as bags goes into the hopper, which is why the batch brew on a Wednesday tastes like a holiday and the batch brew on a Monday tastes like a promise.' / 'The blend changes with the seasons; the promise doesn''t: if a cup isn''t right, we remake it, no questions, no receipt needed.' Right, a numbered ledger of four facts (Fraunces 600 28px value over Nunito 13px Crema label, 1px Rule dividers): '5 kg / drum roaster, second-hand'; 'Tuesday / roast day, every week'; '9 days / rest before we pour'; '$17 / 250g bag of [STREET] Blend'. Below both, a pull quote across the section (Fraunces 500 italic 28px): '*"A cafe is just a living room with better coffee."* — Renata, who has opened every morning since [FOUNDED]'.
Layout: Cream background. Story column 6 cols (max-width 56ch), ledger 4 cols offset 1 with 32px left padding and a 1px Rule left border. Pull quote centered, max-width 820px, 1px Terracotta lines above and below at 24px inset. Under 860px: stack story then ledger, quote at 22px.
6. **Photo strip** — Four square photos in a row, each with a caption: latte-signature.webp again 'The signature, before the first sip'; espresso-pour.webp again 'First pour of the day, 6:31am'; pastry-case.webp 'The case at 7am, if you''re lucky'; corner-tables.webp 'The window bench, permanent sun'. Caption under each in Nunito 13px Crema.
Layout: Latte background. 4 equal columns with 16px gap, aspect 1:1, 14px radius. Horizontal scroll-snap on mobile (each photo 78vw). Clicking a photo opens a lightbox (fixed overlay, Grounds at 80%, the photo at max 80vh centered, caption below in Foam, X to close, Escape closes).
7. **Reviews** — Eyebrow 'Word of mouth' and H2 'What the regulars say.' Three quote cards on Foam: 1) '"The cardamom bun alone is worth the walk across town."' — Priya N., regular since 2019. 2) '"They remember your order by the second visit. And your dog''s name by the third."' — Tom & June A., Saturday bench people. 3) '"Best cortado in the city, and the only cafe where the window seat is free at 7am. I''ve tested both claims extensively."' — Marcus L., works from the corner table. Each card: large opening quote mark (Fraunces 600 48px Terracotta), quote in Fraunces 500 21px / 1.4, attribution in Nunito 600 13px Crema.
Layout: Cream background. Three equal columns, 24px gap, cards 14px radius with 1px Rule border, padding 32px, aligned tops with 8px stagger (middle card offset 24px down on desktop). Under 860px: stacked, no offset.
8. **Order teaser band** — Grounds background. Left: eyebrow in Terracotta Light 'Skip the line', H2 in Foam 'Order ahead. Walk in. Walk out.' and one line (Foam at 75%): 'Pick a drink, pick a time, and it''s waiting at the end of the bar with your name on the cup — the good kind of name tag.' Right: primary button 'Start an order' → ./visit.html#order and under it a caption in Foam at 55% 'Pickup from 6:45am · No app, no account, no card'.
Layout: Full-width band, container-aligned inside, two columns (7 text / 4 button, offset 1), vertical padding 96px. A 1px Terracotta Light top border at 40% width aligned left.
9. **Footer (all pages)** — Grounds background. Four columns: 1) wordmark '[BRAND]' (Fraunces 600 22px Foam) over 'Est. [FOUNDED] · [STREET], [CITY]' and the social line 'On the internet, we''re mostly closed.' 2) 'Find us': address '14 [STREET]', '[CITY]', phone (503) 555-0148, hello@ + emailDomain. 3) 'Hours': Mon–Fri 6:30–18:00, Sat 7:00–18:00, Sun 7:00–16:00, caption 'Holiday hours on the door, and here too, when they exist.' 4) 'Around the block': 'Menu' → ./menu.html, 'Visit & order' → ./visit.html, 'Our story' → ./index.html#story. Bottom line under a 1px Foam/15% rule: '© [BRAND]. Made with too much coffee on [STREET].' Text in Foam at 80%, links Foam with .link-draw.
Layout: Vertical padding 72px, 4 equal columns, bottom line 40px below the rule. Under 768px: two columns, then stacked.
### Menu (`menu.html`)
1. **Masthead** — Solid header from the start (no photo). Eyebrow 'The menu', H1 'Everything on the counter.' Lead (max-width 620px): 'Sizes are 8, 12 and 16 ounces. Oat and almond milk are +50 cents, a decaf swap is free, and the pastry case is restocked at 6am and usually empty by noon — we take that as a compliment.' Right of the lead, the size legend: three dots (8, 12, 16) filled Crema, Terracotta, Espresso with labels, plus the note 'Prices include tax. Card and cash at the counter.'
Layout: Cream background, container-aligned, vertical padding 136px top (header height) + 48px. H1 max-width 720px. Masthead bottom border 1px Rule, 64px below text. Under 860px the legend wraps under the lead.
2. **Filter bar** — Sticky under the header (top 76px) on Foam at 96% with blur and a 1px Rule bottom border. Category tabs (Nunito 700 14px): 'Espresso', 'Brewed & cold', 'Pastries & bites', 'Beans to go'. Filter chips with a 12px dot each: 'Dairy-free' (Olive dot), 'Gluten-free' (Caramel dot), 'Decaf' (Espresso dot); chips are toggles, multiple active chips filter with AND. Right end: count '18 items' updating live, and a caption 'Tap a chip to narrow things down.'
Layout: Tabs left, chips center-right, count right. A 2px Terracotta underline slides between tabs (Motion layoutId). Under 768px: tabs scroll horizontally, chips wrap to a second row.
3. **Menu list (Espresso)** — Rows with name (Fraunces 600 22px), one-line description (Nunito 15px Crema), dietary badge pills, and PriceCols: 1) 'Honey Lavender Latte' — 'Lavender syrup from the flower shop next door, local honey, any milk' — dairy-free badge — $4.75 / $5.25 / $5.75. 2) 'Vanilla Bean Latte' — 'Real vanilla bean paste, none of the perfume stuff' — $4.50 / $5.00 / $5.50. 3) 'Flat White' — 'Double ristretto, velvet milk, no foam architecture' — $4.50 / $5.00 / $5.50. 4) 'Cappuccino' — 'Traditional: 6oz of it is the cup''s business, not ours' — $4.25 / $4.75 / $5.25. 5) 'Maple Cortado' — 'Ristretto cut with whole milk and dark maple' — one size $4.50. 6) 'Mocha' — '70% dark chocolate melted to order, no whip' — $5.00 / $5.50 / $6.00. 7) 'Espresso' — '[STREET] Blend or the current single origin, your call' — 2oz $3.00 / 4oz $3.50. 8) 'Espresso Tonic' — 'Double shot, artisan tonic, orange peel, summer in a glass' — 16oz only $5.75, dairy-free badge. Any espresso drink takes a free decaf swap: the list carries a decaf badge on the two drinks people actually order it in: 'Vanilla Bean Latte' and 'Mocha'.
Layout: Rows: name + description left (8 cols), PriceCols right (3 cols, offset 1) with 8oz / 12oz / 16oz column heads (Nunito 700 11px uppercase Crema) and Fraunces 600 20px Terracotta prices; single-size items span all three columns with 'one size' or the ounce label. 1px Rule dividers between rows, 20px row padding, row hover fills Latte at 60% with an 'Order this' affordance appearing at the right edge (saves the drink to the pickup draft and links to ./visit.html#order). Under 640px prices move under the description in a 3-column row.
4. **Menu list (Brewed & cold)** — 1) 'Batch Brew' — '[STREET] Blend, roasted Tuesday, ground 90 seconds before it hits the water' — $3.50 / $4.00 / $4.50, decaf badge ('Swiss water, always on'). 2) 'Pour-over' — '[BEAN_ORIGIN], made one cup at a time; give it four minutes' — 12oz only $5.50. 3) 'Cold Brew' — 'Steeped 18 hours, poured over one enormous ice cube' — $4.75 / $5.25, dairy-free badge. 4) 'Cardamom Cold Brew' — 'Cold brew, cardamom syrup, a float of oat cream' — 16oz only $5.25, dairy-free badge. 5) 'Hibiscus Iced Tea' — 'Tart, ruby, unsweetened unless you ask' — 16oz only $4.00, dairy-free + gluten-free badges. 6) 'Hot Chocolate' — 'The same 70% chocolate as the mocha, whole milk, no coffee' — $4.25 / $4.75, gluten-free badge.
Layout: Same row system as Espresso.
5. **Menu list (Pastries & bites)** — 1) 'Butter Croissant' — 'Laminated over three days by Renata''s old sous-chef' — $4.25, gluten-free badge shows as 'GF on request' via a Caramel-dot variant. 2) 'Cardamom Bun' — 'The one people photograph before eating; we understand' — $4.75. 3) 'Sourdough Toast & Jam' — 'Two thick slices, house butter, seasonal jam' — $6.50, dairy-free badge 'vegan on request'. 4) 'Sausage Roll' — 'Puff pastry, breakfast sausage, fennel seed' — $5.50. 5) 'Banana Bread' — 'Toasted, salted butter optional but recommended' — $4.00. 6) 'Granola & Yogurt' — 'House granola, yogurt, honey from the same hive as the latte' — $7.00, gluten-free badge.
Layout: Same row system, single 'each' price column instead of three sizes (column head 'each').
6. **Menu list (Beans to go)** — 1) '[STREET] Blend' — 'Chocolate, toasted almond, forgiving. Our daily driver.' — 250g bag $17. 2) '[BEAN_ORIGIN] Single Origin' — 'The pour-over and the espresso guest slot; roasted Tuesdays' — 250g bag $19. 3) 'Half & Half Set' — 'One of each bag, plus brewing notes on a postcard' — 2 x 250g $33. Each row gets a small secondary button 'Add to pickup note' that appends the bag to the pickup draft''s note field (no cart drawer on this site; pickup is drinks-first).
Layout: Same row system, 'per bag' price column. Rows keep the Latte hover fill; the small button appears on hover or focus.
7. **Pickup CTA band** — Grounds band, centered: H3 in Foam 'Decided? Skip the line.' Primary button 'Order ahead for pickup' → ./visit.html#order, caption below in Foam at 55% 'Ready in about 10 minutes · Pay at the counter'.
Layout: Full-width, vertical padding 72px, centered stack, 16px gaps. Sits above the Footer.
### Visit and order (`visit.html`)
1. **Masthead** — Solid header. Eyebrow 'Visit & order', H1 'Find the door. Or don''t — we''ll bring it out.' Lead: 'We''re on the sunny corner of [STREET], between the flower shop and the record store. Inside: 26 seats, six window stools with outlets, water that''s actually cold, and a restroom with a working lock. Outside: a bench that catches the 4pm sun.'
Layout: Cream background, same masthead rhythm as menu.html, bottom border 1px Rule.
2. **Hours and getting here** — Left card (Foam, 14px radius): title 'This week' with the OpenNowPill (Olive dot + 'Open now · closes 6pm' or Terracotta dot + 'Closed · opens 6:30am', computed from the client clock and the hours table). Hours table: Mon–Fri 6:30–18:00 / Sat 7:00–18:00 / Sun 7:00–16:00, current day row bold with a 2px Terracotta left border; caption 'The clock above the door is two minutes fast. We side with the door.' Right, three small rows with Lucide icons: TrainFront 'Transit' — 'Mallow Street station is two blocks north; the 14 and 61 buses stop at the flower shop.'; Bike 'Bike' — 'Two racks on [STREET] and a pump by the door — the pump is free, the air is too.'; Car 'Car' — 'Metered on Mallow Street until 5pm, free after; the alley behind us is loading only, sorry.'
Layout: 12-col: hours card 5 cols, transport rows 6 cols offset 1 stacked with 24px gaps, each row icon in a 44px Latte rounded square. Under 860px stacked.
3. **Illustrated block map** — Inline SVG map of the block on Latte, drawn in code: [STREET] runs diagonally bottom-left to top-right; Mallow Street crosses it a third of the way up; a second block labeled 'Foundry Lane' along the top edge. The shop pin sits at the [STREET]/Mallow corner: a Terracotta teardrop with a Foam coffee-cup glyph, pulsing ring, and label '[BRAND] · 14 [STREET]'. Other drawn labels: 'Flower shop' (small Espresso square, top left on [STREET]), 'Record store' (small square, right of the shop), 'Alder Green' park (Olive rounded block bottom right with two drawn trees), 'Mallow St station' (Espresso square with rail tick marks, top right), 'P' parking (Espresso outlined square on Mallow). A small north arrow bottom left and a caption line: 'Not to scale. Neither is our eggnog season.' Legend row under the map: pin = us, squares = neighbours, olive = grass. The SVG map fills its column with labels at 12px or larger; the legend sits under the map; labels never collide; no cramped corner.
Layout: SVG viewBox 0 0 960 540, width 100%, streets 3px Espresso at 80%, street names along the lines in Nunito 600 13px Espresso. Map container 7 cols; the legend and caption stack right (4 cols) with the title 'The block, honestly drawn'.
4. **Order-ahead pickup builder** — Section id='order'. Latte background. Eyebrow 'Order ahead', H2 'Three taps and it''s on the bar.' Steps: 1) 'Your drink' — a scrollable list of the 10 bookable drinks (the 8 espresso drinks plus Cold Brew and Cardamom Cold Brew) as compact rows (name + starting price); below it SizeToggle (8oz / 12oz / 16oz pills; cortado locked to 'one size'), MilkChips (Whole · 2% · Oat +$0.50 · Almond +$0.50), ExtraChips (Extra shot +$0.80 · Decaf swap, free · Half syrup, free) and, if a drink was preselected on menu.html or index.html, a note 'Kept your pick from the menu page.' 2) 'Pick a time' — slot chips generated client-side for today only: 'ASAP (~10 min)' first, then every 15 minutes from 30 minutes from now until 15 minutes before close; slots past close are not shown; caption 'Orders after the last slot: come by tomorrow, we open at 6:30am.' 3) 'Your name' — one input (placeholder 'Name for the cup') and one optional note input (placeholder 'Anything we should know? No lactose? Dog outside?'), then the summary panel. Summary (always visible, right column, Foam card): drink line, size, milk, extras, slot, a Fraunces 32px total (size price + milk + extras, tabular-nums), primary button 'Place pickup order' and caption 'Nothing is charged or sent — show this at the counter and pay there.' Confirming renders the Ticket: Grounds header strip with '[BRAND]' in Foam and the order number (brandInitials + '-' + four digits, e.g. 'MCH-1042') typed in character by character; below on Foam, dashed-border ticket body: pickup time, drink summary lines, total, the name 'for [NAME]' in Fraunces 26px, a code-drawn barcode (random-height Espresso bars from a seeded hash of the order number), and the line 'Show this at the counter · Good for 30 minutes'. Buttons: 'Start another order' (resets the draft) and 'Back to the menu' → ./menu.html. The ticket persists in localStorage. Section padding stays at the spec rhythm; stepper, form and summary share a tight 12-column grid with the summary sticky beside the form - no dead zones.
Layout: Two columns: the current step (7 cols) and the sticky summary (4 cols, offset 1, sticky top 100px). Step indicator above: three numbered dots with labels connected by 1px Rule lines, done steps filled Olive, current Terracotta. Ticket replaces the whole two-column area centered at max-width 560px. Under 900px: single column, summary first on top of the step.
5. **FAQ** — Eyebrow 'Quick answers', H2 'Asked at the counter, answered here.' Five accordions: 1) 'Do you have WiFi?' — 'Yes, password is on the chalkboard, and the chalkboard is honest: ''stay as long as you bought a coffee for.'' Outlets at all six window stools.' 2) 'Can I work from the cafe?' — 'Weekdays before 11am and after 2pm, absolutely. Weekend mornings belong to the paper readers and the pram fleet.' 3) 'Are you dog-friendly?' — 'On the bench out front, always; inside, yes if the dog is smaller than the roaster. Water bowls by the door.' 4) 'What about gluten-free or dairy-free?' — 'Oat and almond milk at cost +50 cents, decaf free. The granola and the hibiscus tea are gluten-free; the croissant, regrettably, is a croissant.' 5) 'Where do the beans come from?' — 'This month, [BEAN_ORIGIN], roasted by us on [STREET] every Tuesday. We name the farm on the bag when the importer lets us; the postcard in the Half & Half set tells the longer story.'
Layout: Cream background, accordion rows with 1px Rule dividers, question in Fraunces 600 20px, answer Nunito 16px / 1.7 max-width 62ch, Plus icon right. Container max-width 760px.
## Assets
- image: Template photos made for this design (free to redistribute with the template). Download each with curl -L -o into public/images/: https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/hero-interior.webp → public/images/hero-interior.webp (Home hero; object-position 50% 60%; alt 'Sunlit corner cafe interior with an oak counter, an espresso machine and empty stools'); https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/latte-signature.webp → public/images/latte-signature.webp (Home Signature drinks card 1 and Photo strip; alt 'Honey lavender latte with latte art in a ceramic cup on an oak table'); https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/espresso-pour.webp → public/images/espresso-pour.webp (Signature card 2 and Photo strip; alt 'Espresso pouring from an unbranded machine into a small cup below the counter'); https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/beans-scoop.webp → public/images/beans-scoop.webp (Signature card 3; alt 'Freshly roasted coffee beans scooped from a plain hessian sack'); https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/pastry-case.webp → public/images/pastry-case.webp (Photo strip; alt 'Glass pastry case with croissants and cardamom buns at opening time'); https://media.vibefather.ai/assets/307a73bc-a563-4763-8881-9e58eeadeaf7/corner-tables.webp → public/images/corner-tables.webp (Photo strip; alt 'Window bench and corner table in afternoon sun').
- image: Write ASSETS.md at the project root with a table: path, source URL, author, license — one row for each of the six photos (source 'media.vibefather.ai, made for this template', author 'VibeFather', license 'Distributed with the template'), plus rows for @fontsource-variable/fraunces and @fontsource/nunito-sans (OFL-1.1) and lucide-react (ISC). If you change [BEAN_ORIGIN] or [CITY], keep these photos or replace them only with other CC0 / public-domain files or your own photos shot in the same warm style — never Unsplash, Pexels or Pixabay, and never images with faces, hands or readable branding.
- icon: lucide-react only: Coffee, Menu, X, Plus, Check, ArrowRight, ArrowUpRight, MapPin, Phone, Mail, Clock, TrainFront, Bike, Car, Wifi, Leaf, Wheat, MoonStar, CupSoda, Croissant, Dog, Plug, ShoppingBag. Stroke width 1.5, 16–24px, color inherits. public/favicon.svg hand-written: viewBox 0 0 32 32, a 32x32 rect rx 8 filled #C05A2E, a Foam (#FFFDF8) coffee cup glyph (a 12x10 rounded rect body at y 13 with a 2.5px handle arc on the right) and two 2px Foam steam curves above. No other logo: the cafe name is always set as type.
- font: Install @fontsource-variable/fraunces and @fontsource/nunito-sans and import them in src/fonts.ts as listed in Setup. Vite bundles the woff2 files into dist/.
- image: Drawn in code: the illustrated block map (inline SVG with street name labels), the open-now pill dot, dietary badge dots, the size legend dots, the ticket barcode, the check circle, dividers and the favicon. No other bitmaps, no illustrations, no map tiles, no external map embeds.
## Don'ts
- No backend, no form submission, no fetch to any API: the pickup order, its confirmation and every choice live in the browser only (localStorage), and the order builder never charges anything.
- Every internal link points to a file name (./index.html, ./menu.html, ./visit.html, ./visit.html#order) — never to a bare directory.
- Self-host everything: fonts through Fontsource, icons as npm packages or inline SVG, images downloaded into public/images/. No CDN <script> or <link> tags, no Google Fonts, no analytics.
- Production build: minified, no source maps, no src/ copied into dist/, single command npm run build, output in dist/ under 10 MB.
- No real cafe or chain names, no real addresses, no real map tiles or embeds (the block map is drawn in SVG), no photos with faces, hands or readable logos, cups or signage.
- No dates or years anywhere except 'Est. [FOUNDED]' and the story copy; the site never shows today's date.
- Never mention VibeFather or any other brand inside the site except the optional credit footer link; all copy is invented US English.
- Respect prefers-reduced-motion everywhere: disable parallax, count-ups, pin drops and layout animations; keep color/border hovers.
- The site must work at 1440x900 desktop and 390x844 mobile with zero console errors; the order builder works with keyboard only and every interactive element has a visible focus ring.
- Keep copy concrete: no lorem, no filler, no superlatives without evidence; prices, hours and sizes always come from src/content.ts.
---
— Prompt by VibeFather · https://vibefather.ai/t/coffee-shop-website · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown
Free for personal projects under CC BY-NC 4.0. Commercial use comes with Pro.
DESIGN.md
The design system on its own — colors, type, spacing and motion. Apply this look to a project you already have.
---
name: "Coffee Shop Website"
colors:
cream: "#FAF5EC"
latte: "#F1E7D6"
foam: "#FFFDF8"
espresso: "#2B211B"
grounds: "#241A14"
crema: "#7A6A5C"
rule: "#E3D5BE"
terracotta: "#C05A2E"
terracotta_deep: "#A2481F"
terracotta_light: "#E9A275"
olive: "#67784B"
caramel: "#B98A4E"
typography:
display_h1_h2_h3_drink_and_pastry_names_prices_in_large_sizes_the_wordmark_ticket_totals: { family: "Fraunces", weights: [500, 600] }
text_and_ui_body_eyebrows_buttons_nav_form_fields_menu_descriptions_captions_numbers_font_variant_numeric_tabular_nums_for_prices_hours_and_totals: { family: "Nunito Sans", weights: [400, 600, 700] }
spacing: "8px base unit. Container max-width 1200px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 112px desktop, 80px under 1024px, 64px under 640px. Type scale: H1 clamp(44px, 6.4vw, 96px) Fraunces 500, line-height 1.0, letter-spacing -0.01em; H2 clamp(34px, 4.2vw, 60px) Fraunces 500, line-height 1.06; H3 26px Fraunces 600, line-height 1.2; italic phrases in headings use Fraunces 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Nunito 400 18px / 1.65 Espresso at 85% opacity; body Nunito 400 16px / 1.7 (max-width 62ch); eyebrow Nunito 700 12px uppercase letter-spacing 0.16em Crema, preceded by a 24px x 1px Terracotta line with 12px gap; caption Nunito 400 13px Crema. Buttons: height 50px, padding 0 26px, Nunito 700 14px uppercase letter-spacing 0.1em. Primary: Terracotta fill, Foam text. Secondary: 1px Espresso border, Espresso text, transparent (on photos: 1px Foam border, Foam text). Small buttons 38px high, padding 0 16px, 12px text. Inputs: height 50px, 1px Rule border, Foam fill, 16px Nunito, focus border Terracotta. Focus ring everywhere: 2px Terracotta outline with 3px offset."
radius: "14px on cards, buttons, inputs, chips, photos and the ticket. 999px only for badges, the open-now dot, dietary badge pills, size-toggle dots and the map pin."
---
# Coffee Shop Website — Design System
Apply this design system to an existing project. It describes the look and feel only; for the full site, use prompt.md.
## Colors
- **Cream** `#FAF5EC` — Page background on all three pages, header background after scroll.
- **Latte** `#F1E7D6` — Alternate section background (Signature drinks, Bean story, FAQ), image wells, hover fill for rows and chips.
- **Foam** `#FFFDF8` — Card surfaces (drink cards, hours card, ticket), input fill, mobile menu background.
- **Espresso** `#2B211B` — Headlines and body text on light backgrounds, primary outline buttons, icon color.
- **Grounds** `#241A14` — Order teaser band, footer, ticket header, photo overlays (as rgba(36,26,20,x)).
- **Crema** `#7A6A5C` — Secondary text, captions, eyebrows, disabled slot chips (at 45% opacity).
- **Rule** `#E3D5BE` — 1px hairlines, card borders, input borders, map street lines.
- **Terracotta** `#C05A2E` — The one accent: primary buttons, prices, badges, selected tab and chip states, map pin, focus ring, timeline dots.
- **Terracotta Deep** `#A2481F` — Primary button hover and pressed state.
- **Terracotta Light** `#E9A275` — Terracotta replacement for text and lines on Grounds backgrounds (prices, active chip border).
- **Olive** `#67784B` — Quiet second color: open-now dot and 'open' text, vegan and dairy-free badges, park block on the map, decaf badge.
- **Caramel** `#B98A4E` — Small numerals, years in the bean story, roast-day marks, window bench highlight on the map. Never for body text.
## Typography
- **Display: H1, H2, H3, drink and pastry names, prices in large sizes, the wordmark, ticket totals** — Fraunces (OFL), weights 500/600. Self-host the font files.
- **Text and UI: body, eyebrows, buttons, nav, form fields, menu descriptions, captions, numbers (font-variant-numeric tabular-nums for prices, hours and totals)** — Nunito Sans (OFL), weights 400/600/700. Self-host the font files.
## Spacing & shape
- Spacing: 8px base unit. Container max-width 1200px, centered, side padding 48px desktop, 32px tablet, 20px under 640px. 12-column grid, column gap 24px. Section vertical padding 112px desktop, 80px under 1024px, 64px under 640px. Type scale: H1 clamp(44px, 6.4vw, 96px) Fraunces 500, line-height 1.0, letter-spacing -0.01em; H2 clamp(34px, 4.2vw, 60px) Fraunces 500, line-height 1.06; H3 26px Fraunces 600, line-height 1.2; italic phrases in headings use Fraunces 500 italic (marked with *asterisks* in content.ts and rendered as <em>); lead paragraph Nunito 400 18px / 1.65 Espresso at 85% opacity; body Nunito 400 16px / 1.7 (max-width 62ch); eyebrow Nunito 700 12px uppercase letter-spacing 0.16em Crema, preceded by a 24px x 1px Terracotta line with 12px gap; caption Nunito 400 13px Crema. Buttons: height 50px, padding 0 26px, Nunito 700 14px uppercase letter-spacing 0.1em. Primary: Terracotta fill, Foam text. Secondary: 1px Espresso border, Espresso text, transparent (on photos: 1px Foam border, Foam text). Small buttons 38px high, padding 0 16px, 12px text. Inputs: height 50px, 1px Rule border, Foam fill, 16px Nunito, focus border Terracotta. Focus ring everywhere: 2px Terracotta outline with 3px offset.
- Radius: 14px on cards, buttons, inputs, chips, photos and the ticket. 999px only for badges, the open-now dot, dietary badge pills, size-toggle dots and the map pin.
## Motion
- Easing: --ease-out cubic-bezier(0.22, 0.61, 0.36, 1) for reveals and drawers; --ease-io cubic-bezier(0.65, 0, 0.35, 1) for tabs, accordions and builder steps. Nothing bounces.
- Reveal: blocks wrapped in <Reveal> start at opacity 0, translateY(18px) and animate to rest over 700ms --ease-out when 15% visible (Motion whileInView, viewport once). Siblings in a list stagger by 80ms (index prop).
- Hero photo: on load the image scales from 1.07 to 1.0 over 2200ms --ease-out; while scrolling, the image translates 0 to 10% of its height as the hero scrolls out (Motion useScroll on the hero, offset ['start start', 'end start']), and the headline block fades to opacity 0.25 and moves -32px over the same range. H1 lines rise from translateY(26px) and opacity 0 with 120ms stagger, starting 150ms after load.
- Signature drink cards: on hover the photo scales to 1.04 over 700ms --ease-out and the card border turns Espresso; the price ticks up 4px and settles. 'Order this' click: the button crossfades to a Check icon and 'Added' for 1400ms.
- Menu filtering: rows use Motion layout with AnimatePresence mode 'popLayout'; leaving rows fade and slide 8px left over 200ms, remaining rows glide to position over 380ms --ease-io. Tab switch slides a 2px Terracotta underline between tabs with Motion layoutId.
- Order builder: step changes crossfade with a 16px horizontal slide, 280ms --ease-io (AnimatePresence mode 'wait'). Selecting size, milk or extras fills the chip over 150ms; the running total counts to the new value over 400ms; the ticket replaces the form with a fade and a dashed border draw, and the order number types in character by character over 800ms.
- Hours: the open-now dot pulses (scale 1 to 1.25, 1600ms loop) only while open; 'Opens at 6:30am' lines crossfade when the day changes at midnight.
- Block map: on entering view the streets draw (stroke-dashoffset to 0) over 900ms, then the park block fills, then the shop pin drops from scale 0.6 with a soft overshoot and the transit, bike and parking markers pop in with 120ms stagger.
- Header: transparent over the photo hero with Foam text; after 40px of scroll it gets Cream at 94% opacity, backdrop-filter blur(10px), Espresso text and a 1px Rule bottom border, 250ms transition. On menu.html and visit.html it is solid from the start.
- FAQ accordions: height 0 to auto and opacity 0 to 1 over 300ms --ease-io; the Plus icon rotates 45 degrees into an X.
- Links: .link-draw grows a 1px currentColor underline from 0% to 100% width over 300ms --ease-out on hover and focus-visible.
- prefers-reduced-motion: reduce — disable the hero scale and parallax, H1 rise, street draw, pin drop, count-ups, pulse and layout animations (render at rest; tabs and accordions switch instantly). Color and border hover changes stay. Use CSS @media in index.css plus Motion's useReducedMotion in components.
## Imagery
Real photography only, warm and natural, all six made for this template in one consistent style: morning window light, oak and terracotta palette, documentary editorial look, fine grain. No people, no faces, no hands, no readable text, logos, cup branding or menu boards with writing. Every photo uses object-fit cover with the object-position given under Assets, 14px corners, no shadow; photos on Cream get a 1px Rule outline. Captions below photos in Nunito 13px Crema. Drawn in code: the favicon, the wordmark (type only), the illustrated block map, size dots, dietary badge icons, the ticket and dividers. Icons: lucide-react only, stroke width 1.5.
## Tone
Warm, plain and a little playful, like the person behind the counter who remembers your order. Short sentences, concrete numbers (sizes, prices, hours, grams), no coffee-snob vocabulary without a plain-word gloss, no exclamation marks.
---
— Prompt by VibeFather · https://vibefather.ai/t/coffee-shop-website · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown