Static marketing site for Boba Mantra.
npm install
npm run devOpens http://localhost:5173. Editing index.html reloads the page automatically.
| Script | What it does |
|---|---|
npm run dev |
Vite dev server with live reload |
npm run build |
Copies the site into dist/ (no bundling — see below) |
npm run preview |
Serves the built dist/ on http://localhost:4173 |
index.html is a dc-runtime document, not a module-based React app. The page holds a
template inside <x-dc> plus a component class in <script type="text/x-dc">;
support.js compiles both at runtime and mounts them with React. That is why there is no
src/ folder and no bundling step — the browser gets the HTML essentially as authored.
index.html— the source of truth. Edit this file. It began as a design-tool export and has since gained a<title>/<meta description>, the local-React shim, the responsive layer and the mobile nav. Re-exporting the design over the top of it would discard all of that — port changes in by hand instead. (The original.dc.htmlexports have been removed; they are in git history if one is ever needed.)support.js— the dc-runtime (template parser + React mount). Generated; don't edit.image-slot.js— the<image-slot>custom element used for the photo tiles.uploads/— images and video used by the page.vendor/— React 18.3.1 UMD builds, copied out ofnode_modulesbyscripts/vendor.mjs. The runtime would otherwise fetch React from unpkg; pointingwindow.__resourcesat these local copies (see the shim near the top ofindex.html) keeps the page working without a CDN.
Google Fonts is still loaded over the network. Without it the layout is intact but falls back to system fonts.
The design was authored desktop-first with inline styles, so the responsive rules live in a
single <style> block near the top of index.html (search for RESPONSIVE LAYER). Because
inline styles outrank stylesheet rules, every override in that block needs !important —
that is deliberate, not sloppiness. Layout hooks are the bm-* classes on the markup.
Breakpoints:
| Width | What changes |
|---|---|
| ≤ 1180px | Section gutters tighten |
| ≤ 1024px | Matcha spotlight, craft columns and contact/map stack to one column; menu grid relaxes to 340px tracks |
| ≤ 900px | Nav bar collapses to a hamburger + slide-down panel; menu becomes one column; hero art scales down |
| ≤ 620px | Phone pass — gutters, type scale, carousel card width, stacked form, wrapped map badge, centered footer |
| ≤ 480px | Logo sprite drops to 40px (bmLogoPlaySm keeps the sprite frames aligned) |
| ≤ 400px | Small-phone pass — narrower price columns, single-column contact details |
Also handled: no horizontal page scroll from 280px up, hover: effects disabled on touch so
taps don't leave cards stuck mid-transform, 16px form fields so iOS doesn't zoom on focus,
scroll-margin-top so the sticky nav doesn't cover anchored sections, and
prefers-reduced-motion support.
Verified with headless Chrome viewport emulation at 280 / 320 / 390 / 412 / 430 / 768 / 844 (landscape) / 1024 / 1280 / 1440 / 1920 — no overflow and no console errors at any width.
Because nothing is bundled, npm run build is a plain file copy (scripts/build.mjs) of
index.html, support.js, image-slot.js, vendor/ and uploads/ into dist/. dist/ is
~6 MB, mostly uploads/, and can be deployed to any static host as-is.
Every file in the repo is reachable from the page or the build; there are no unused design exports or spare assets left in the tree.