A minimal, carefully structured Shopify theme with a Vite-powered asset pipeline, built for modularity, maintainability, and Shopify best practices.
-
Template-specific asset loading (no global JS bloat)
- Centralized routing in
layout/theme.liquidbased onrequest.page_type - Global bootstrap in
frontend/entrypoints/ts/theme.ts - Per-template entrypoints in
frontend/entrypoints/ts/*
- Centralized routing in
-
Vite + Shopify integration
- Fast local development with HMR
- Automatic asset manifest +
snippets/vite-tag.liquidgeneration - Remote dev support with tunnel for Shopify domain previews
-
TypeScript-ready frontend architecture
- TS entrypoints in
frontend/entrypoints/ts/ - Shared utilities in
frontend/entrypoints/ts/utils/ typecheckgate withtsc --noEmit
- TS entrypoints in
-
Branch-linked deploy workflow
- Built assets are committed to branch for Shopify Git-connected themes
- CI validates quality gates (
typecheck,vite:build,theme-check)
dev: Run Shopify + Vite locally (developmentenvironment)dev:remote: Run Shopify + Vite with tunnel enabledbuild: Build production assets with Vitetypecheck: Run TypeScript checks without emitting filesvite:dev: Start Vite dev server onlyvite:build: Build Vite assets onlyshopify:dev: Start Shopify theme dev server (developmentenvironment)
-
Install dependencies:
bun install
-
Create local config files:
cp .env.example .env cp example.shopify.theme.toml shopify.theme.toml
-
Set your store domain in
.env:SHOPIFY_STORE_DOMAIN=your-store.myshopify.com
-
Start local development:
bun run dev
-
If you need preview/editor on the Shopify domain:
bun run dev:remote
.
├── assets/ # Vite-built assets (hashed JS/CSS) + manifest
│ └── .vite/manifest.json
├── blocks/ # Reusable Liquid blocks
├── config/ # Theme settings
├── frontend/
│ └── entrypoints/
│ ├── css/
│ │ └── main.css # Global CSS (loaded on every page)
│ └── ts/
│ ├── theme.ts # Global bootstrap/shared setup
│ ├── index.ts # Home
│ ├── product.ts # PDP
│ ├── collection.ts # PLP
│ ├── cart.ts
│ ├── search.ts
│ ├── blog.ts
│ ├── article.ts
│ ├── page.ts
│ ├── 404.ts
│ ├── password.ts
│ ├── gift-card.ts
│ └── utils/
├── layout/
│ ├── theme.liquid # Main layout + centralized JS router
│ └── password.liquid
├── sections/ # Page sections
├── snippets/
│ └── vite-tag.liquid # Auto-generated by vite-plugin-shopify
├── templates/ # JSON templates + gift_card.liquid
├── vite.config.js
├── tsconfig.json
└── package.json- Always loaded:
css/main.cssts/theme.ts
- Template-specific:
ts/product.ts,ts/collection.ts, etc.
- Do not render
vite-tagin section files.- Asset loading is managed in layouts/templates.
.env(local, gitignored)SHOPIFY_STORE_DOMAIN=your-store.myshopify.com
shopify.theme.toml(local, gitignored)- Shopify CLI environment config (
development)
- Shopify CLI environment config (
example.shopify.theme.toml(committed)- Template for local environment setup
If your Shopify theme is connected directly to a Git branch, Shopify does not run Vite build for you.
Required flow:
- Run:
bun run build
- Commit generated files:
assets/*assets/.vite/manifest.jsonsnippets/vite-tag.liquid
- Push the branch
main: production-ready branch (connected to production theme)staging: QA/integration branch (connected to staging theme)feat/*: feature branches
Flow:
- Build feature on
feat/* - PR to
staging - QA on staging theme
- Merge
stagingintomain
- CSS not loading in local preview:
- Ensure
bun run devis running.
- Ensure
- CSS not loading on
myshopify.compreview:- Use
bun run dev:remote(Chrome loopback/PNA limitation).
- Use
- Port conflicts:
lsof -nP -iTCP:5173 -sTCP:LISTENlsof -nP -iTCP:9292 -sTCP:LISTEN
This project uses the Shopify Skeleton Theme license; see LICENSE.md.