Модуль и раздел

Сайт собирается из блоков: «первый экран», «карточки товаров», «форма обратной связи», «текст с картинкой».

Модуль — это тип такого блока, его чертёж: какие у блока настройки, как он выглядит и откуда берёт данные. Раздел — это модуль, поставленный на конкретную страницу и заполненный. Один модуль — сколько угодно разделов на разных страницах, у каждого свои настройки.

Если вы пишете на Vue или React, аналогия прямая: модуль — компонент, раздел — его экземпляр в шаблоне, поля раздела — пропсы, а contract.json — описание пропсов.

Главный принцип: страницу собирает сервер

Ядро на Go берёт описание страницы, находит нужные модули, подставляет данные в их шаблоны и отдаёт браузеру готовый HTML — не пустой <div id="app">, который потом оживает. Страница видна сразу, её понимают поисковики и она не разваливается, если скрипт не загрузился.

Для большинства блоков код писать не нужно: модуль описывается JSON-файлами и шаблонами, а движок разбирается сам. JavaScript подключается только там, где нужна интерактивность: слайдер, вкладки, аккордеон.

Файлы модуля

Модуль — это папка в modules/. Имя папки и есть тип модуля — то слово, по которому его позовут со страницы. Пишется латиницей через подчёркивание.

hello_block/
  manifest.json                       паспорт модуля
  module.compose.json                 сборка: где шаблон и ассеты
  contract.json                       поля раздела и записей
  style.scss                          стили модуля
  templates/
    hello_block_template.tpl.html     вёрстка блока
    _components/hello_block/card.tpl.html   повторяющаяся часть

manifest.json — паспорт

Единственный файл, без которого папку вообще не сочтут модулем: имя, подпись для редактора на двух языках, описание и версия.

contract.json — какие у блока поля

Контракт описывает два уровня:

  • поля раздела — заголовок, подзаголовок, текст, картинка, режим контейнера;
  • поля записей — если внутри блока список карточек: заголовок карточки, текст, иконка, ссылка.

У каждого поля есть тип (text, textarea, html, enum, bool, image), подпись для редактора, значение по умолчанию и ограничения. Движок не примет полей, которых нет в контракте — это и держит редактор и рендер согласованными.

Шаблон — вёрстка блока

{{ raw:module_css }}
<section class="hello section" data-section-id="{{ section_id }}">
  <div class="container">
    <h2 v-if="title">{{ title }}</h2>
    <hello_block:Card v-for="rec in records" :heading="rec.heading" />
  </div>
</section>

Синтаксис нарочно похож на Vue, но выполняется на сервере — подробнее в разделе Шаблоны и Vue.

Свой модуль и логика на JavaScript

Проще всего начать с копии близкого по смыслу модуля: скопируйте папку, переименуйте её, поправьте контракт, шаблон и стили. После правок фронтенда модуль пересобирается; правки серверных шаблонов подхватываются без сборки.

Когда блоку нужна собственная логика — расчёты, свой источник данных, обработка формы — её можно описать на JavaScript прямо в модуле: код выполняется серверным ядром на Go, пересобирать ядро для этого не нужно.