Getting started
Folder structure
What lives where, and how src maps to dist.
You edit src/. Vite compiles it to dist/, which is the actual Shopify theme
and the only thing ever uploaded.
They are not the same shape. Four rules decide what becomes what:
src/liquid/**
dist/**Same paths, copied through · Except sections, which flatten
src/components/**src/framework/**src/javascript/**src/styles/**
dist/assets/main.js
dist/assets/main.cssCompiled into one bundle · Which is what lets islands share state
src/fonts/**src/media/**
dist/assets/Flattened · Shopify’s assets/ has no subfolders
src/api/**
deploy/netlify/Never uploaded to Shopify · Built separately by api:build
Everything below follows from those four lanes.
The folders
Top level is open; the rest is one click away. Each folder carries where its contents end up.
src/liquidBecomes the Shopify theme, path for paththeme
sectionsFlattened into dist/sections — filenames must be globally unique
src/componentsReact, atomic designbundle
src/javascriptShared runtime. Reach it through @/framework, not directlybundle
src/apiServerless gateway. Copied into deploy/, never into the themenot uploaded
Notes are hidden on narrow screens. Every folder is listed; only the noteworthy files are.
The two rules worth remembering
Section filenames are global. Shopify has no concept of a section subfolder,
so sections/js/hero/hero.liquid and sections/non-js/hero.liquid both become
sections/hero.liquid. The build warns rather than silently overwriting one
with the other.
The same applies to fonts/ and media/ — Shopify's assets/ is flat.
One bundle, on purpose. Everything under components/, framework/,
javascript/ and styles/ compiles into a single assets/main.js. That is what
makes cross-island state work without a library: separate React roots still share
one module instance, so a module-level variable is already shared between them.
See State across islands.
Where generated files come from
Three files are written by the build and should never be edited by hand. All three are gitignored.
| File | Written by | Holds |
|---|---|---|
src/javascript/components.generated.js | the Vite plugin | Every section and island component |
src/javascript/api.generated.js | the Vite plugin | The api registry of operations and services |
src/api/_lib/*.generated.js | npm run api:build | Compiled operations and the service index |
The first two are regenerated on every theme build, so they cannot go stale.
The third is regenerated by api:build, which is also what writes deploy/.
Adding a section
Two files in one folder, named the same:
src/liquid/sections/js/my-thing/├── my-thing.liquid ← markup, JSON payload, schema└── my-thing.jsx ← default export, receives the JSON as propsNo registry to update — the build generates it. See Adding a section.