7.7 KiB
Braids by Mira — Frontend Visual Overhaul Design
Context
The Phase 1 public site (Home, Shop, Book, Rules) is functionally complete and passed final review, but the visual result is flat: the hero is a plain gradient circle standing in for "3D," no product/service images ever render even though the data model already carries image fields, sections have large dead whitespace gaps, and Book/Rules are plain text stacks with little visual hierarchy. This spec covers a full visual/motion pass across all four existing pages before Phase 2 (backend/admin) work begins. It does not add new pages, routes, or data — it makes the existing structure look and feel like the "Elegant Editorial" design intended in the Phase 1 spec.
Scope
All four existing routes (/, /shop, /book, /rules) get a visual/motion upgrade. The cream/charcoal/gold palette and Georgia/script typography from the original design system are unchanged — this is a richness and polish pass, not a rebrand. The single biggest addition is a real WebGL 3D hero centerpiece, scoped to the Home page only.
Tech Stack Additions
three,@react-three/fiber,@react-three/drei— for the 3D hero scene. These are only imported from Home's hero component, so Vite's route-level code splitting keeps them out of the Shop/Book/Rules bundles.- No other new dependencies. Motion elsewhere continues to use the existing
framer-motionsetup (ScrollReveal,useReducedMotion,useScroll/useTransform).
3D Hero Scene
Hero3DScene replaces the current Hero3D component on the Home page hero:
- A
<Canvas>(react-three-fiber) containing a procedural braided-crown mesh: 5–7 strands built fromTubeGeometryfollowingCatmullRomCurve3paths, arranged radially in a crown silhouette (abstract, not a literal recreation of the logo). - Material: gold
MeshStandardMaterial(color sampled from the--color-goldtoken), lit by one soft key light and one rim light for depth. - Motion: continuous gentle Y-axis rotation via
useFrame, plus additional tilt driven by scroll position (same scroll-linked approach the currentHero3Dalready uses viauseScroll/useTransform, applied to the group's rotation instead of a CSS transform). prefers-reduced-motion: skip mounting the<Canvas>entirely and render the existing static gradient-circle fallback — this both respects the motion preference and avoids the WebGL cost for those users.- The canvas is
aria-hidden="true"since it's decorative; the hero's headline text carries the actual accessible content, consistent with the currentHero3Dpattern. - No 3D asset pipeline is introduced — the mesh is built entirely from code (primitive geometry + curves), so there's no
.glb/.gltffile to source, store, or version.
Imagery
AI-generated placeholder photography, saved as static files under public/, sized reasonably for web (not full-res) with no optimization pipeline beyond that — matches Phase 1's "no backend" scope:
public/products/*.jpg— one image per product (10 total), clean product-on-neutral-background style consistent with the cream/charcoal palette.public/styles/*.jpg— one image per signature style (4 total: knotless, boho, locs, cornrows), on-model shots.public/about/mira-portrait.jpg— one warm editorial-style portrait for Home's About section.public/testimonials/*.jpg— three small circular avatar images, one per testimonial.
No changes to the Product/Service TypeScript interfaces — both already carry an image: string field from Phase 1; this work only points those fields at real generated files and wires the field into rendering, which never happened in Phase 1.
Component changes:
ProductCardandServiceCardrenderproduct.image/service.imagein a fixed-aspect-ratio image region above the existing text content, with a subtle hover-zoom (transform: scale(1.05)on hover, matching the existing hover-lift pattern already used elsewhere).- Home's About section gets the portrait image next to (or behind, TBD at implementation time based on what reads best) the existing bio text.
- Home's testimonial blocks get the small avatar images next to each quote.
Page-by-Page Changes
Home
- Reduce dead whitespace between sections — current
ScrollRevealsections leave large gaps; tighten section padding/margins so content reads as continuous rather than isolated islands. - About section gains the portrait image.
- Signature Styles cards (already
ServiceCard) gain real images via the imagery work above. - Shop Highlights cards gain real images and upgrade from bare
<div>s to usingProductCardstyling (or an equivalent lightweight card) for visual consistency with the Shop page. - Add a subtle parallax offset between text and background layers on scroll (background sections drift slightly slower than foreground text, via
useScroll/useTransform, same toolkit already in use).
Shop
ProductCardimages (from Imagery section above) with hover-zoom.- Tighten grid spacing/card padding for a less sparse layout.
- Category filter pills: replace the static active-color swap with a
framer-motionlayoutIdsliding indicator so the active pill's highlight animates smoothly between filter clicks.
Book
- Add a visual step-progress indicator (4 steps: Service, Date & Time, Contact, Confirmed) shown as labeled dots/segments at the top of the flow, reflecting
useBooking's currentstepstate. - Service picker cards (
ServiceCard) gain images via the imagery work above. - Animate transitions between steps with
framer-motion(slide/fade) instead of the current instant swap.
Rules
- Add a simple inline SVG icon per rule section (deposit, cancellation/lateness, guests & kids, hair prep, health & safety) — small, monochrome, matching the charcoal/gold palette, no icon library dependency.
- Tighten typography rhythm (spacing between title/body, section-to-section spacing).
- Stagger each rule section's entrance on scroll (extend the existing
ScrollRevealusage with per-item delay).
Testing
Hero3DScenegets a test mirroring the currentHero3D.test.tsxpattern: asserts a<canvas>(or its container) renders when motion is allowed, and that the static fallback renders underprefers-reduced-motion— WebGL internals (the actual 3D rendering) are not unit-tested, only the mount/fallback contract, consistent with how the current component is tested.ProductCard/ServiceCardtests are extended to assert the image renders with the correctsrcandalttext (derived fromproduct.name/service.name).- No new test infrastructure needed — same Vitest + React Testing Library setup as Phase 1.
Performance & Accessibility
three/@react-three/fiber/@react-three/dreiare only imported from Home's hero, so they don't inflate the Shop/Book/Rules bundles (Vite's existing route-based code splitting handles this without additional configuration).- All images get descriptive
alttext sourced from existing product/service names — no new copy needed. - The 3D canvas is
aria-hidden="true"; reduced-motion users get the existing static fallback instead of a spinning WebGL scene.
Out of Scope
- Real photography from Mira (placeholder AI imagery is used throughout; swapping to real photos later is just replacing files in
public/, no code changes). - 3D treatment anywhere beyond the Home hero (product cards, other pages) — explicitly hero-only per this spec.
- Any Phase 2 concerns: backend, admin panel, real booking/inquiry submission, image upload/management — unchanged from the Phase 1 spec's scope boundary.
- Rebranding the color palette or typography — this is a richness pass on the existing "Elegant Editorial" system, not a new visual identity.