This document gives new teammates a map of the theme with a focus on the custom services we ship (stringing, knotting, gripping, remix, and T-shirt printing). Keep it close when you are onboarding a new store or chasing a regression in one of the services.
- Install Node 18+ and pnpm. Log in with
shopify loginbefore running any CLI commands. - Pull the latest theme files with
pnpm run pull(wrap it with the correctSHOPIFY_FLAG_STORE=<store>.myshopify.com). - Start local development via
pnpm devornpm run dev. Both proxy toshopify theme devand honourSHOPIFY_FLAG_STORE. - Run
npx shopify theme checkbefore you ship to keep Liquid lint clean. - Format with
npx prettier --write .(the repo has@shopify/prettier-plugin-liquidconfigured). - Preact bundles are built in
reax/. Runcd reax && pnpm install && pnpm buildafter you touch anything underreax/src/**.
- Theme assets live where Dawn expects them: global layouts in
layout/, sections insections/, reusable snippets insnippets/, translations inlocales/, and settings inconfig/. - Service UI is server-rendered by snippets in
snippets/and hydrated by the matching Preact bundles compiled intoassets/vx-*.jsfromreax/src/components/**. - All services write configuration onto
window.s3_*.assets/product-form.jsreads those flags when a shopper clicks "Add to cart" and adds the right mix of main product, service variants, and accessory SKUs in one bundle. - Shared styles for service cards live in
assets/services.css. Tweak in there rather than touching base Dawn CSS.
What shoppers see
Customers pick "Pro Stringing" on eligible rackets, choose a string, colour, tension, and optionally upgrade to four-knot stringing. The UI is rendered by snippets/stringing.liquid and hydrated by reax/src/components/stringing (compiled to assets/vx-stringing.js).
Toggle switches
settings.is_stringing_enabled_globallymust be true.- The product needs metafield
custom_but_hidden.studio_pro_stringing(boolean or enum). Valuestrungmakes the "factory strung" copy render. - Set
settings.stringing_collection_idto the numeric Shopify collection id that holds string SKUs (the code wraps it ingid://shopify/Collection/<id>before querying). Optional:settings.tennis_stringing_collection_idif you mirror the feature for tennis. - Enable
settings.is_knotting_enabled_globallyto surface the 2-knot vs 4-knot choice.
Shopify data to create
- Hidden service products:
- Handle
studio-pro-stringing(contains the paid service variant). - Handle
studio-four-knots-service(upsell when a customer selects four knots).
- Handle
- Collection of string products linked to
settings.stringing_collection_id. - Each string product needs:
Metafields > custom > durability | control | repulsion_power | hitting_sound | shock_absorptionwith numeric values (out of 10) used for filtering and charts.Metafield custom_but_hidden.short_description(displayed under the title).Metafield custom_but_hidden.product_tag(optional badge).- Option 1 colour values with swatches enabled so the UI pulls the hex from
optionValues[].swatch.color.
- On the racket itself, set
Metafield custom.maximum_racket_tensionso the tension picker hides options above the safe limit.
How it adds to cart
snippets/stringing.liquidexposes the service variant ids viawindow.s3_stringing_service_variant_idandwindow.s3_four_knots_service_variant_id.- When the shopper submits the form,
assets/product-form.jslooks for checked inputs namedstring-variant,string-tension, andknot-configand adds:- the stringing service variant,
- the selected string variant,
- and (if four knots selected) the four-knot service variant.
All line items share a
_bundleIdso they stay grouped.
New store checklist
- Create the two hidden service products with the exact handles listed above.
- Ensure every racket that should offer stringing has the
studio_pro_stringingmetafield populated and amaximum_racket_tensionvalue. - Populate the string collection and map its numeric id into theme settings.
- Flip on the stringing and knotting checkboxes in theme settings once products, collections, and metafields are in place.
- Translate copy under
locales/en.default.json > studio.stringing.*(duplicate keys were intentional; keep them synced if you localise).
What shoppers see
Eligible rackets surface a "Gripping Service" card. Customers can keep the factory grip or pick from curated aftermarket grips. Hydration comes from reax/src/components/gripping compiled to assets/vx-gripping.js.
Toggle switches
settings.is_gripping_enabled_globallymust be true.- Product metafield
custom_but_hidden.studio_grip_servicemust be set. settings.gripping_collection_idpoints to the collection of grip SKUs.- Optional
settings.factory_grip_imageadds the marketing image for the "no grip" option.
Shopify data to create
- Hidden service product with handle
studio-gripping-service. - Collection of grip products referenced by
settings.gripping_collection_id. - Each grip product uses:
custom_but_hidden.short_descriptionfor the UI blurb.- Colour swatches on option values so the picker can render circles.
How it adds to cart
snippets/gripping.liquidemitswindow.s3_gripping_service_variant_idand a hidden input#selected-grip-variant-idthat keeps the chosen variant id and sku.assets/product-form.jschecks that hidden field and adds both the service variant and the selected grip variant (again tagged with_bundleId).
New store checklist
- Build the grip collection, note its numeric id, and drop it into theme settings.
- Create the
studio-gripping-serviceproduct and lock it from storefront visibility. - Confirm product metafields and translations
studio.gripping.*exist.
What shoppers see
Racket or paddle products with the Remix flag render a "Personalise" line item. Clicking loads a Radix modal powered by reax/src/components/remix (assets/vx-remix.js) that overlays a 3D model with editable decals.
Toggle switches
settings.is_remix_enabled_globallymust be true.- Product metafield
custom_but_hidden.stickersmust be truthy. - The selected variant needs metafield
custom_but_hidden.rmx_3d_modelpointing to a media item or metaobject whosenamematches an assetassets/rmx-<name>.glb.
Shopify data to create
- Hidden service products:
- Handle
remixfor rackets. - Handle
paddle-remixfor pickleball paddles.
- Handle
- Variant-level metafields used to skin the configurator:
rmx_racket_frame_colorrmx_racket_grip_colorrmx_logo_colorrmx_sticker_text_color
- Optional: upload matching
mono3.ttfandSpaceMono-Regular.ttf(already in assets) if you replicate on a new store.
How it adds to cart
snippets/remix.liquidwriteswindow.s3_remix_service_variant_idandwindow.s3_paddle_remix_service_variant_id.- The Preact app exposes
window.s3_remix_modal_controller.openModal()so the Liquid label can open the modal. assets/product-form.jslooks for the rendered#the-stickerelement and adds the correct remix service variant with encoded sticker text.
New store checklist
- Upload the
.glbmodels toassets/with thermx-<name>.glbnaming scheme. - Populate the remix service products and hide them from the storefront.
- Configure variant metafields for colours and set the
stickersmetafield on eligible products. - Translate copy under
locales/en.default.json > studio.remix.*if you localise.
What shoppers see
Apparel flagged for personalisation shows a "Make this T-Shirt yours" option. The modal (from reax/src/components/tshirt-printing, compiled to assets/vx-tshirt-printing.js) lets customers preview up to 12 alphanumeric characters on a render of the product colourway.
Toggle switches
settings.is_tshirt_printing_enabled_globallymust be true.- Product metafield
custom_but_hidden.customisemust be truthy.
Shopify data to create
- Hidden service product handle
t-shirt-printing. - Variant metafields to drive the preview:
tpr_t_shirt_color(hex) for the garment fill.tpr_text_color(hex) for the printed text.
- Optional texture asset
tshirt-texture.pngalready lives inassets/; swap if the illustration changes.
How it adds to cart
snippets/tshirt-printing.liquidsetswindow.s3_tshirt_printing_service_variant_idand loads the module lazily.- The Preact modal sets
#the-tshirt-text.assets/product-form.jsreads that value and adds the printing service variant with text metadata when the shopper checks out.
New store checklist
- Create the
t-shirt-printingproduct and hide it from sales channels. - Populate variant metafields for every colourway.
- Confirm the product carries the
customisemetafield toggle. - Update translations under
locales/en.default.json > studio.tshirt_printing.*when localising.
- Create all hidden service products with handles:
studio-pro-stringingstudio-four-knots-servicestudio-gripping-serviceremixpaddle-remixt-shirt-printingKeep them in the "Services" product type and hide from all channels.
- Build the collections referenced by theme settings and capture their numeric ids (Shopify Admin -> open the collection -> copy the number at the end of the URL).
- Configure theme settings under "Product Customisations" (toggle checkboxes, paste collection ids, upload optional factory grip image).
- Create and assign product metafields:
- Booleans for
studio_pro_stringing,studio_grip_service,stickers,customise. - Numbers for
maximum_racket_tension. - Variant-level colour metafields listed above.
- String product metric metafields under
customnamespace.
- Booleans for
- Upload supporting assets (
rmx-*.glb, optional textures) intoassets/. - Verify translations exist in
locales/en.default.jsonfor thestudio.*namespaces. Duplicated English strings are placeholders-replace them with store-specific copy or locales. - Run through the CX journey in
shopify theme dev: select each service, add to cart, and confirmcart.jsshows bundled line items with_bundleIdproperties.
- Theme snippets:
snippets/stringing.liquid,snippets/gripping.liquid,snippets/remix.liquid,snippets/tshirt-printing.liquid. - Service scripts:
assets/vx-stringing.js,assets/vx-gripping.js,assets/vx-remix.js,assets/vx-tshirt-printing.js(source inreax/src/components/**). - Cart orchestration:
assets/product-form.js. - Shared styles:
assets/services.css. - Theme settings:
config/settings_schema.json("Product Customisations" group) and defaults inconfig/settings_data.json. - Translation keys:
locales/en.default.jsonunder thestudio.*namespace buckets.
- Always rebuild the Preact bundles (
cd reax && pnpm build) before you push service changes, otherwise Shopify will still serve the previousassets/vx-*.jsfiles. - Use the browser console to inspect
window.s3_*coverage if a bundle fails-missing values usually point to misconfigured handles or metafields. - If a collection id is wrong, the Preact fetch falls back to the "empty" translation and logs to console; keep DevTools open while testing.
- Theme Check will not catch missing metafields, so keep this README's checklist handy when onboarding a new store.
Welcome aboard-reach out in #dev-themes if any of these flows diverge from what you see locally.