Скин: каркас, шапка и подвал

Скин — внешний вид сайта вокруг блоков: шапка, подвал, каркас страницы, меню и стили. Файлы вёрстки имеют расширение .sehtml — это обычный HTML с «дырками» вида {{ … }}, которые заполняет ядро.

www/templates/
  pages/base.sehtml       каркас: весь документ от <!doctype> до </html>
  pages/default.sehtml    страница по умолчанию: {{ extends:base }} и свои слоты
  partials/header.sehtml  шапка: логотип, меню, телефон
  partials/footer.sehtml  подвал
  menus/menu.tpl.html     вёрстка меню целиком

Три папки — три роли: pages/ — документ целиком (ядро берёт его по полю «Шаблон» страницы), partials/ — куски вёрстки, которые вы вставляете сами через {{ partial:header }}, menus/ — вёрстка меню, которую ядро подставляет на {{ menu:имя }}.

Стилям и скриптам в templates/ места нет — их дом frontend/styles и frontend/scripts. Собранный результат уезжает в public/skin — там лежат готовые файлы, а не исходники.

Ссылки на картинки и шрифты в SCSS можно писать как удобно — сборка сама переведёт их на итоговый путь с content-hash. Единственное исключение — одинаковые имена файлов в разных папках: такую ссылку сборка оставит как написана.

Vue-HTML на сервере и Vue 3 в браузере

В шаблонах модулей и меню работает Vue-HTML — язык, нарочно похожий на Vue, но выполняемый на сервере. Никакого Vue в браузере для этого не нужно.

  • {{ title }} — вставить значение;
  • {{ raw:text }} — вставить готовый HTML как есть;
  • v-if, v-else-if, v-else — условия;
  • v-for="rec in records" — повтор по списку;
  • :атрибут="выражение" — значение атрибута из выражения;
  • <ns:Name /> — подключить компонент из _components/ns/name.tpl.html.

В выражениях доступны сравнения, логические операторы, арифметика, склейка строк и тернарный оператор. А вот методов у значений, стрелочных функций, шаблонных строк и дат в языке нет: если нужного не хватает, значение готовится на стороне модуля и приходит в шаблон готовым.

Одна особенность, которая экономит время: ложны только null, false, 0 и пустая строка; строка "0", пустой список и пустой объект — истинны.

Где работает полный язык

Циклы и :bind-атрибуты имеют смысл в шаблонах модулей и меню. В каркасах страниц (.sehtml) работает подстановка токенов и ветвление v-if.

Vue 3 — остров поверх готового HTML

Там, где нужна настоящая интерактивность — корзина, фильтры каталога, вкладки с подгрузкой — подключается Vue 3. Исходники острова живут в папке frontend/ рядом с модулем (обычные .vue-компоненты), собираются vite и подключаются в module.compose.json.

Принцип один: сначала сервер отдаёт осмысленную разметку, а Vue гидрирует её поверх — страница целиком на Vue не строится. Без JavaScript блок остаётся читаемым. Стартовые данные и все видимые подписи приходят острову с сервера отдельным JSON, поэтому тексты не попадают в бандл и локализация остаётся на сервере.