Skip to content

Latest commit

 

History

History
204 lines (153 loc) · 10.1 KB

File metadata and controls

204 lines (153 loc) · 10.1 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

npm run dev       # Run Shopify CLI dev + Vite dev server in parallel (hot reload)
npm run build     # TypeScript compile + Vite bundle (outputs to assets/)
npm run deploy    # Build then push to Shopify store
shopify theme check  # Lint Liquid files against theme-check:recommended rules

shopify theme dev, shopify theme push, and vite build are also available individually via the corresponding npm scripts.

Package manager: Bun (bun install to install dependencies). npm scripts still work as wrappers.

Development Philosophy

These principles define how all code in this theme should be written. Follow them strictly when adding or modifying any feature.

Code Splitting by Function

Every distinct feature or component lives in its own file. Do not bundle unrelated logic together.

frontend/entrypoints/js/
  global/          # always loaded (variant-picker, modal, etc.) — exists
  components/      # feature-specific (cart-drawer, predictive-search, etc.) — not yet created
  utils/           # pure utility functions (debounce, fetch-helpers, etc.) — not yet created
  • One file = one responsibility. A cart-drawer.js handles only the cart drawer.
  • Global utilities (e.g. debounce, fetchSection) go in js/utils/ and are imported where needed.
  • Avoid adding logic directly to theme.js. Keep it a thin entry point that only orchestrates dynamic imports.

Import Only Where Needed

Use dynamic imports to load components on demand, not on every page.

// theme.js — only load what the page actually needs
if (document.querySelector('variant-picker')) {
  import('./js/global/variant-picker.js');
}
  • Never statically import a component that isn't guaranteed to be on every page.
  • Heavy components (e.g. modals, drawers, video players) must always be lazy-loaded.
  • CSS scoped to a section/block belongs in that file's {% stylesheet %} tag, not in the global bundle.

Reusable and Extensible Classes

Build components as extensible base classes so future variants don't require copy-paste.

// Base class with shared logic
class Drawer extends HTMLElement {
  open() { ... }
  close() { ... }
  trapFocus() { ... }
}

// Specialized class extends and overrides what it needs
class CartDrawer extends Drawer {
  open() {
    super.open();
    this.fetchCart();
  }
}
  • Prefer custom elements (HTMLElement subclasses) for interactive UI components. They are self-contained and compose cleanly with Liquid.
  • Shared behaviors (focus trap, overlay, scroll-lock) live in base classes or utility functions — never duplicated.
  • Schema settings follow the same principle: prefer a generic group block that composes with other blocks over one-off section-specific layout blocks.

CSS Guidelines

  • Component-scoped styles: use {% stylesheet %} in sections/blocks. Shopify deduplicates them automatically.
  • Single CSS property from schema → inline CSS variable: style="--gap: {{ block.settings.gap }}px"
  • Multiple CSS properties from schema → CSS class: class="{{ block.settings.layout }}"
  • Global design tokens live in theme.css under @theme {}. Do not hardcode colors, spacing, or type sizes elsewhere.
  • Tailwind utilities for layout and spacing; {% stylesheet %} for structural/component CSS that Tailwind doesn't cover.

Architecture

This is a Shopify theme built on top of the Shopify Skeleton Theme. It uses Vite (via rolldown-vite — the Rolldown-powered Vite fork, aliased as vite in package.json) for bundling and Tailwind CSS v4 for styling.

Source vs. Compiled

  • frontend/entrypoints/ — source files (TypeScript, CSS). Edit these.
  • assets/ — Vite output with hashed filenames. Do not edit directly.
  • snippets/vite-tag.liquid — auto-generated by vite-plugin-shopify; maps frontend entrypoints to built assets. Do not edit.

CSS

Tailwind CSS v4 is configured via @theme and @source directives directly in frontend/entrypoints/theme.css. There is no tailwind.config.js.

CSS is split into layered entry files:

  • theme.css — root entry, defines CSS custom properties and global styles
  • css/typography.css — font sizes and weights
  • css/spacing.css — spacing scale with responsive breakpoints
  • css/utilities.css — custom Tailwind utilities (scrollbar-hidden, flex-00auto, etc.)

JavaScript

JS is split into per-feature entrypoints. Each file in frontend/entrypoints/ becomes a separate Vite chunk. Loading is controlled by Liquid via {% render 'vite-tag' %} placed directly in the relevant section — not in theme.liquid.

Entrypoint Loaded in Purpose
theme.js layout/theme.liquid Global: mobile menu, announcement bar, header utils
product.js sections/product.liquid Variant picker, image gallery, ATC AJAX
collection.js sections/collection.liquid Filters, sort, quick view, infinite scroll
cart.js sections/header.liquid Cart drawer (global — triggered from header on any page)
search.js sections/header.liquid Predictive search (global — lives in the header)

Shared classes and utilities live in frontend/entrypoints/js/:

  • js/global/variant-picker.js<variant-picker> custom element; fetches updated section HTML on variant change and uses pushState to update the URL.
  • js/global/modal.jsModal base class wrapping native <dialog>; imported by whichever entrypoint needs it.

Rule: never add a component to theme.js unless it runs on every single page. Page/section-specific logic always goes in the matching entrypoint.

Shopify Structure

Directory Purpose
layout/ Full-page wrappers (theme.liquid, password.liquid)
sections/ Merchant-customizable full-width components
blocks/ Nestable components used inside sections (text.liquid, group.liquid)
snippets/ Reusable Liquid partials (not customizable by merchants)
templates/ JSON templates wiring sections to page types
config/ settings_schema.json (editable) and settings_data.json (auto-generated, don't edit)
locales/ Translation strings (en.default.json)

Key Snippets

  • {% render 'vite-tag', with: 'theme.css' %} — renders the correct hashed asset URL
  • {% render 'meta-tags' %} — SEO meta tags in <head>
  • {% render 'image', image: ..., ... %} — responsive image component
  • {% render 'product-variant-picker', product: product %} — variant picker Liquid markup (pairs with <variant-picker> custom element)

Store Configuration

The target store is configured in shopify.theme.toml (gitignored). Vite dev server allows CORS from display-xxx.myshopify.com.


Template Status

Full roadmap and open tasks: GitHub Issue #1

Customer Accounts

This template uses New Customer Accounts (hosted by Shopify on account.shopify.com), not the legacy Liquid-based system. The customer Liquid object is null in the Online Store when new accounts are enabled. Do not rely on it for conditional rendering. Use {{ routes.account_url }} for account links.

What is currently implemented

Area Component Notes
Layout theme.liquid, password.liquid Full-page wrappers
SEO meta-tags.liquid Open Graph, Twitter card, schema.org for products
CSS Tailwind v4 + design tokens Typography, spacing, utilities via @theme
Product Variant picker (<variant-picker>) Fetch-based section re-render, pushState URL update
Product Add-to-cart form Standard Shopify form, no AJAX yet
UI Modal class Wraps native <dialog>, manages body scroll-lock
Images image snippet Responsive images with aspect ratio and lazy loading
Sections header, footer, product, collection, collections, cart, search, article, blog, 404, page, password, index, custom-section All wired to corresponding JSON templates
Blocks group, text Composable layout blocks with schema settings
Customizer Section-level schemas Settings per section; no global settings yet

What is not yet implemented

The following features are pending. When implementing them, follow the Development Philosophy above.

Area Feature Priority
Cart AJAX cart (quantity update, remove, totals) High
Cart Cart Drawer / Mini-cart High
Cart Add-to-cart AJAX (no redirect) High
Navigation Mobile Menu (hamburger drawer, focus-trap) High
Search Predictive Search (<predictive-search>) High
Collection Storefront Filtering (price, tags, variants) High
Collection Sort-by dropdown with URL update High
Product Image gallery (thumbnails, zoom, swipe) High
Customizer settings_schema.json global settings (colors, type, spacing) High
Accessibility Focus management, ARIA live regions, skip-to-content High
Navigation Mega Menu (multi-level, desktop columns) Medium
Navigation Sticky Header Medium
Navigation Announcement Bar Medium
Collection Infinite scroll / Load more Medium
Collection Quick View modal Medium
Product Sticky Add-to-Cart bar Medium
Product Related products (Recommendations API) Medium
Product Media gallery (video, 3D models) Medium
Account Account/logout links in header Medium
Sections Homepage sections (Hero, Image+Text, Testimonials, Newsletter) Medium
DX ESLint + Prettier Medium
DX Theme Check in CI Medium
DX README update (feature tracking) Medium
Product Recently Viewed (localStorage) Low
Collection Breadcrumb Low
Customizer Italian translations (locales/it.default.json) Low