AgentSkillsCN

theme-extension

当用户询问“主题扩展”“应用区块”“Liquid 模板”“应用嵌入”“门店渲染”“应用代理”,或任何 Theme App Extension 开发相关需求时,可运用此技能。它将提供以 Liquid 为主导的门店渲染模式,最大限度减少 JavaScript 的使用。

SKILL.md
--- frontmatter
name: theme-extension
description: Use this skill when the user asks about "theme extension", "app blocks", "Liquid templates", "app embed", "storefront rendering", "app proxy", or any Theme App Extension development work. Provides patterns for Liquid-first storefront rendering with minimal JavaScript.

Theme App Extension Development

Quick Reference

TopicReference File
Block Schema, Settings, App Embedreferences/app-blocks.md
Loading States, Async Fetch Patternreferences/async-data.md
App Proxy Config, Backend Handlerreferences/app-proxy.md

Overview

Theme App Extensions use Shopify's native Liquid rendering for optimal storefront performance. Content is server-rendered before reaching the customer's browser.

When to Use

ApproachUse For
Theme ExtensionStatic/semi-static content, SEO-critical content
ScripttagHighly interactive widgets, real-time updates

Directory Structure

code
extensions/theme-extension/
├── blocks/                    # App blocks (merchant can position)
│   ├── feature-block.liquid
│   └── badge.liquid
├── snippets/                  # Reusable Liquid snippets
├── assets/                    # JS/CSS files
└── locales/
    └── en.default.json        # Translations

Liquid-First Rendering

liquid
{% comment %} Data from metafields {% endcomment %}
{% assign items = product.metafields.app_namespace.items.value %}

{% if items.size > 0 %}
  <div class="items-list">
    {% for item in items %}
      {% render 'item-card', item: item %}
    {% endfor %}
  </div>
{% else %}
  <p class="no-items">{{ 'app.no_items' | t }}</p>
{% endif %}

Minimal JavaScript Pattern

When JS is Needed

Use JS ForKeep in Liquid
Form submissionStatic content display
File uploadBadges and indicators
Pagination/load moreProduct lists
Real-time validationSEO content

Minimal JS Structure

javascript
(function() {
  'use strict';
  const config = window.APP_CONFIG || {};

  function initForms() {
    document.querySelectorAll('[data-app-form]').forEach(form => {
      form.addEventListener('submit', handleSubmit);
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initForms);
  } else {
    initForms();
  }
})();

Translations

json
{
  "app": {
    "title": "Feature Title",
    "submit": "Submit",
    "success": "Submitted successfully"
  }
}
liquid
{{ 'app.title' | t }}
{{ 'app.count' | t: count: items.size }}

Performance Guidelines

Do's

PracticeWhy
Render in LiquidServer-side = faster
Use snippetsReusable, cacheable
Defer JS loadingNon-blocking
Scope CSSAvoid conflicts

Don'ts

AvoidWhy
Heavy JS frameworksBundle size
Inline stylesCache miss
Blocking scriptsSlow page load

Checklist

code
Block Development:
- Schema defines all settings
- Uses snippets for reusable parts
- Translations for all text
- Scoped CSS (no global pollution)
- Minimal/no inline JS

Performance:
- JS deferred or async
- CSS in stylesheet (not inline)
- Images lazy loaded
- No external dependencies
- Bundle < 20KB total