Shopify Theme Development Overview Build and customize Shopify themes using Liquid templating, JSON templates, sections and blocks for merchant-customizable layouts, and theme app extensions for app integrations. This skill covers the Shopify theme architecture (Online Store 2.0), the Shopify CLI development workflow, performance optimization with lazy loading and critical CSS, and patterns for building flexible sections that merchants can configure through the theme editor. When to Use This Skill - When building a new Shopify theme from scratch or forking Dawn - When creating custom sections…

+ (cents / 100).toFixed(2);\n }\n}\n\ncustomElements.define('variant-selector', VariantSelector);\n```\n\n## Best Practices\n\n- **Use Online Store 2.0 JSON templates** — they enable merchants to add, remove, and reorder sections without editing code\n- **Leverage the `image_url` and `image_tag` filters** — they generate responsive `srcset` attributes automatically from Shopify's CDN\n- **Always include `{{ block.shopify_attributes }}`** — this data attribute is required for the theme editor to identify and select blocks\n- **Defer all JavaScript** — use `defer` or `type=\"module\"` on script tags; avoid render-blocking JS\n- **Use Shopify's native Liquid filters** — `| money`, `| image_url`, `| asset_url` are optimized and handle edge cases; don't reinvent them\n- **Provide section presets** — presets define the default state when a merchant adds a section; without them, the section won't appear in \"Add section\"\n- **Keep sections under 50KB of Liquid** — large sections slow down the Liquid renderer; extract reusable code into snippets\n- **Test on Shopify's staging theme** — always preview changes on an unpublished theme before deploying to the live theme\n\n## Common Pitfalls\n\n| Problem | Solution |\n|---------|----------|\n| Section not appearing in \"Add section\" menu | Ensure the section has a `presets` array in its `{% schema %}`; sections without presets are only available in JSON templates |\n| Theme editor shows \"Error rendering section\" | Check for Liquid syntax errors; use `shopify theme check` to lint your Liquid code |\n| Images not loading on Shopify CDN | Use `image_url` filter with explicit `width` parameter; the old `img_url` filter is deprecated |\n| Cart count badge not updating after AJAX add | Fetch `/cart.js` after every cart mutation and update the badge; don't rely on the response from `add.js` alone |\n| Slow Largest Contentful Paint (LCP) | Preload the hero/product image in `\u003chead>` using `\u003clink rel=\"preload\" as=\"image\">`; inline critical CSS |\n| Metafields not accessible in Liquid | Ensure metafield definitions are created in Shopify admin; access via `product.metafields.namespace.key` |\n\n## Related Skills\n\n- @product-page-design\n- @ecommerce-seo\n- @ecommerce-caching\n- @storefront-performance\n- @shopify-app-development\n---","attachment_filenames":["evals/collection-grid-with-lazy-images-and-pag/criteria.json","evals/collection-grid-with-lazy-images-and-pag/task.md","evals/performance-optimization-and-ajax-cart/criteria.json","evals/performance-optimization-and-ajax-cart/task.md","evals/section-blocks-with-theme-editor-support/criteria.json","evals/section-blocks-with-theme-editor-support/task.md","tile.json"],"attachments":[{"filename":"evals/collection-grid-with-lazy-images-and-pag/criteria.json","content":"{\n \"context\": \"Tests whether the agent builds a Shopify collection grid section using correct Online Store 2.0 JSON templates, native Liquid pagination tags, responsive lazy-loaded images via image_url/image_tag, native money filter, deferred JavaScript, and proper schema presets.\",\n \"type\": \"weighted_checklist\",\n \"checklist\": [\n {\n \"name\": \"JSON template for collection\",\n \"max_score\": 12,\n \"description\": \"A `templates/collection.json` file is produced that references the collection section by key with an `order` array, rather than a Liquid `.liquid` template\"\n },\n {\n \"name\": \"paginate tag used\",\n \"max_score\": 10,\n \"description\": \"Product listing uses `{% paginate collection.products by N %}...{% endpaginate %}` Liquid tags rather than manual slicing\"\n },\n {\n \"name\": \"default_pagination filter\",\n \"max_score\": 10,\n \"description\": \"Pagination navigation uses `{{ paginate | default_pagination }}` filter rather than manually constructing pagination links\"\n },\n {\n \"name\": \"image_url not img_url\",\n \"max_score\": 10,\n \"description\": \"Product card images use `image_url` filter with an explicit `width` parameter — the deprecated `img_url` filter is NOT used anywhere\"\n },\n {\n \"name\": \"image_tag lazy loading\",\n \"max_score\": 8,\n \"description\": \"Product card images use `image_tag` with `loading: 'lazy'`\"\n },\n {\n \"name\": \"image_tag widths and sizes\",\n \"max_score\": 8,\n \"description\": \"Product card `image_tag` calls include both `widths` and `sizes` parameters for responsive images\"\n },\n {\n \"name\": \"money filter for price\",\n \"max_score\": 8,\n \"description\": \"Product card prices use the `| money` Liquid filter, not manual cent division or string formatting\"\n },\n {\n \"name\": \"Schema presets present\",\n \"max_score\": 10,\n \"description\": \"The section's `{% schema %}` includes a non-empty `presets` array\"\n },\n {\n \"name\": \"block.shopify_attributes on blocks\",\n \"max_score\": 8,\n \"description\": \"If the section defines any blocks, every block wrapper element includes `{{ block.shopify_attributes }}`\"\n },\n {\n \"name\": \"JS deferred or module\",\n \"max_score\": 8,\n \"description\": \"Any `\u003cscript>` tags in the section or included assets use `defer` attribute or `type=\\\"module\\\"` — no synchronous render-blocking script tags\"\n },\n {\n \"name\": \"asset_url filter for assets\",\n \"max_score\": 8,\n \"description\": \"CSS and JS files are referenced using `| asset_url` filter rather than hardcoded paths\"\n }\n ]\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":2639,"content_sha256":"81a034f1309109e80261eed91fc2ecb05c09537cfdf765b3724b88859fe7b63d"},{"filename":"evals/collection-grid-with-lazy-images-and-pag/task.md","content":"# Build a Shopify Collection Page Section\n\n## Problem/Feature Description\n\nA home goods retailer is launching a new Shopify store and needs a collection browsing page. Their catalog has hundreds of products across several collections, and shoppers need to be able to browse product thumbnails quickly without the page feeling slow or overwhelming. The team's previous theme used an older Shopify architecture, and the new theme must support the modern theme editor workflow so the marketing team can adjust the layout themselves.\n\nThe collection page should show product cards in a responsive grid, with the product name and price visible under each card. Because many collections have more than 24 products, the page needs to support pagination. Page load speed is a priority: product card images should load efficiently on all screen sizes and should not block the initial render.\n\nAdditionally, the section needs to be configurable from the theme editor, so merchants can tune the number of products per page and optionally enable a sort/filter bar.\n\n## Output Specification\n\nProduce the following theme files:\n\n- `sections/collection-grid.liquid` — the section file with schema\n- `templates/collection.json` — the JSON template that wires up the section\n- Any supporting JS should be placed in `assets/` and referenced appropriately\n\nThe section should render a responsive product grid with card images, titles, and prices. Pagination should work for large collections. Include at least one configurable section setting (e.g. products per page) in the schema.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1568,"content_sha256":"b098b3330f6523cf160edc9ea493f82bcd9859617f765e21f7cea691da087933"},{"filename":"evals/performance-optimization-and-ajax-cart/criteria.json","content":"{\n \"context\": \"Tests whether the agent correctly implements a performance-optimized Shopify theme layout with critical CSS inlining, deferred non-critical CSS, hero image preloading, CDN preconnect hints, deferred JS, and a correct AJAX cart implementation that fetches /cart.js after mutations and updates the badge.\",\n \"type\": \"weighted_checklist\",\n \"checklist\": [\n {\n \"name\": \"preconnect to Shopify CDN\",\n \"max_score\": 8,\n \"description\": \"The layout/theme.liquid `\u003chead>` includes `\u003clink rel=\\\"preconnect\\\" href=\\\"https://cdn.shopify.com\\\" crossorigin>` and `\u003clink rel=\\\"preconnect\\\" href=\\\"https://fonts.shopifycdn.com\\\" crossorigin>`\"\n },\n {\n \"name\": \"Hero image preload tag\",\n \"max_score\": 10,\n \"description\": \"A `\u003clink rel=\\\"preload\\\" as=\\\"image\\\">` tag is conditionally rendered in `\u003chead>` for the product featured image when on a product template (checks `template.name == 'product'`)\"\n },\n {\n \"name\": \"Critical CSS inlined\",\n \"max_score\": 10,\n \"description\": \"Critical CSS content is inlined inside a `\u003cstyle>` tag in `\u003chead>` rather than loaded via an external `\u003clink>` tag\"\n },\n {\n \"name\": \"Non-critical CSS deferred\",\n \"max_score\": 10,\n \"description\": \"Non-critical CSS (e.g. theme.css) uses the `media=\\\"print\\\" onload=\\\"this.media='all'\\\"` pattern to defer loading, with a `\u003cnoscript>` fallback\"\n },\n {\n \"name\": \"JS uses defer attribute\",\n \"max_score\": 8,\n \"description\": \"Main theme JavaScript is loaded with `defer` attribute (or `type=\\\"module\\\"`) on the `\u003cscript>` tag — no render-blocking synchronous script tags\"\n },\n {\n \"name\": \"Cart API add endpoint\",\n \"max_score\": 8,\n \"description\": \"AJAX add-to-cart uses POST to `/cart/add.js` with JSON body containing `items` array\"\n },\n {\n \"name\": \"Cart API change endpoint\",\n \"max_score\": 8,\n \"description\": \"Cart quantity update uses POST to `/cart/change.js` with `id` and `quantity` fields\"\n },\n {\n \"name\": \"Fetch /cart.js after mutation\",\n \"max_score\": 12,\n \"description\": \"After any cart mutation (add or update), `/cart.js` is fetched separately to retrieve the current cart state for UI update — NOT relying solely on the response from `/cart/add.js`\"\n },\n {\n \"name\": \"Cart count badge updated\",\n \"max_score\": 10,\n \"description\": \"The cart item count badge (selected by a data attribute like `[data-cart-count]`) is updated with `cart.item_count` from the `/cart.js` response\"\n },\n {\n \"name\": \"asset_url for stylesheets\",\n \"max_score\": 8,\n \"description\": \"CSS files are referenced using `| asset_url` Liquid filter rather than hardcoded paths or CDN URLs\"\n },\n {\n \"name\": \"content_for_header tag\",\n \"max_score\": 8,\n \"description\": \"The layout includes `{{ content_for_header }}` inside `\u003chead>` and `{{ content_for_layout }}` in the `\u003cbody>`\"\n }\n ]\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":2962,"content_sha256":"ca09ae29ff457ec91faf481252ba4eaa20397447be78d51db0558d02879f30a8"},{"filename":"evals/performance-optimization-and-ajax-cart/task.md","content":"# Optimize Shopify Theme Layout and Implement AJAX Cart\n\n## Problem/Feature Description\n\nA fashion e-commerce brand has been struggling with poor Core Web Vitals scores on their Shopify store. Their Google Search Console shows consistently low scores for Largest Contentful Paint and Total Blocking Time, which is hurting both SEO rankings and conversion rates. A performance audit identified that the main theme layout loads all CSS and JavaScript synchronously, there are no resource hints for the Shopify CDN, and the hero product image is not prioritized.\n\nAdditionally, their \"Add to Cart\" button does a full page reload, which creates a jarring experience. The team wants a seamless AJAX cart where clicking \"Add to Cart\" updates a cart count badge in the header without reloading the page. A known pain point from their previous AJAX implementation was that the cart badge count sometimes got out of sync after adding items — the old code read the count directly from the add response rather than verifying the true cart state.\n\nYour task is to produce an optimized `layout/theme.liquid` file and a `assets/cart.js` file that address both problems.\n\n## Output Specification\n\nProduce the following files:\n\n- `layout/theme.liquid` — a complete theme layout with performance optimizations in the `\u003chead>` and body, including a cart count badge element in the header area\n- `assets/cart.js` — a JavaScript cart manager class that handles add-to-cart, quantity updates, cart state retrieval, and header badge updates\n\nThe layout should handle both product and non-product pages appropriately. The cart implementation should expose a usable API (e.g. `window.cart`) for other scripts to call.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1700,"content_sha256":"ef717e72e2b2a3a1aefd5904ef8807a063aed6649316e85ce51e130fbea6a922"},{"filename":"evals/section-blocks-with-theme-editor-support/criteria.json","content":"{\n \"context\": \"Tests whether the agent correctly builds a merchant-customizable Shopify product section with proper block attributes, schema presets, native Liquid filters, and variant-aware UI. Covers core Online Store 2.0 section patterns required for theme editor compatibility.\",\n \"type\": \"weighted_checklist\",\n \"checklist\": [\n {\n \"name\": \"block.shopify_attributes present\",\n \"max_score\": 12,\n \"description\": \"Every block's wrapper element includes `{{ block.shopify_attributes }}` as an attribute\"\n },\n {\n \"name\": \"Schema has presets array\",\n \"max_score\": 12,\n \"description\": \"The section's {% schema %} JSON includes a non-empty `presets` array so the section appears in the theme editor 'Add section' menu\"\n },\n {\n \"name\": \"image_url filter used\",\n \"max_score\": 10,\n \"description\": \"Product images are rendered using the `image_url` filter (with an explicit `width` parameter), not the deprecated `img_url` filter\"\n },\n {\n \"name\": \"image_tag with lazy loading\",\n \"max_score\": 8,\n \"description\": \"The `image_tag` filter is used with `loading: 'lazy'` for product media images\"\n },\n {\n \"name\": \"image_tag widths and sizes\",\n \"max_score\": 8,\n \"description\": \"The `image_tag` filter includes both `widths` and `sizes` parameters to generate a responsive srcset\"\n },\n {\n \"name\": \"money filter for prices\",\n \"max_score\": 8,\n \"description\": \"All price output uses the `| money` Liquid filter rather than manual formatting\"\n },\n {\n \"name\": \"product form tag used\",\n \"max_score\": 10,\n \"description\": \"The add-to-cart form uses `{% form 'product', product %}` rather than a plain HTML `\u003cform>` tag\"\n },\n {\n \"name\": \"selected_or_first_available_variant\",\n \"max_score\": 10,\n \"description\": \"The hidden variant ID input and availability logic reference `product.selected_or_first_available_variant` (not `product.variants.first` or a hardcoded variant)\"\n },\n {\n \"name\": \"Blocks iterated via section.blocks\",\n \"max_score\": 8,\n \"description\": \"The section renders content by looping over `section.blocks` with `{% for block in section.blocks %}` and using `block.type`\"\n },\n {\n \"name\": \"JSON template uses section reference\",\n \"max_score\": 14,\n \"description\": \"A JSON template file (e.g. product.json) is produced that references the section by key, with an `order` array — not an inline Liquid template\"\n }\n ]\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":2521,"content_sha256":"a6216e587e7bf51d95d2906fdbde896755cbc5d6556a7c6f053da0e54d43dd91"},{"filename":"evals/section-blocks-with-theme-editor-support/task.md","content":"# Build a Customizable Product Section for a Shopify Theme\n\n## Problem/Feature Description\n\nA direct-to-consumer apparel brand is migrating their Shopify store to a new custom theme. The merchandising team needs a product detail page that their non-technical staff can configure through the Shopify theme editor — rearranging the page content, toggling individual elements, and tweaking copy — without touching code. Currently the product page is a monolithic Liquid file that hardcodes every element, so merchants can't customize anything without a developer.\n\nYour task is to build the product section and its accompanying template for the new theme. The section should support the most common product page content blocks (title, price with sale display, variant picker via radio buttons, add-to-cart button that reflects availability, and product description). It should be structured so that the theme editor can identify each block, and the section should be discoverable in the editor's \"Add section\" panel.\n\n## Output Specification\n\nProduce the following files representing the theme structure:\n\n- `sections/main-product.liquid` — the Liquid section with schema\n- `templates/product.json` — the JSON template that uses the section\n- Any snippets you extract for reusability should go under `snippets/`\n\nThe section must work with the standard Shopify product object and support multiple product media types (images and video at minimum). Prices should handle sale scenarios (compare-at price vs current price).\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1526,"content_sha256":"4d9fab868b0db52c33515459f4215f55f91dce694f64983b6269bf1c18c2dfeb"},{"filename":"tile.json","content":"{\n \"name\": \"finsi/shopify-theme-development\",\n \"version\": \"0.1.0\",\n \"summary\": \"Liquid templating, theme architecture, sections, and theme app extensions\",\n \"skills\": {\n \"shopify-theme-development\": {\n \"path\": \"SKILL.md\"\n }\n }\n}\n","content_type":"application/json; charset=utf-8","language":"json","size":245,"content_sha256":"21b2a717eb9e03fe99dae9d364cf7d2bda95750802b8f3d1c45cb1052dfad025"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Shopify Theme Development","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"Build and customize Shopify themes using Liquid templating, JSON templates, sections and blocks for merchant-customizable layouts, and theme app extensions for app integrations. This skill covers the Shopify theme architecture (Online Store 2.0), the Shopify CLI development workflow, performance optimization with lazy loading and critical CSS, and patterns for building flexible sections that merchants can configure through the theme editor.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Use This Skill","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When building a new Shopify theme from scratch or forking Dawn","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When creating custom sections and blocks for the theme editor","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When implementing product pages, collection grids, or cart functionality in Liquid","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When optimizing a Shopify theme for Core Web Vitals and speed","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"When building theme app extensions to inject app content into themes","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Instructions","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Set up the development environment with Shopify CLI","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Install Shopify CLI\nnpm install -g @shopify/cli @shopify/theme\n\n# Initialize a new theme (or clone Dawn)\nshopify theme init my-theme\n\n# Start development server with hot reload\nshopify theme dev --store=your-store.myshopify.com","type":"text"}]},{"type":"paragraph","content":[{"text":"Theme directory structure (Online Store 2.0):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"my-theme/\n├── assets/ # CSS, JS, images\n├── config/ # settings_schema.json, settings_data.json\n├── layout/ # theme.liquid (main layout)\n├── locales/ # Translation files\n├── sections/ # Sections (reusable, merchant-configurable)\n├── snippets/ # Partials (reusable Liquid fragments)\n└── templates/ # JSON templates referencing sections\n ├── product.json\n ├── collection.json\n └── index.json","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create a JSON template with sections","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"json"},"content":[{"text":"// templates/product.json\n{\n \"sections\": {\n \"main\": {\n \"type\": \"main-product\",\n \"settings\": {}\n },\n \"recommendations\": {\n \"type\": \"product-recommendations\",\n \"settings\": {\n \"heading\": \"You may also like\",\n \"products_to_show\": 4\n }\n },\n \"reviews\": {\n \"type\": \"product-reviews\",\n \"settings\": {}\n }\n },\n \"order\": [\"main\", \"recommendations\", \"reviews\"]\n}","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Build a customizable product section with blocks","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"liquid"},"content":[{"text":"{% comment %}\n sections/main-product.liquid\n{% endcomment %}\n\n\u003csection class=\"product-section\" data-section-id=\"{{ section.id }}\">\n \u003cdiv class=\"product-grid\">\n \u003cdiv class=\"product-media\">\n {% for media in product.media %}\n {% case media.media_type %}\n {% when 'image' %}\n \u003cdiv class=\"product-media-item {% if forloop.first %}active{% endif %}\">\n {{ media | image_url: width: 800 | image_tag:\n loading: 'lazy',\n widths: '200,400,600,800,1000',\n sizes: '(min-width: 768px) 50vw, 100vw',\n class: 'product-image'\n }}\n \u003c/div>\n {% when 'video' %}\n \u003cdiv class=\"product-media-item\">\n {{ media | video_tag: autoplay: false, controls: true }}\n \u003c/div>\n {% endcase %}\n {% endfor %}\n \u003c/div>\n\n \u003cdiv class=\"product-info\">\n {% for block in section.blocks %}\n {% case block.type %}\n {% when 'title' %}\n \u003ch1 class=\"product-title\" {{ block.shopify_attributes }}>\n {{ product.title }}\n \u003c/h1>\n\n {% when 'price' %}\n \u003cdiv class=\"product-price\" {{ block.shopify_attributes }}>\n {% if product.compare_at_price > product.price %}\n \u003cs class=\"price-compare\">{{ product.compare_at_price | money }}\u003c/s>\n {% endif %}\n \u003cspan class=\"price-current\">{{ product.price | money }}\u003c/span>\n {% if product.compare_at_price > product.price %}\n \u003cspan class=\"price-badge\">Sale\u003c/span>\n {% endif %}\n \u003c/div>\n\n {% when 'variant_picker' %}\n \u003cdiv class=\"variant-picker\" {{ block.shopify_attributes }}>\n {% for option in product.options_with_values %}\n \u003cfieldset class=\"option-group\">\n \u003clegend>{{ option.name }}\u003c/legend>\n {% for value in option.values %}\n \u003clabel class=\"option-label\">\n \u003cinput\n type=\"radio\"\n name=\"{{ option.name }}\"\n value=\"{{ value }}\"\n {% if option.selected_value == value %}checked{% endif %}\n >\n \u003cspan>{{ value }}\u003c/span>\n \u003c/label>\n {% endfor %}\n \u003c/fieldset>\n {% endfor %}\n \u003c/div>\n\n {% when 'buy_buttons' %}\n \u003cdiv class=\"buy-buttons\" {{ block.shopify_attributes }}>\n {% form 'product', product %}\n \u003cinput type=\"hidden\" name=\"id\" value=\"{{ product.selected_or_first_available_variant.id }}\">\n \u003cdiv class=\"quantity-selector\">\n \u003clabel for=\"quantity\">Quantity\u003c/label>\n \u003cinput type=\"number\" id=\"quantity\" name=\"quantity\" value=\"1\" min=\"1\">\n \u003c/div>\n \u003cbutton\n type=\"submit\"\n class=\"btn btn-primary add-to-cart\"\n {% unless product.selected_or_first_available_variant.available %}disabled{% endunless %}\n >\n {% if product.selected_or_first_available_variant.available %}\n Add to cart — {{ product.selected_or_first_available_variant.price | money }}\n {% else %}\n Sold out\n {% endif %}\n \u003c/button>\n {% endform %}\n \u003c/div>\n\n {% when 'description' %}\n \u003cdiv class=\"product-description\" {{ block.shopify_attributes }}>\n {{ product.description }}\n \u003c/div>\n\n {% when 'custom_text' %}\n \u003cdiv class=\"custom-text\" {{ block.shopify_attributes }}>\n {{ block.settings.text }}\n \u003c/div>\n {% endcase %}\n {% endfor %}\n \u003c/div>\n \u003c/div>\n\u003c/section>\n\n{% schema %}\n{\n \"name\": \"Product Page\",\n \"tag\": \"section\",\n \"class\": \"section-product\",\n \"blocks\": [\n {\n \"type\": \"title\",\n \"name\": \"Title\",\n \"limit\": 1\n },\n {\n \"type\": \"price\",\n \"name\": \"Price\",\n \"limit\": 1\n },\n {\n \"type\": \"variant_picker\",\n \"name\": \"Variant Picker\",\n \"limit\": 1\n },\n {\n \"type\": \"buy_buttons\",\n \"name\": \"Buy Buttons\",\n \"limit\": 1\n },\n {\n \"type\": \"description\",\n \"name\": \"Description\",\n \"limit\": 1\n },\n {\n \"type\": \"custom_text\",\n \"name\": \"Custom Text\",\n \"settings\": [\n {\n \"type\": \"richtext\",\n \"id\": \"text\",\n \"label\": \"Text\"\n }\n ]\n }\n ],\n \"presets\": [\n {\n \"name\": \"Product Page\",\n \"blocks\": [\n { \"type\": \"title\" },\n { \"type\": \"price\" },\n { \"type\": \"variant_picker\" },\n { \"type\": \"buy_buttons\" },\n { \"type\": \"description\" }\n ]\n }\n ]\n}\n{% endschema %}","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Implement AJAX cart with the Cart API","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"javascript"},"content":[{"text":"// assets/cart.js\nclass CartManager {\n async addItem(variantId, quantity = 1) {\n const response = await fetch('/cart/add.js', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n items: [{ id: variantId, quantity }],\n }),\n });\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.description || 'Could not add to cart');\n }\n\n const data = await response.json();\n this.updateCartUI();\n return data;\n }\n\n async updateQuantity(lineKey, quantity) {\n const response = await fetch('/cart/change.js', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: lineKey, quantity }),\n });\n\n const cart = await response.json();\n this.updateCartUI(cart);\n return cart;\n }\n\n async getCart() {\n const response = await fetch('/cart.js');\n return response.json();\n }\n\n async updateCartUI(cart) {\n cart = cart || await this.getCart();\n\n // Update cart count badge\n const badge = document.querySelector('[data-cart-count]');\n if (badge) badge.textContent = cart.item_count;\n\n // Update cart drawer if open\n const drawer = document.querySelector('cart-drawer');\n if (drawer) drawer.render(cart);\n }\n}\n\nwindow.cart = new CartManager();","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Optimize for performance","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"liquid"},"content":[{"text":"{% comment %}\n layout/theme.liquid — Critical performance optimizations\n{% endcomment %}\n\u003c!doctype html>\n\u003chtml lang=\"{{ request.locale.iso_code }}\">\n\u003chead>\n \u003cmeta charset=\"utf-8\">\n \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n \u003c!-- Preconnect to Shopify CDN -->\n \u003clink rel=\"preconnect\" href=\"https://cdn.shopify.com\" crossorigin>\n \u003clink rel=\"preconnect\" href=\"https://fonts.shopifycdn.com\" crossorigin>\n\n \u003c!-- Preload critical assets -->\n {% if template.name == 'product' %}\n {% assign hero_image = product.featured_image %}\n {% if hero_image %}\n \u003clink\n rel=\"preload\"\n as=\"image\"\n href=\"{{ hero_image | image_url: width: 800 }}\"\n imagesrcset=\"{{ hero_image | image_url: width: 400 }} 400w,\n {{ hero_image | image_url: width: 800 }} 800w\"\n imagesizes=\"(min-width: 768px) 50vw, 100vw\"\n >\n {% endif %}\n {% endif %}\n\n \u003c!-- Inline critical CSS -->\n \u003cstyle>\n {{ 'critical.css' | asset_url | stylesheet_tag | split: '\u003clink' | first }}\n \u003c/style>\n\n \u003c!-- Defer non-critical CSS -->\n \u003clink rel=\"stylesheet\" href=\"{{ 'theme.css' | asset_url }}\" media=\"print\" onload=\"this.media='all'\">\n \u003cnoscript>\u003clink rel=\"stylesheet\" href=\"{{ 'theme.css' | asset_url }}\">\u003c/noscript>\n\n {{ content_for_header }}\n\u003c/head>\n\u003cbody>\n {{ content_for_layout }}\n\n \u003c!-- Defer JavaScript -->\n \u003cscript src=\"{{ 'theme.js' | asset_url }}\" defer>\u003c/script>\n\u003c/body>\n\u003c/html>","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create a theme app extension","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Generate a theme app extension block\nshopify app generate extension --type theme_app_extension --name my-app-block","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"liquid"},"content":[{"text":"{% comment %}\n extensions/my-app-block/blocks/product-badge.liquid\n{% endcomment %}\n\u003cdiv class=\"app-product-badge\" {{ block.shopify_attributes }}>\n {% if block.settings.badge_text != blank %}\n \u003cspan\n class=\"badge\"\n style=\"background-color: {{ block.settings.badge_color }};\n color: {{ block.settings.text_color }};\"\n >\n {{ block.settings.badge_text }}\n \u003c/span>\n {% endif %}\n\u003c/div>\n\n{% schema %}\n{\n \"name\": \"Product Badge\",\n \"target\": \"section\",\n \"settings\": [\n {\n \"type\": \"text\",\n \"id\": \"badge_text\",\n \"label\": \"Badge text\",\n \"default\": \"New\"\n },\n {\n \"type\": \"color\",\n \"id\": \"badge_color\",\n \"label\": \"Badge color\",\n \"default\": \"#FF0000\"\n },\n {\n \"type\": \"color\",\n \"id\": \"text_color\",\n \"label\": \"Text color\",\n \"default\": \"#FFFFFF\"\n }\n ]\n}\n{% endschema %}","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Collection grid with lazy-loaded images","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"liquid"},"content":[{"text":"{% comment %} sections/collection-grid.liquid {% endcomment %}\n\u003csection class=\"collection-grid\">\n \u003ch1>{{ collection.title }}\u003c/h1>\n\n \u003cdiv class=\"product-grid\" role=\"list\">\n {% paginate collection.products by 24 %}\n {% for product in collection.products %}\n \u003cdiv class=\"product-card\" role=\"listitem\">\n \u003ca href=\"{{ product.url }}\">\n {% if product.featured_image %}\n {{ product.featured_image | image_url: width: 400 | image_tag:\n loading: 'lazy',\n widths: '200,300,400',\n sizes: '(min-width: 1024px) 25vw, (min-width: 768px) 33vw, 50vw',\n class: 'product-card-image'\n }}\n {% endif %}\n \u003ch2 class=\"product-card-title\">{{ product.title }}\u003c/h2>\n \u003cp class=\"product-card-price\">{{ product.price | money }}\u003c/p>\n \u003c/a>\n \u003c/div>\n {% endfor %}\n\n {% if paginate.pages > 1 %}\n \u003cnav class=\"pagination\" aria-label=\"Pagination\">\n {{ paginate | default_pagination: next: 'Next', previous: 'Previous' }}\n \u003c/nav>\n {% endif %}\n {% endpaginate %}\n \u003c/div>\n\u003c/section>","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Variant change with JavaScript","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"javascript"},"content":[{"text":"// assets/variant-selector.js\nclass VariantSelector extends HTMLElement {\n connectedCallback() {\n this.addEventListener('change', this.onVariantChange.bind(this));\n this.productData = JSON.parse(\n this.querySelector('[type=\"application/json\"]').textContent\n );\n }\n\n onVariantChange() {\n const selectedOptions = [...this.querySelectorAll('input:checked')].map(\n input => input.value\n );\n\n const variant = this.productData.variants.find(v =>\n v.options.every((opt, i) => opt === selectedOptions[i])\n );\n\n if (!variant) return;\n\n // Update URL without reload\n const url = new URL(window.location);\n url.searchParams.set('variant', variant.id);\n window.history.replaceState({}, '', url);\n\n // Update price display\n const priceEl = document.querySelector('.price-current');\n if (priceEl) {\n priceEl.textContent = this.formatMoney(variant.price);\n }\n\n // Update add-to-cart button\n const addToCart = document.querySelector('.add-to-cart');\n const idInput = document.querySelector('input[name=\"id\"]');\n if (addToCart && idInput) {\n idInput.value = variant.id;\n addToCart.disabled = !variant.available;\n addToCart.textContent = variant.available ? 'Add to cart' : 'Sold out';\n }\n }\n\n formatMoney(cents) {\n return '

Shopify Theme Development Overview Build and customize Shopify themes using Liquid templating, JSON templates, sections and blocks for merchant-customizable layouts, and theme app extensions for app integrations. This skill covers the Shopify theme architecture (Online Store 2.0), the Shopify CLI development workflow, performance optimization with lazy loading and critical CSS, and patterns for building flexible sections that merchants can configure through the theme editor. When to Use This Skill - When building a new Shopify theme from scratch or forking Dawn - When creating custom sections…

+ (cents / 100).toFixed(2);\n }\n}\n\ncustomElements.define('variant-selector', VariantSelector);","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use Online Store 2.0 JSON templates","type":"text","marks":[{"type":"strong"}]},{"text":" — they enable merchants to add, remove, and reorder sections without editing code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Leverage the ","type":"text","marks":[{"type":"strong"}]},{"text":"image_url","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" and ","type":"text","marks":[{"type":"strong"}]},{"text":"image_tag","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" filters","type":"text","marks":[{"type":"strong"}]},{"text":" — they generate responsive ","type":"text"},{"text":"srcset","type":"text","marks":[{"type":"code_inline"}]},{"text":" attributes automatically from Shopify's CDN","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Always include ","type":"text","marks":[{"type":"strong"}]},{"text":"{{ block.shopify_attributes }}","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — this data attribute is required for the theme editor to identify and select blocks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Defer all JavaScript","type":"text","marks":[{"type":"strong"}]},{"text":" — use ","type":"text"},{"text":"defer","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"type=\"module\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" on script tags; avoid render-blocking JS","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use Shopify's native Liquid filters","type":"text","marks":[{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"| money","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"| image_url","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"| asset_url","type":"text","marks":[{"type":"code_inline"}]},{"text":" are optimized and handle edge cases; don't reinvent them","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Provide section presets","type":"text","marks":[{"type":"strong"}]},{"text":" — presets define the default state when a merchant adds a section; without them, the section won't appear in \"Add section\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Keep sections under 50KB of Liquid","type":"text","marks":[{"type":"strong"}]},{"text":" — large sections slow down the Liquid renderer; extract reusable code into snippets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test on Shopify's staging theme","type":"text","marks":[{"type":"strong"}]},{"text":" — always preview changes on an unpublished theme before deploying to the live theme","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common Pitfalls","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Problem","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Solution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Section not appearing in \"Add section\" menu","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ensure the section has a ","type":"text"},{"text":"presets","type":"text","marks":[{"type":"code_inline"}]},{"text":" array in its ","type":"text"},{"text":"{% schema %}","type":"text","marks":[{"type":"code_inline"}]},{"text":"; sections without presets are only available in JSON templates","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Theme editor shows \"Error rendering section\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check for Liquid syntax errors; use ","type":"text"},{"text":"shopify theme check","type":"text","marks":[{"type":"code_inline"}]},{"text":" to lint your Liquid code","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Images not loading on Shopify CDN","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"image_url","type":"text","marks":[{"type":"code_inline"}]},{"text":" filter with explicit ","type":"text"},{"text":"width","type":"text","marks":[{"type":"code_inline"}]},{"text":" parameter; the old ","type":"text"},{"text":"img_url","type":"text","marks":[{"type":"code_inline"}]},{"text":" filter is deprecated","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cart count badge not updating after AJAX add","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fetch ","type":"text"},{"text":"/cart.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" after every cart mutation and update the badge; don't rely on the response from ","type":"text"},{"text":"add.js","type":"text","marks":[{"type":"code_inline"}]},{"text":" alone","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Slow Largest Contentful Paint (LCP)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Preload the hero/product image in ","type":"text"},{"text":"\u003chead>","type":"text","marks":[{"type":"code_inline"}]},{"text":" using ","type":"text"},{"text":"\u003clink rel=\"preload\" as=\"image\">","type":"text","marks":[{"type":"code_inline"}]},{"text":"; inline critical CSS","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Metafields not accessible in Liquid","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ensure metafield definitions are created in Shopify admin; access via ","type":"text"},{"text":"product.metafields.namespace.key","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@product-page-design","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@ecommerce-seo","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@ecommerce-caching","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@storefront-performance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@shopify-app-development","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"shopify-theme-development","risk":"safe","tags":["shopify","liquid","theme","sections","blocks","dawn","theme-app-extensions"],"tools":["claude-code","cursor","gemini-cli","copilot","codex-cli","kiro","opencode"],"author":"@skillopedia","source":{"stars":24,"repo_name":"awesome-ecommerce-skills","origin_url":"https://github.com/finsilabs/awesome-ecommerce-skills/blob/HEAD/skills/platform-shopify/shopify-theme-development/SKILL.md","repo_owner":"finsilabs","body_sha256":"d7cfac9bc9a799ad2696dd279d1fcf96e2a54846efab15d388a44585e8a5dd78","cluster_key":"d604c3f411385b5253a886ee1e2f174630cabe0a3de914ac6509c268a377c752","clean_bundle":{"format":"clean-skill-bundle-v1","source":"finsilabs/awesome-ecommerce-skills/skills/platform-shopify/shopify-theme-development/SKILL.md","attachments":[{"id":"152cb350-38e9-5333-8c3d-cd8e3871dacf","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/152cb350-38e9-5333-8c3d-cd8e3871dacf/attachment.json","path":"evals/collection-grid-with-lazy-images-and-pag/criteria.json","size":2639,"sha256":"81a034f1309109e80261eed91fc2ecb05c09537cfdf765b3724b88859fe7b63d","contentType":"application/json; charset=utf-8"},{"id":"e3a0fbae-aa82-577c-8fa4-8c9dd313236d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e3a0fbae-aa82-577c-8fa4-8c9dd313236d/attachment.md","path":"evals/collection-grid-with-lazy-images-and-pag/task.md","size":1568,"sha256":"b098b3330f6523cf160edc9ea493f82bcd9859617f765e21f7cea691da087933","contentType":"text/markdown; charset=utf-8"},{"id":"5a6dc807-61c6-52fc-a2e1-deb4b50775c6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/5a6dc807-61c6-52fc-a2e1-deb4b50775c6/attachment.json","path":"evals/performance-optimization-and-ajax-cart/criteria.json","size":2962,"sha256":"ca09ae29ff457ec91faf481252ba4eaa20397447be78d51db0558d02879f30a8","contentType":"application/json; charset=utf-8"},{"id":"b04561a0-d903-5fb0-9a76-9f8992b92059","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b04561a0-d903-5fb0-9a76-9f8992b92059/attachment.md","path":"evals/performance-optimization-and-ajax-cart/task.md","size":1700,"sha256":"ef717e72e2b2a3a1aefd5904ef8807a063aed6649316e85ce51e130fbea6a922","contentType":"text/markdown; charset=utf-8"},{"id":"6bad1d73-7499-5cec-b5ea-ab097f82b859","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6bad1d73-7499-5cec-b5ea-ab097f82b859/attachment.json","path":"evals/section-blocks-with-theme-editor-support/criteria.json","size":2521,"sha256":"a6216e587e7bf51d95d2906fdbde896755cbc5d6556a7c6f053da0e54d43dd91","contentType":"application/json; charset=utf-8"},{"id":"4fa6c30a-3025-56fc-9825-64b0cd1eb7db","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4fa6c30a-3025-56fc-9825-64b0cd1eb7db/attachment.md","path":"evals/section-blocks-with-theme-editor-support/task.md","size":1526,"sha256":"4d9fab868b0db52c33515459f4215f55f91dce694f64983b6269bf1c18c2dfeb","contentType":"text/markdown; charset=utf-8"},{"id":"1e4cc819-4dd2-5d41-97bb-7f18bfa64064","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1e4cc819-4dd2-5d41-97bb-7f18bfa64064/attachment.json","path":"tile.json","size":245,"sha256":"21b2a717eb9e03fe99dae9d364cf7d2bda95750802b8f3d1c45cb1052dfad025","contentType":"application/json; charset=utf-8"}],"bundle_sha256":"79caa368f547767bdf23751478e215e8cc205c840ecf7d6350409d57669970a1","attachment_count":7,"text_attachments":7,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/platform-shopify/shopify-theme-development/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"web-development","triggers":["build shopify theme","customize shopify template","shopify liquid code","create shopify section"],"platforms":["shopify"],"date_added":"2026-03-12","difficulty":"intermediate","import_tag":"clean-skills-v1","description":"Build and customize Shopify themes using Liquid templating, JSON sections, dynamic blocks, and theme app extensions for added functionality"}},"renderedAt":1782986516169}

Shopify Theme Development Overview Build and customize Shopify themes using Liquid templating, JSON templates, sections and blocks for merchant-customizable layouts, and theme app extensions for app integrations. This skill covers the Shopify theme architecture (Online Store 2.0), the Shopify CLI development workflow, performance optimization with lazy loading and critical CSS, and patterns for building flexible sections that merchants can configure through the theme editor. When to Use This Skill - When building a new Shopify theme from scratch or forking Dawn - When creating custom sections…