Restyle the storefront
There are two ways to make a Beluga store look like yours, and they stack. The theme editor covers palette, corner radius, logo and typeface with no code. Forking the storefront components covers everything else. Do the first before the second, because a replacement component should still read the theme tokens or it stops matching the rest of the store the moment a merchant opens the editor.
1. The theme editor
Section titled “1. The theme editor”Settings → Look. Primary colour, accent, page background, light or dark scheme, a corner radius from 0 to 4 px, a logo, and a font.
The font needs two fields. A font stack alone only renders on a machine that already
has the face installed, so Font stylesheet URL holds the stylesheet that defines
it: for Google Fonts, the href out of the <link> they give you. Saving it widens
the store’s Content-Security-Policy by exactly the origins that stylesheet needs,
which is why fonts.gstatic.com gets allowed even though it appears nowhere in the
URL you pasted. The preview cannot show a typeface you have not saved yet, for the
same reason.
Settings → Landing page sets the hero: heading, a line of text, a button label and target, and a background image. Leave any empty and the storefront falls back to the store name and a Shop everything button.
2. The tokens
Section titled “2. The tokens”Everything above lands on :root as --beluga-* custom properties: --beluga-ink,
--beluga-muted, --beluga-line, --beluga-surface, --beluga-page,
--beluga-primary, --beluga-on-primary, --beluga-accent, --beluga-on-accent,
--beluga-radius. src/index.css carries the light values as a first-paint
fallback; src/lib/theme.ts is the source of truth for both schemes. Read colours
and radius from these in anything you write.
3. Replace the landing page
Section titled “3. Replace the landing page”src/pages/LandingPage.tsx is presentation. It reads store.hero and two helpers,
getFeaturedProducts and getVisibleCollections from shared/catalog.ts, and
nothing else depends on its internals. Rewrite it. A custom landing page
is a worked example that keeps the hero fallbacks and adds a section of its own.
4. Replace the product card
Section titled “4. Replace the product card”src/components/product/ProductCard.tsx takes a name, a preformatted price string,
an image and a sold-out flag. It takes no Product and calls nothing from shared/,
on purpose, so the theme editor can render a real-looking card with no catalogue
behind it. ProductList.tsx is the thin layer above it that turns a Product[]
into those props via formatPriceRange and isSoldOut.
Replace the card freely. If you replace the list too, keep it deriving price and sold-out state from the catalogue rather than caching them; that is the cart rule applied one layer up. A custom product card.
5. The header and footer
Section titled “5. The header and footer”src/components/layout/Banner.tsx and Footer.tsx build their links from
store.pages and the visible collections. Read the footer once before rewriting
it: it deliberately lists every published page whether or not it is in the
header menu. That is the only way a returns policy a merchant publishes but forgets
to add to the menu is still one link from every page of the shop. Keep that
behaviour.
6. Email
Section titled “6. Email”emails/*.hbs are Handlebars: a body.hbs and subject.hbs per template, a shared
layout.hbs, and an items.hbs partial. The locals are pre-formatted display
strings, so a template does no arithmetic and cannot get money wrong by rounding it
twice. Restyle them as HTML email allows.
What not to touch while you are in there
Section titled “What not to touch while you are in there”CartPage.tsx, ConfirmPage.tsx and ProductDetails.tsx look like the files
above and are not. Each is the specific place an invariant is enforced on the
client: the cart holds identifiers and re-derives every price on render, the
confirmation page polls for status rather than assuming payment, and the quantity
control re-clamps against stock when the variant changes. The styling around those
rules is yours; the rules are not. The seams has the full map.