Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:51 +08:00
commit 636e443771
13 changed files with 6987 additions and 0 deletions

View File

@@ -0,0 +1,734 @@
---
name: shopify-theme-dev
description: Complete theme development guide including file structure, JSON templates, sections, snippets, settings schema, and Online Store 2.0 architecture. Use when creating Shopify themes, organizing theme files, building sections and blocks, working with .json template files, configuring settings_schema.json, creating snippets, or implementing theme customization features.
---
# Shopify Theme Development
Expert guidance for Shopify theme development including file structure, Online Store 2.0 architecture, sections, snippets, and configuration.
## When to Use This Skill
Invoke this skill when:
- Creating or modifying Shopify themes
- Working with `.json` template files (Online Store 2.0)
- Building theme sections with schema definitions
- Creating reusable snippets
- Organizing theme file structure
- Configuring `settings_schema.json` for theme settings
- Implementing section blocks and settings
- Setting up theme assets (CSS, JavaScript, images)
- Working with layout files (`theme.liquid`, `password.liquid`)
- Creating template variations with suffixes
## Core Capabilities
### 1. Theme File Structure
Complete directory organization for Shopify themes:
```
theme/
├── assets/ {# Static resources #}
│ ├── style.css {# Main stylesheet #}
│ ├── style.css.liquid {# Dynamic CSS with Liquid #}
│ ├── theme.js {# Main JavaScript #}
│ ├── theme.js.liquid {# Dynamic JS with Liquid #}
│ ├── logo.png {# Images #}
│ └── fonts/ {# Custom fonts #}
├── config/ {# Configuration #}
│ ├── settings_schema.json {# Theme settings UI #}
│ └── settings_data.json {# Default values #}
├── layout/ {# Master templates #}
│ ├── theme.liquid {# Main wrapper #}
│ ├── password.liquid {# Password protection #}
│ └── checkout.liquid {# Checkout (Plus only) #}
├── locales/ {# Translations #}
│ ├── en.default.json {# English #}
│ └── fr.json {# French #}
├── sections/ {# Reusable sections #}
│ ├── header.liquid
│ ├── hero-banner.liquid
│ ├── product-card.liquid
│ └── footer.liquid
├── snippets/ {# Reusable partials #}
│ ├── product-price.liquid
│ ├── product-rating.liquid
│ └── icon.liquid
└── templates/ {# Page templates #}
├── index.json {# Homepage (JSON) #}
├── product.json {# Product page (JSON) #}
├── collection.json {# Collection page (JSON) #}
├── product.liquid {# Product (Liquid - legacy) #}
├── cart.liquid
├── search.liquid
├── page.liquid
├── 404.liquid
└── customers/
├── account.liquid
├── login.liquid
└── register.liquid
```
### 2. JSON Templates (Online Store 2.0)
Modern template format using JSON configuration:
**templates/index.json (Homepage):**
```json
{
"sections": {
"hero": {
"type": "hero-banner",
"settings": {
"heading": "Summer Collection",
"subheading": "New arrivals",
"button_text": "Shop Now",
"button_link": "/collections/all"
}
},
"featured": {
"type": "featured-products",
"blocks": {
"block_1": {
"type": "product",
"settings": {
"product": "snowboard"
}
},
"block_2": {
"type": "product",
"settings": {
"product": "skateboard"
}
}
},
"block_order": ["block_1", "block_2"],
"settings": {
"title": "Featured Products",
"products_to_show": 4
}
}
},
"order": ["hero", "featured"]
}
```
**templates/product.json:**
```json
{
"sections": {
"main": {
"type": "main-product",
"settings": {
"show_vendor": true,
"show_quantity": true,
"enable_zoom": true
}
},
"recommendations": {
"type": "product-recommendations",
"settings": {
"heading": "You may also like",
"products_to_show": 4
}
}
},
"order": ["main", "recommendations"]
}
```
### 3. Section Architecture
Sections are reusable content blocks with schema configuration:
**sections/hero-banner.liquid:**
```liquid
<div class="hero" style="background-color: {{ section.settings.background_color }}">
{% if section.settings.image %}
<img
src="{{ section.settings.image | img_url: '1920x' }}"
alt="{{ section.settings.heading }}"
loading="lazy"
>
{% endif %}
<div class="hero__content">
{% if section.settings.heading != blank %}
<h1>{{ section.settings.heading }}</h1>
{% endif %}
{% if section.settings.subheading != blank %}
<p>{{ section.settings.subheading }}</p>
{% endif %}
{% if section.settings.button_text != blank %}
<a href="{{ section.settings.button_link }}" class="button">
{{ section.settings.button_text }}
</a>
{% endif %}
</div>
</div>
{% stylesheet %}
.hero {
position: relative;
min-height: 500px;
display: flex;
align-items: center;
justify-content: center;
padding: var(--spacing, 2rem);
}
.hero img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
}
.hero__content {
text-align: center;
max-width: 600px;
}
{% endstylesheet %}
{% javascript %}
console.log('Hero banner loaded');
{% endjavascript %}
{% schema %}
{
"name": "Hero Banner",
"tag": "section",
"class": "hero-section",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Welcome"
},
{
"type": "textarea",
"id": "subheading",
"label": "Subheading",
"default": "Discover our collection"
},
{
"type": "image_picker",
"id": "image",
"label": "Background Image"
},
{
"type": "color",
"id": "background_color",
"label": "Background Color",
"default": "#000000"
},
{
"type": "text",
"id": "button_text",
"label": "Button Text",
"default": "Shop Now"
},
{
"type": "url",
"id": "button_link",
"label": "Button Link"
}
],
"presets": [
{
"name": "Hero Banner"
}
]
}
{% endschema %}
```
### 4. Sections with Blocks
Sections can contain dynamic blocks for flexible layouts:
**sections/featured-products.liquid:**
```liquid
<div class="featured-products" {{ section.shopify_attributes }}>
<h2>{{ section.settings.title }}</h2>
<div class="product-grid">
{% for block in section.blocks %}
<div class="product-item" {{ block.shopify_attributes }}>
{% case block.type %}
{% when 'product' %}
{% assign product = all_products[block.settings.product] %}
{% render 'product-card', product: product %}
{% when 'collection' %}
{% assign collection = collections[block.settings.collection] %}
<h3>{{ collection.title }}</h3>
{% for product in collection.products limit: block.settings.products_to_show %}
{% render 'product-card', product: product %}
{% endfor %}
{% when 'heading' %}
<h3>{{ block.settings.heading }}</h3>
{% when 'text' %}
<div class="text-block">
{{ block.settings.text }}
</div>
{% endcase %}
</div>
{% endfor %}
</div>
</div>
{% schema %}
{
"name": "Featured Products",
"tag": "section",
"settings": [
{
"type": "text",
"id": "title",
"label": "Section Title",
"default": "Featured Products"
},
{
"type": "range",
"id": "products_per_row",
"label": "Products per Row",
"min": 2,
"max": 5,
"step": 1,
"default": 4
}
],
"blocks": [
{
"type": "product",
"name": "Product",
"settings": [
{
"type": "product",
"id": "product",
"label": "Product"
}
]
},
{
"type": "collection",
"name": "Collection",
"settings": [
{
"type": "collection",
"id": "collection",
"label": "Collection"
},
{
"type": "range",
"id": "products_to_show",
"label": "Products to Show",
"min": 1,
"max": 12,
"step": 1,
"default": 4
}
]
},
{
"type": "heading",
"name": "Heading",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading Text"
}
]
},
{
"type": "text",
"name": "Text Block",
"settings": [
{
"type": "richtext",
"id": "text",
"label": "Text Content"
}
]
}
],
"presets": [
{
"name": "Featured Products",
"blocks": [
{
"type": "product"
},
{
"type": "product"
},
{
"type": "product"
}
]
}
],
"max_blocks": 12
}
{% endschema %}
```
### 5. Snippets
Reusable template partials:
**snippets/product-card.liquid:**
```liquid
{% comment %}
Usage: {% render 'product-card', product: product, show_vendor: true %}
{% endcomment %}
<div class="product-card">
<a href="{{ product.url }}">
{% if product.featured_image %}
<img
src="{{ product.featured_image | img_url: '400x400' }}"
alt="{{ product.featured_image.alt | escape }}"
loading="lazy"
>
{% else %}
{{ 'product-1' | placeholder_svg_tag: 'placeholder' }}
{% endif %}
</a>
<div class="product-card__info">
{% if show_vendor and product.vendor != blank %}
<p class="product-card__vendor">{{ product.vendor }}</p>
{% endif %}
<h3 class="product-card__title">
<a href="{{ product.url }}">{{ product.title }}</a>
</h3>
<div class="product-card__price">
{% render 'product-price', product: product %}
</div>
{% unless product.available %}
<p class="sold-out">Sold Out</p>
{% endunless %}
</div>
</div>
```
**snippets/product-price.liquid:**
```liquid
{% comment %}
Usage: {% render 'product-price', product: product %}
{% endcomment %}
{% if product.compare_at_price > product.price %}
<span class="price price--sale">
{{ product.price | money }}
</span>
<span class="price price--compare">
{{ product.compare_at_price | money }}
</span>
<span class="price__badge">
Save {{ product.compare_at_price | minus: product.price | money }}
</span>
{% else %}
<span class="price">
{{ product.price | money }}
</span>
{% endif %}
{% if product.price_varies %}
<span class="price__from">from</span>
{% endif %}
```
### 6. Settings Schema
Complete theme customization interface:
**config/settings_schema.json:**
```json
[
{
"name": "theme_info",
"theme_name": "My Theme",
"theme_version": "1.0.0",
"theme_author": "Your Name",
"theme_documentation_url": "https://...",
"theme_support_url": "https://..."
},
{
"name": "Colors",
"settings": [
{
"type": "header",
"content": "Color Scheme"
},
{
"type": "color",
"id": "color_primary",
"label": "Primary Color",
"default": "#000000"
},
{
"type": "color",
"id": "color_secondary",
"label": "Secondary Color",
"default": "#ffffff"
},
{
"type": "color_background",
"id": "color_body_bg",
"label": "Body Background"
}
]
},
{
"name": "Typography",
"settings": [
{
"type": "font_picker",
"id": "type_header_font",
"label": "Heading Font",
"default": "helvetica_n7"
},
{
"type": "font_picker",
"id": "type_body_font",
"label": "Body Font",
"default": "helvetica_n4"
},
{
"type": "range",
"id": "type_base_size",
"label": "Base Font Size",
"min": 12,
"max": 24,
"step": 1,
"default": 16,
"unit": "px"
}
]
},
{
"name": "Layout",
"settings": [
{
"type": "select",
"id": "layout_style",
"label": "Layout Style",
"options": [
{ "value": "boxed", "label": "Boxed" },
{ "value": "full-width", "label": "Full Width" },
{ "value": "wide", "label": "Wide" }
],
"default": "full-width"
},
{
"type": "checkbox",
"id": "layout_sidebar_enabled",
"label": "Enable Sidebar",
"default": true
}
]
},
{
"name": "Header",
"settings": [
{
"type": "image_picker",
"id": "logo",
"label": "Logo"
},
{
"type": "range",
"id": "logo_max_width",
"label": "Logo Width",
"min": 50,
"max": 300,
"step": 10,
"default": 150,
"unit": "px"
},
{
"type": "link_list",
"id": "main_menu",
"label": "Main Menu"
},
{
"type": "checkbox",
"id": "header_sticky",
"label": "Sticky Header",
"default": false
}
]
},
{
"name": "Social Media",
"settings": [
{
"type": "header",
"content": "Social Accounts"
},
{
"type": "url",
"id": "social_twitter",
"label": "Twitter URL",
"info": "https://twitter.com/username"
},
{
"type": "url",
"id": "social_facebook",
"label": "Facebook URL"
},
{
"type": "url",
"id": "social_instagram",
"label": "Instagram URL"
}
]
}
]
```
### 7. Layout Files
Master template wrappers:
**layout/theme.liquid:**
```liquid
<!doctype html>
<html lang="{{ request.locale.iso_code }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>
{{ page_title }}
{%- if current_tags %} &ndash; {{ 'general.meta.tags' | t: tags: current_tags.join(', ') }}{% endif -%}
{%- if current_page != 1 %} &ndash; {{ 'general.meta.page' | t: page: current_page }}{% endif -%}
{%- unless page_title contains shop.name %} &ndash; {{ shop.name }}{% endunless -%}
</title>
{{ content_for_header }}
<link rel="stylesheet" href="{{ 'style.css' | asset_url }}">
<script src="{{ 'theme.js' | asset_url }}" defer></script>
</head>
<body class="template-{{ request.page_type }}">
{% section 'header' %}
<main role="main">
{{ content_for_layout }}
</main>
{% section 'footer' %}
</body>
</html>
```
## Common Settings Input Types
All 28+ input types for theme customization:
- `text` - Single line text
- `textarea` - Multi-line text
- `html` - HTML editor
- `richtext` - WYSIWYG editor
- `number` - Numeric input
- `range` - Slider
- `checkbox` - Boolean toggle
- `select` - Dropdown menu
- `radio` - Radio buttons
- `color` - Color picker
- `color_background` - Color with gradient
- `image_picker` - Upload image
- `media` - Image or video
- `url` - URL input
- `font_picker` - Font selector
- `product` - Product picker
- `collection` - Collection picker
- `page` - Page picker
- `blog` - Blog picker
- `article` - Article picker
- `link_list` - Menu picker
- `date` - Date picker
- `video_url` - Video URL (YouTube, Vimeo)
See [references/settings-schema.md](references/settings-schema.md) for complete examples.
## Best Practices
1. **Use JSON templates** for Online Store 2.0 compatibility
2. **Make sections dynamic** with blocks for merchant flexibility
3. **Add `shopify_attributes`** to section/block containers for theme editor
4. **Provide sensible defaults** in schema settings
5. **Use snippets** for repeated UI components
6. **Add `{% stylesheet %}` and `{% javascript %}`** blocks in sections for scoped styles
7. **Include accessibility** attributes (ARIA labels, alt text)
8. **Test in theme editor** to ensure live preview works
9. **Document snippet parameters** with comments
10. **Use semantic HTML** for better SEO
## Detailed References
- **[references/settings-schema.md](references/settings-schema.md)** - Complete input type reference
- **[references/section-patterns.md](references/section-patterns.md)** - Common section architectures
- **[references/template-examples.md](references/template-examples.md)** - JSON template patterns
## Integration with Other Skills
- **shopify-liquid** - Use when working with Liquid code within theme files
- **shopify-performance** - Use when optimizing theme load times and asset delivery
- **shopify-api** - Use when fetching data via Ajax for dynamic sections
- **shopify-debugging** - Use when troubleshooting theme editor or rendering issues
## Quick Reference
```liquid
{# Section with settings #}
{% schema %}
{
"name": "Section Name",
"settings": [...],
"blocks": [...],
"presets": [...]
}
{% endschema %}
{# Access section settings #}
{{ section.settings.setting_id }}
{# Loop through blocks #}
{% for block in section.blocks %}
{{ block.settings.text }}
{{ block.shopify_attributes }}
{% endfor %}
{# Render snippet with parameters #}
{% render 'snippet-name', param: value %}
{# Access theme settings #}
{{ settings.color_primary }}
{# Section attributes for theme editor #}
<div {{ section.shopify_attributes }}>...</div>
<div {{ block.shopify_attributes }}>...</div>
```

View File

@@ -0,0 +1,753 @@
# Settings Schema - Complete Input Type Reference
All 28+ input types for `settings_schema.json` with examples.
## Text Inputs
### text
Single-line text input:
```json
{
"type": "text",
"id": "store_name",
"label": "Store Name",
"default": "My Store",
"placeholder": "Enter store name",
"info": "This appears in the header"
}
```
### textarea
Multi-line text input:
```json
{
"type": "textarea",
"id": "footer_text",
"label": "Footer Text",
"default": "© 2025 My Store. All rights reserved.",
"placeholder": "Enter footer text"
}
```
### html
HTML code editor:
```json
{
"type": "html",
"id": "custom_html",
"label": "Custom HTML",
"default": "<p>Welcome to our store!</p>",
"info": "Add custom HTML code"
}
```
### richtext
WYSIWYG rich text editor:
```json
{
"type": "richtext",
"id": "announcement_content",
"label": "Announcement Bar Content",
"default": "<p>Free shipping on orders over $50!</p>"
}
```
## Numeric Inputs
### number
Numeric input field:
```json
{
"type": "number",
"id": "products_per_page",
"label": "Products Per Page",
"default": 12,
"min": 1,
"max": 100,
"step": 1,
"info": "Number of products to show per page"
}
```
### range
Slider input:
```json
{
"type": "range",
"id": "columns",
"label": "Number of Columns",
"min": 2,
"max": 6,
"step": 1,
"default": 4,
"unit": "columns",
"info": "Adjust the grid layout"
}
```
**Common units:**
- `px` - Pixels
- `%` - Percentage
- `em` - Em units
- `rem` - Root em units
- Custom text (like "columns", "items")
## Boolean Inputs
### checkbox
Toggle checkbox:
```json
{
"type": "checkbox",
"id": "show_search",
"label": "Show Search Bar",
"default": true,
"info": "Display search in header"
}
```
### boolean
Boolean setting (same as checkbox):
```json
{
"type": "boolean",
"id": "enable_feature",
"label": "Enable Feature",
"default": false
}
```
## Selection Inputs
### select
Dropdown menu:
```json
{
"type": "select",
"id": "layout_style",
"label": "Layout Style",
"options": [
{
"value": "boxed",
"label": "Boxed"
},
{
"value": "full-width",
"label": "Full Width"
},
{
"value": "wide",
"label": "Wide"
}
],
"default": "full-width",
"info": "Choose your layout style"
}
```
### radio
Radio button selection:
```json
{
"type": "radio",
"id": "text_alignment",
"label": "Text Alignment",
"options": [
{ "value": "left", "label": "Left" },
{ "value": "center", "label": "Center" },
{ "value": "right", "label": "Right" }
],
"default": "center"
}
```
## Color Inputs
### color
Color picker:
```json
{
"type": "color",
"id": "primary_color",
"label": "Primary Color",
"default": "#000000",
"info": "Main brand color"
}
```
### color_background
Color with gradient support:
```json
{
"type": "color_background",
"id": "section_background",
"label": "Section Background",
"default": "linear-gradient(#ffffff, #000000)"
}
```
**Supports:**
- Solid colors: `#ffffff`
- Linear gradients: `linear-gradient(#fff, #000)`
- Radial gradients
- With opacity
## Media Inputs
### image_picker
Image upload and selection:
```json
{
"type": "image_picker",
"id": "logo",
"label": "Logo Image",
"info": "Recommended size: 300x100px"
}
```
Access in Liquid:
```liquid
{% if settings.logo %}
<img src="{{ settings.logo | img_url: '300x' }}" alt="{{ shop.name }}">
{% endif %}
{{ settings.logo.width }}
{{ settings.logo.height }}
{{ settings.logo.alt }}
{{ settings.logo.src }}
```
### media
Image or video picker:
```json
{
"type": "media",
"id": "hero_media",
"label": "Hero Media",
"accept": ["image", "video"],
"info": "Upload image or video"
}
```
### video_url
Video URL input (YouTube, Vimeo):
```json
{
"type": "video_url",
"id": "promo_video",
"label": "Promo Video",
"accept": ["youtube", "vimeo"],
"placeholder": "https://www.youtube.com/watch?v=...",
"info": "YouTube or Vimeo URL"
}
```
Access in Liquid:
```liquid
{% if settings.promo_video %}
{{ settings.promo_video.type }} {# youtube or vimeo #}
{{ settings.promo_video.id }} {# Video ID #}
{% endif %}
```
## Typography Inputs
### font_picker
Google Fonts selector:
```json
{
"type": "font_picker",
"id": "heading_font",
"label": "Heading Font",
"default": "helvetica_n7",
"info": "Font for headings"
}
```
**Font format:** `family_weight`
- `n4` - Normal 400
- `n7` - Bold 700
- `i4` - Italic 400
Access in Liquid:
```liquid
{{ settings.heading_font.family }}
{{ settings.heading_font.weight }}
{{ settings.heading_font.style }}
{# CSS font face #}
<style>
{{ settings.heading_font | font_face }}
h1, h2, h3 {
font-family: {{ settings.heading_font.family }}, {{ settings.heading_font.fallback_families }};
font-weight: {{ settings.heading_font.weight }};
font-style: {{ settings.heading_font.style }};
}
</style>
```
## Resource Pickers
### product
Product selector:
```json
{
"type": "product",
"id": "featured_product",
"label": "Featured Product",
"info": "Select a product to feature"
}
```
Access in Liquid:
```liquid
{% assign product = all_products[settings.featured_product] %}
{{ product.title }}
{{ product.price | money }}
```
### collection
Collection selector:
```json
{
"type": "collection",
"id": "featured_collection",
"label": "Featured Collection",
"info": "Select a collection to feature"
}
```
Access in Liquid:
```liquid
{% assign collection = collections[settings.featured_collection] %}
{{ collection.title }}
{% for product in collection.products limit: 4 %}
{{ product.title }}
{% endfor %}
```
### page
Page selector:
```json
{
"type": "page",
"id": "about_page",
"label": "About Page",
"info": "Link to about page"
}
```
Access in Liquid:
```liquid
{% assign page = pages[settings.about_page] %}
<a href="{{ page.url }}">{{ page.title }}</a>
{{ page.content }}
```
### blog
Blog selector:
```json
{
"type": "blog",
"id": "main_blog",
"label": "Main Blog",
"info": "Select your primary blog"
}
```
Access in Liquid:
```liquid
{% assign blog = blogs[settings.main_blog] %}
{{ blog.title }}
{% for article in blog.articles limit: 3 %}
{{ article.title }}
{% endfor %}
```
### article
Article (blog post) selector:
```json
{
"type": "article",
"id": "featured_article",
"label": "Featured Article",
"info": "Select an article to feature"
}
```
### link_list
Menu/navigation selector:
```json
{
"type": "link_list",
"id": "main_menu",
"label": "Main Navigation",
"default": "main-menu",
"info": "Select menu for header"
}
```
Access in Liquid:
```liquid
{% assign menu = linklists[settings.main_menu] %}
{% for link in menu.links %}
<a href="{{ link.url }}">{{ link.title }}</a>
{% if link.links.size > 0 %}
{# Nested links #}
{% for child_link in link.links %}
<a href="{{ child_link.url }}">{{ child_link.title }}</a>
{% endfor %}
{% endif %}
{% endfor %}
```
## URL Inputs
### url
URL input field:
```json
{
"type": "url",
"id": "twitter_url",
"label": "Twitter URL",
"placeholder": "https://twitter.com/username",
"info": "Your Twitter profile URL"
}
```
## Date & Time Inputs
### date
Date picker:
```json
{
"type": "date",
"id": "sale_end_date",
"label": "Sale End Date",
"info": "When the sale ends"
}
```
Access in Liquid:
```liquid
{{ settings.sale_end_date | date: '%B %d, %Y' }}
```
## Organization Elements
### header
Visual separator with heading:
```json
{
"type": "header",
"content": "Color Scheme Settings",
"info": "Configure your color palette"
}
```
Not a setting, just a visual divider in the settings panel.
### paragraph
Informational text block:
```json
{
"type": "paragraph",
"content": "These settings control the appearance of your product cards. Make sure to preview changes on different screen sizes."
}
```
## Advanced Inputs
### liquid
Liquid code editor:
```json
{
"type": "liquid",
"id": "custom_liquid",
"label": "Custom Liquid Code",
"info": "Add custom Liquid code"
}
```
### inline_richtext
Inline rich text (no `<p>` wrapper):
```json
{
"type": "inline_richtext",
"id": "banner_text",
"label": "Banner Text",
"default": "Welcome to <strong>our store</strong>!",
"info": "Text without paragraph wrapper"
}
```
## Complete Example
Full settings schema with multiple sections:
```json
[
{
"name": "theme_info",
"theme_name": "Professional Theme",
"theme_version": "1.0.0",
"theme_author": "Your Name",
"theme_documentation_url": "https://docs.example.com",
"theme_support_url": "https://support.example.com"
},
{
"name": "Colors",
"settings": [
{
"type": "header",
"content": "Brand Colors"
},
{
"type": "color",
"id": "color_primary",
"label": "Primary Brand Color",
"default": "#2196F3"
},
{
"type": "color",
"id": "color_secondary",
"label": "Secondary Color",
"default": "#FFC107"
},
{
"type": "header",
"content": "Background Colors"
},
{
"type": "color_background",
"id": "color_body_bg",
"label": "Body Background",
"default": "#FFFFFF"
},
{
"type": "color_background",
"id": "color_header_bg",
"label": "Header Background",
"default": "linear-gradient(#FFFFFF, #F5F5F5)"
}
]
},
{
"name": "Typography",
"settings": [
{
"type": "paragraph",
"content": "Select fonts for your store. Changes preview in real-time."
},
{
"type": "font_picker",
"id": "type_header_font",
"label": "Heading Font",
"default": "helvetica_n7",
"info": "Font for all headings"
},
{
"type": "font_picker",
"id": "type_body_font",
"label": "Body Font",
"default": "helvetica_n4",
"info": "Font for body text"
},
{
"type": "range",
"id": "type_base_size",
"label": "Base Font Size",
"min": 12,
"max": 24,
"step": 1,
"default": 16,
"unit": "px"
}
]
},
{
"name": "Header",
"settings": [
{
"type": "image_picker",
"id": "logo",
"label": "Logo Image"
},
{
"type": "range",
"id": "logo_width",
"label": "Logo Width",
"min": 50,
"max": 300,
"step": 10,
"default": 150,
"unit": "px"
},
{
"type": "link_list",
"id": "main_menu",
"label": "Main Menu",
"default": "main-menu"
},
{
"type": "checkbox",
"id": "header_sticky",
"label": "Sticky Header",
"default": true,
"info": "Header stays visible while scrolling"
},
{
"type": "select",
"id": "header_style",
"label": "Header Style",
"options": [
{ "value": "minimal", "label": "Minimal" },
{ "value": "classic", "label": "Classic" },
{ "value": "centered", "label": "Centered" }
],
"default": "classic"
}
]
},
{
"name": "Product Pages",
"settings": [
{
"type": "checkbox",
"id": "product_show_vendor",
"label": "Show Vendor",
"default": true
},
{
"type": "checkbox",
"id": "product_show_sku",
"label": "Show SKU",
"default": false
},
{
"type": "select",
"id": "product_image_size",
"label": "Image Size",
"options": [
{ "value": "small", "label": "Small" },
{ "value": "medium", "label": "Medium" },
{ "value": "large", "label": "Large" }
],
"default": "medium"
},
{
"type": "product",
"id": "related_product",
"label": "Related Product"
}
]
},
{
"name": "Social Media",
"settings": [
{
"type": "header",
"content": "Social Media Accounts"
},
{
"type": "url",
"id": "social_twitter",
"label": "Twitter",
"placeholder": "https://twitter.com/username"
},
{
"type": "url",
"id": "social_facebook",
"label": "Facebook",
"placeholder": "https://facebook.com/username"
},
{
"type": "url",
"id": "social_instagram",
"label": "Instagram",
"placeholder": "https://instagram.com/username"
}
]
}
]
```
## Best Practices
1. **Group related settings** into logical sections
2. **Provide clear labels and info text** for guidance
3. **Set sensible defaults** for all settings
4. **Use appropriate input types** for each setting
5. **Add placeholder text** for URL and text inputs
6. **Use headers and paragraphs** to organize complex sections
7. **Limit range values** to reasonable min/max
8. **Test in theme customizer** to ensure good UX
9. **Document dependencies** between settings
10. **Consider mobile experience** when choosing input types