Часто шукають

↑↓ вибрати ↵ відкрити Усі результати →

Розробникам · Теми

Розробка тем

Тема — тека файлів: Liquid, CSS, переклади й налаштування. Структура, theme.json, як почати, перевірки під час імпорту і перша тема за 30 хвилин.

Тема задає вигляд магазину, але не торгівлю: ціна, наявність, кнопка «купити», кошик і оформлення замовлення — компоненти ядра. Тема ставить їх у потрібне місце тегом {% component %} і оформлює. Мова шаблонів — Liquid з назвами обʼєктів як у Shopify.

Довідники до цієї статті:

Структура

my-theme/
  theme.json                   маніфест: id, назва, версія, стилі
  config/settings_schema.json  глобальні налаштування теми
  sections/<handle>.liquid     секції: Liquid + {% schema %}
  snippets/<handle>.liquid     сніпети для {% render %} і сторінки теми
  assets/                      CSS, зображення, шрифти, іконки
  locales/uk.json, en.json     слова теми для фільтра t
  design/*.json                токени, стилі, шапка, підвал, шаблони сторінок
  README.md                    нотатки автора (не входить у тему)
ЩоЛіміт
Пакетдо 300 файлів і 10 МБ; zip в адмінці — до 12 МБ
Один файлдо 1 МБ
Сніпетдо 64 КБ
Liquid однієї секції чи сніпетадо 50 000 символів; довший не рендериться
CSS-файлдо 60 000 символів; решта відкидається
Перекладиlocales/<мова>.json — лише рядки, до 256 КБ; мови — ті, що підтримує вітрина: uk, en, ru, de, es, fr, it, pl, pt
Файли assets/css, png, jpg, jpeg, gif, webp, avif, svg, ico, woff2, woff; js, mjs, json, map — лише для магазину, якому дозволено JavaScript

Будь-який інший файл у пакеті — помилка імпорту з назвою файлу. У zip пропускаються теки, файли з крапкою на початку імені (.DS_Store) і __MACOSX; теку .git у архів не кладіть.

theme.json

{
  "storeforma_theme": 1,
  "id": "ua.my-studio.bloom",
  "name": "Bloom",
  "version": "1.0.0",
  "author": "My Studio",
  "description": "Світла тема для квіткових магазинів.",
  "stylesheets": ["kit.css", "theme.css"],
  "kit": "pages",
  "menus": [{"handle": "mega", "name": "Мегаменю"}]
}
КлючОбовʼязковийЩо
storeforma_themeтакФормат пакета: 1.
idтакЗворотний домен, який належить вам: ua.my-studio.bloom. com.storeforma.* і id офіційних тем зарезервовано; id, закріплений за іншою організацією, відхиляється. Короткий id (bloom) — для теми одного магазину.
nameтакНазва, до 120 символів.
versionтакsemver: 1.0.0. Виправлення — нова версія.
author, descriptionніДо 120 і 1000 символів.
stylesheetsніДо 5 CSS-файлів з assets/, підключаються на кожній сторінці вітрини в цьому порядку. З набором сторінок kit.css ставте першим, свій CSS — після нього.
kitні"pages" — тема бере спільні сторінки (кошик, оформлення, кабінет, вхід, 404, пошук, сторінки записів) і assets/kit.css з набору Storeforma, якщо не має свого файлу з тим самим імʼям. Докладно — /docs/theme-pages.
supportsніВиди сторінок, які оформлює дизайн теми: home, product, content, entry, entry-list, collection, search, blog, article, cart. На кожен потрібен шаблон <вид>.default у design/templates.json, інакше імпорт зупиняється.
menusніДо 10 меню, яких чекають секції: {handle, name}. Встановлення створює порожні, яких у магазині немає. main і footer-store вбудовані.
content_typesніТипи контенту, яких чекають секції. Встановлення створює відсутні типи й додає бракуючі поля; нічого не видаляє.

З чого почати

  1. Від офіційної теми. Дизайн → Теми: встановіть тему, найближчу до задуму (Forma — еталон, де кожна сторінка — свій шаблон; Primitive — стартова з коментарями). Потім «Експорт поточної теми»: вкажіть назву — zip отримає власний id з неї, а не id офіційної теми.
  2. Стартова тема. «Стартова тема (zip)» на тій самій сторінці або — Primitive з вашим id і версією 0.1.0.
  3. Правки на сайті. Дизайн → Код теми — секції активної теми: Liquid і схема, перевірка під час збереження. Сніпети, CSS і переклади змінюйте в zip, через CLI або асистентом.
  4. Асистент магазину змінює будь-який файл теми: один-два файли — одразу, більшу переробку — пакетом у своїй пісочниці. Кожну зміну ви схвалюєте карткою; JavaScript — лише після перегляду коду.
  5. Імпорт. «Імпорт теми з файлу» — zip теки або JSON-пакет .

З терміналом або AI-агентом

node storeforma-agent.mjs theme init ua.my-studio.bloom   # нова тема з Primitive
node storeforma-agent.mjs theme pull ./theme              # або поточна тема магазину
node storeforma-agent.mjs theme check ./bloom             # перевірка на сервері, нічого не зберігає
node storeforma-agent.mjs theme dev ./bloom --open        # перегляд лише для вас: сторінка оновлюється після кожного збереження
node storeforma-agent.mjs theme push ./bloom --publish    # встановити

theme dev ставить у магазин окрему копію теми «<id>.dev» і друкує посилання на перегляд: воно відкриває копію лише у вашому браузері на 12 годин, з плашкою «Перегляд теми» внизу, а сторінка сама перезавантажується після кожного збереження файлу. Покупці бачать опубліковану тему, чернетка дизайну магазину лишається як була. --path /shop відкриває потрібну сторінку. Для розробки візьміть безкоштовний магазин у розробці з шаблоном і демоданими — посилання відкриває й його. Коли тема готова — theme push ./bloom --publish. Оновлення теми не перезаписує секції, які магазин змінив у себе; щоб замінити й їх — theme push --replace-edits.

Покроково для дизайнера

Потрібні лише Node.js 20 або новіший і будь-який редактор коду. Docker, локальний сервер і база не потрібні: тема показується на справжньому магазині з його товарами, кошиком і оформленням, але бачите її лише ви.

1. Магазин для роботи. Партнер створює безкоштовний магазин у розробці в кабінеті («Партнерам», блок «Магазини для клієнтів») і обирає шаблон — у магазині одразу будуть демо-товари, категорії й сторінки. Можна працювати й у магазині клієнта: покупці нічого не побачать, доки ви не опублікуєте тему.

2. Клієнт терміналу. Завантажте storeforma-agent.mjs (адмінка магазину → «Контент → MCP і термінал») у теку проєкту й підключіться до магазину: відкриється браузер, де ви підтверджуєте доступ. Для theme push --publish позначте «Дизайн і стилі».

node storeforma-agent.mjs login --store mystore.storeforma.shop

3. Тека теми. Почніть з офіційної стартової теми або з поточної теми магазину; щоб відштовхнутися від іншої офіційної — встановіть її в «Дизайн → Теми» і стягніть theme pull:

node storeforma-agent.mjs theme init ua.my-studio.bloom   # нова тема з Primitive у ./ua.my-studio.bloom
node storeforma-agent.mjs theme pull ./bloom              # або поточна тема магазину

4. Живий перегляд. Запустіть theme dev і не закривайте термінал: кожне збереження файлу відправляє тему в магазин як копію «<id>.dev», а відкрита сторінка сама перезавантажується за секунду-дві.

node storeforma-agent.mjs theme dev ./bloom --open              # головна
node storeforma-agent.mjs theme dev ./bloom --open --path /shop  # одразу каталог

Посилання діє 12 годин і лише в тому браузері, де ви його відкрили; внизу сторінки — плашка «Перегляд теми · Вийти». Перевіряйте і телефон: відкрийте те саме посилання на телефоні або звузьте вікно до 390 px. Помилка Liquid чи CSS показується в терміналі з назвою файлу, а сторінка лишається на попередній версії.

5. Що редагувати. Вигляд — assets/theme.css на змінних магазину (var(--store-primary), var(--store-paper) …): власник потім змінює кольори й шрифти в «Стилі магазину». Розмітку сторінок — snippets/*-page.liquid і snippets/product-card.liquid; секції головної — sections/*.liquid. Кнопку «у кошик», варіанти, галерею й оформлення ставте компонентами ({% component 'commerce.add-to-cart' %}), не своїм кодом. CSS теми перекриває стилі Storeforma без !important.

6. Перевірка й публікація. theme check перевіряє теку так само, як імпорт; theme push встановлює тему під її справжнім id, а --publish одразу її публікує (кольори, шрифти й шаблони з design/ — у чернетку дизайну, її публікують у редакторі шаблонів).

node storeforma-agent.mjs theme check ./bloom
node storeforma-agent.mjs theme push ./bloom --publish

Перевірки під час імпорту

Імпорт, theme check і збереження файлу асистентом проходять ті самі перевірки. Перша помилка зупиняє встановлення й називає файл.

ПеревіркаЩо означає
Маніфестstoreforma_theme: 1, id, name, semver; stylesheets — існуючі CSS з assets/; supports — лише відомі види з шаблоном <вид>.default.
ФайлиЛише відомі шляхи, типи й ліміти зі списку вище.
СекціїСхема: name до 120 символів, до 60 налаштувань відомих типів, до 20 типів блоків, max_blocks 1–50, select і radio з options, коректний enabled_on.
LiquidКожна секція й сніпет розбираються; синтаксична помилка зупиняє імпорт.
CSS@import, expression(), javascript: і url() на інші сайти вирізаються; url() на файли теми й шляхи магазину лишаються.
ПерекладиJSON-обʼєкт, лише рядки, до 256 КБ.
Сторінка товаруНазва, ціна, галерея, наявність, вибір варіанта й кнопка «У кошик» — по одному на шаблон товару; повтор дозволено лише в sticky-bar.
IdНе офіційний і не чужий.

Після імпорту перевірте тему руками: порожній магазин, товар без фото, товар з варіантами, довгі назви, телефон 390 px. Секція, що падає під час рендеру, на вітрині не показується, а в превʼю редактора показує помилку на своєму місці.

Перша тема за 30 хвилин

Мінімальна тема Bloom: одна секція з налаштуванням і блоками, власна картка товару, слова в locales і CSS на змінних магазину. Решту сторінок дає набір спільних сторінок.

1. theme.json:

{
  "storeforma_theme": 1,
  "id": "ua.my-studio.bloom",
  "name": "Bloom",
  "version": "0.1.0",
  "author": "My Studio",
  "stylesheets": ["kit.css", "theme.css"],
  "kit": "pages"
}

2. sections/bloom-picks.liquid — заголовок і блоки «Товар» та «Примітка». Текст заголовка за замовчуванням — з перекладу, тож порожнє поле говорить мовою сторінки, а вписаний власником текст перемагає. Блок додатка (@app) рендерить render_block.

{%- assign title = section.settings.title | default: 'sec.picks_title' | t -%}
<section class="bloom-picks">
  <h2 class="bloom-picks__title">{{ title }}</h2>
  <div class="bloom-picks__grid">
    {% for block in section.blocks %}
      {% if block.type == 'product' and block.settings.product %}
        <div {{ block.attributes }}>{% component 'product.card', product: block.settings.product.id %}</div>
      {% elsif block.type == 'note' %}
        <p class="bloom-picks__note" {{ block.attributes }}>{{ block.settings.text }}</p>
      {% else %}
        {% render_block block %}
      {% endif %}
    {% endfor %}
  </div>
  {% if section.blocks.size == 0 and request.design_mode %}<p>{{ 'ui.choose_product' | t }}</p>{% endif %}
</section>

{% schema %}
{
  "name": "Bloom: добірка",
  "settings": [
    {"id": "title", "type": "text", "label": "Заголовок (порожньо — текст теми)", "default": ""}
  ],
  "blocks": [
    {"type": "product", "name": "Товар", "settings": [{"id": "product", "type": "product", "label": "Товар"}]},
    {"type": "note", "name": "Примітка", "settings": [{"id": "text", "type": "text", "label": "Текст"}]},
    {"type": "@app"}
  ],
  "max_blocks": 8
}
{% endschema %}

3. snippets/product-card.liquid — тепер кожна картка в каталозі, пошуку й добірках малюється цим сніпетом. Ціна в картці вже відформатована; купівля — компонентом.

<article class="bloom-card">
  <a class="bloom-card__media" href="{{ product.url }}">
    {% if product.featured_image %}
      <img src="{{ product.featured_image.src }}" srcset="{{ product.featured_image.srcset }}" sizes="(min-width: 1024px) 25vw, 50vw" alt="{{ product.title }}" loading="lazy">
    {% endif %}
    {% if product.discount_percent %}<span class="bloom-card__sale">−{{ product.discount_percent }}%</span>{% endif %}
  </a>
  <a class="bloom-card__title" href="{{ product.url }}">{{ product.title }}</a>
  {% component 'product.swatches', limit: 5 %}
  <p class="bloom-card__price">{% if product.compare_at_price %}<s>{{ product.compare_at_price }}</s> {% endif %}{{ product.price }}</p>
  {% unless product.available %}<p class="bloom-card__muted">{{ 'ui.sold_out' | t }}</p>{% endunless %}
  {% component 'commerce.add-to-cart' %}
</article>

4. locales/uk.json і locales/en.json — лише свої слова; загальні (ui.sold_out, ui.choose_product) уже є в спільному словнику дев’ятьма мовами:

// locales/uk.json
{"sec": {"picks_title": "Свіжі квіти щодня"}}

// locales/en.json
{"sec": {"picks_title": "Fresh flowers every day"}}

5. assets/theme.css — лише змінні магазину, тож кольори, шрифти й заокруглення змінюються зі «Стилями магазину»:

.bloom-picks { max-width: var(--store-container); margin: 0 auto; padding: var(--store-space-12) var(--store-space-4); }
.bloom-picks__title { font-family: var(--store-font-display); font-size: var(--store-text-3xl); color: var(--store-ink); }
.bloom-picks__grid { display: grid; gap: var(--store-space-6); grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }
.bloom-card { display: grid; gap: var(--store-space-2); padding: var(--store-space-3); border-radius: var(--store-radius-lg); background: var(--store-surface); box-shadow: var(--store-shadow-card); }
.bloom-card__media { position: relative; display: block; aspect-ratio: 4 / 5; overflow: hidden; border-radius: var(--store-radius-md); }
.bloom-card__media img { width: 100%; height: 100%; object-fit: cover; }
.bloom-card__sale { position: absolute; top: var(--store-space-2); left: var(--store-space-2); padding: 0 var(--store-space-2); border-radius: var(--store-radius-full); background: var(--store-accent); color: var(--store-on-accent); font-size: var(--store-text-xs); }
.bloom-card__title { color: var(--store-ink); font-weight: 600; text-decoration: none; }
.bloom-card__price { margin: 0; color: var(--store-primary-strong); font-weight: 700; }
.bloom-card__price s, .bloom-card__muted { color: var(--store-muted); font-weight: 400; }

6. Запакуйте й імпортуйте:

cd bloom && zip -r ../bloom.zip . && cd ..
# Дизайн → Теми → «Імпорт теми з файлу» → bloom.zip
# або: node storeforma-agent.mjs theme push ./bloom

7. Відкрийте редактор шаблонів, додайте на головну секцію «Bloom: добірка», виберіть товари в блоках і опублікуйте. Картки каталогу вже малюються вашим сніпетом; кошик, оформлення й кабінет — сторінками набору в стилі kit.css.

Далі: власна сторінка товару й каталогу — Сторінки теми; меню, вкладки й шухляди без JavaScript — Поведінки й стилі; шапка й підвал — секції з і компоненти з Компонентів ядра.