SSOT Template Markup Language — фреймворк-независимая декларация UI.
Фронтенд-код смешивает две вещи: ваши решения и обвязку фреймворка. Какой API вызвать, какие поля показать, в каком порядке, при каких условиях — эти решения тонут в React hooks или Vue composables. При смене фреймворка или рефакторинге решения переинтерпретируются или теряются.
STML разделяет их. Решения остаются в стандартном HTML с атрибутами data-*. Обвязка фреймворка генерируется или делегируется.
Структура
┌─────────────────────────────────┐
│ STML (specs/) │ Ваши решения. Независимы от фреймворка.
│ Что получать, показывать, │ Переживёт любую перезапись.
│ отправлять │
├─────────────────────────────────┤
│ Кодогенерация / LLM │ Генерирует обвязку фреймворка.
│ React, Vue, Svelte, любой │ Заменяемый.
├─────────────────────────────────┤
│ Рантайм (artifacts/) │ React TSX, Vue SFC и т.д.
│ Хуки, состояние, рендеринг │ Сгенерировано. Не редактировать.
└─────────────────────────────────┘
Что сохраняется
Всё в HTML STML — это решение пользователя:
- Какие API-эндпоинты вызывать (
data-fetch,data-action) - Какие поля отображать или собирать (
data-bind,data-field) - В каком порядке появляются элементы (DOM-структура)
- Как выглядит (классы Tailwind, HTML-теги)
- Какой текст видят пользователи (заголовки, плейсхолдеры, надписи кнопок)
- Какие условия управляют видимостью (
data-state) - Какие компоненты обрабатывают специальный UX (
data-component) - Поведение списков — пагинация, сортировка, фильтрация
Это не React. Это не Vue. Это что делает ваша страница, объявленное в стандартном HTML5.
Валидация
Встроенный валидатор проверяет STML против OpenAPI перед генерацией кода:
- Существует ли operationId? Корректен ли HTTP-метод?
- Совпадают ли поля запроса, ответа и параметры со схемой?
- Находятся ли колонки сортировки/фильтрации/включения в разрешённых списках?
- Существуют ли упомянутые компоненты?
Ловит несоответствия фронтенд-API на этапе CI, не в рантайме.
stml validate specs/my-project # 12 символьных проверок по OpenAPI
Атрибуты data-*
| Атрибут | Что объявляет |
|---|---|
data-fetch | Загрузка данных из GET-эндпоинта |
data-action | Отправка данных в POST/PUT/DELETE-эндпоинт |
data-field | Сбор поля тела запроса |
data-bind | Отображение поля ответа |
data-param-* | Операция требует параметр пути/запроса |
data-each | Итерация по полю-массиву |
data-state | Условное отображение |
data-component | Делегирование пользовательскому компоненту |
data-paginate | Список с пагинацией |
data-sort | Сортируемый список (колонка и направление по умолчанию) |
data-filter | Фильтруемый список (какие колонки) |
data-include | Включение связанных ресурсов |
Лицензия
MIT — GitHub