Files
marketplaces/docs/platform/00-bootstrap-example.md

747 lines
24 KiB
Markdown
Raw Normal View History

2026-07-05 04:23:47 +04:00
# 1. SYSTEM OVERVIEW
Платформа является полностью configuration-driven SaaS-решением для запуска и масштабирования multi-tenant маркетплейсов.
Ключевые принципы:
- Поведение витрины определяется конфигурацией, а не кастомным кодом под каждого клиента.
- Каждый домен однозначно резолвится в конкретный tenant.
- UI формируется только на основе bootstrap JSON.
- Во frontend отсутствуют hardcoded правила по layout, страницам и tenant-ветвлению.
Это позволяет запускать новые магазины без форка frontend-приложения: меняется конфигурация и данные, а не архитектура продукта.
# 2. BOOTSTRAP FLOW
Стандартный поток инициализации:
1. Пользователь открывает домен магазина.
2. Backend определяет tenant по домену.
3. Backend возвращает tenant-specific bootstrap JSON.
4. Frontend валидирует конфигурацию.
5. Frontend динамически строит:
- тему,
- навигацию,
- страницы,
- секции,
- виджеты,
- статические страницы.
6. Данные каталога и товаров подгружаются через API-контракты, указанные в bootstrap.
Итог: один frontend runtime обслуживает множество магазинов, различающихся конфигурацией.
# 3. FULL BOOTSTRAP JSON EXAMPLE
Ниже приведен полный production-grade пример bootstrap JSON с явно именованными сущностями.
```json
{
"schemaVersion": "1.0.0",
"generatedAt": "2026-07-05T10:00:00Z",
"tenant": {
"id": "tenant-dexar-ru",
"name": "Dexar Market RU",
"domain": "dexarmarket.ru",
"slug": "dexar-ru",
"defaultLocale": "ru",
"supportedLocales": ["ru", "en", "hy"],
"defaultCurrency": "RUB",
"supportedCurrencies": ["RUB", "USD", "EUR", "AMD"],
"timezone": "Europe/Moscow"
},
"api": {
"baseUrl": "https://api.dexarmarket.ru",
"endpoints": {
"bootstrap": "/bootstrap",
"categories": "/categories",
"products": "/products",
"productDetails": "/products/{id}",
"search": "/search",
"cart": "/cart"
},
"timeouts": {
"defaultMs": 10000,
"catalogMs": 12000,
"productMs": 12000
}
},
"theme": {
"themeId": "dexar-light",
"colors": {
"primary": "#2F6E5D",
"secondary": "#8FA9A2",
"accent": "#CBE4DA",
"textPrimary": "#1F322D",
"textSecondary": "#5F6E6A",
"backgroundPrimary": "#FFFFFF",
"backgroundSecondary": "#F6F8F7",
"border": "#D5DDDB",
"success": "#1FA97A",
"warning": "#D9941A",
"danger": "#D64545"
},
"typography": {
"fontFamily": "DM Sans, sans-serif",
"headingFontFamily": "DM Sans, sans-serif",
"baseFontSize": 16,
"scale": {
"h1": 40,
"h2": 32,
"h3": 24,
"body": 16,
"caption": 14
}
},
"radius": {
"sm": "8px",
"md": "12px",
"lg": "16px"
},
"shadows": {
"sm": "0 2px 8px rgba(0,0,0,0.08)",
"md": "0 6px 18px rgba(0,0,0,0.12)",
"lg": "0 14px 36px rgba(0,0,0,0.16)"
}
},
"layoutProfile": "default",
"layoutProfiles": {
"default": {
"description": "Стандартный storefront layout с верхней навигацией",
"pageContainer": {
"maxWidth": 1280,
"paddingX": 16,
"paddingY": 24
},
"sectionSpacing": 24,
"grid": {
"gap": 16,
"columnsDesktop": 4,
"columnsTablet": 2,
"columnsMobile": 1
},
"regions": ["header", "content", "footer"]
},
"side-menu-layout": {
"description": "Layout с левой боковой навигацией",
"pageContainer": {
"maxWidth": 1360,
"paddingX": 16,
"paddingY": 24
},
"sectionSpacing": 24,
"grid": {
"gap": 16,
"columnsDesktop": 3,
"columnsTablet": 2,
"columnsMobile": 1
},
"regions": ["header", "side", "content", "footer"]
},
"grid-layout": {
"description": "Плиточная витрина с усиленным grid-представлением",
"pageContainer": {
"maxWidth": 1440,
"paddingX": 20,
"paddingY": 24
},
"sectionSpacing": 20,
"grid": {
"gap": 20,
"columnsDesktop": 5,
"columnsTablet": 3,
"columnsMobile": 2
},
"regions": ["header", "content", "footer"]
},
"landing-page-layout": {
"description": "Промо-лендинг с акцентом на hero и banner секции",
"pageContainer": {
"maxWidth": 1200,
"paddingX": 16,
"paddingY": 32
},
"sectionSpacing": 32,
"grid": {
"gap": 24,
"columnsDesktop": 2,
"columnsTablet": 1,
"columnsMobile": 1
},
"regions": ["header", "content", "footer"]
}
},
"navigation": {
"header": [
{
"id": "nav-logo",
"type": "logo",
"label": "Dexar",
"route": "/",
"order": 1,
"visible": true
},
{
"id": "nav-side-menu",
"type": "side-menu",
"label": "Меню",
"route": "/catalog",
"order": 2,
"visible": true
},
{
"id": "nav-category-menu",
"type": "category-menu",
"label": "Категории",
"route": "/catalog",
"order": 3,
"visible": true
},
{
"id": "nav-search",
"type": "search",
"label": "Поиск",
"route": "/search",
"order": 4,
"visible": true
},
{
"id": "nav-language",
"type": "language-switcher",
"label": "Язык",
"order": 5,
"visible": true
},
{
"id": "nav-currency",
"type": "currency-switcher",
"label": "Валюта",
"order": 6,
"visible": true
},
{
"id": "nav-cart",
"type": "cart",
"label": "Корзина",
"route": "/cart",
"order": 7,
"visible": true
}
],
"footer": [
{
"id": "footer-about",
"type": "footer-links",
"label": "О компании",
"route": "/about",
"order": 1,
"visible": true
},
{
"id": "footer-terms",
"type": "footer-links",
"label": "Условия",
"route": "/terms",
"order": 2,
"visible": true
},
{
"id": "footer-privacy",
"type": "footer-links",
"label": "Конфиденциальность",
"route": "/privacy",
"order": 3,
"visible": true
}
]
},
"widgetManifest": [
{
"type": "hero-widget",
"version": "1.0.0",
"component": "HeroWidgetComponent",
"dataSource": "static",
"enabled": true
},
{
"type": "category-widget",
"version": "1.0.0",
"component": "CategoryWidgetComponent",
"dataSource": "categories",
"enabled": true
},
{
"type": "product-grid-widget",
"version": "1.0.0",
"component": "ProductGridWidgetComponent",
"dataSource": "products",
"enabled": true
},
{
"type": "product-carousel-widget",
"version": "1.0.0",
"component": "ProductCarouselWidgetComponent",
"dataSource": "products",
"enabled": true
},
{
"type": "cart-widget",
"version": "1.0.0",
"component": "CartWidgetComponent",
"dataSource": "cart",
"enabled": true
},
{
"type": "side-menu-widget",
"version": "1.0.0",
"component": "SideMenuWidgetComponent",
"dataSource": "navigation",
"enabled": true
}
],
"catalog": {
"layout": "grid",
"navigationMode": "default",
"defaultSort": "relevance",
"availableSorts": ["relevance", "latest", "price_asc", "price_desc", "rating", "popular", "discount"],
"enabledFilters": ["price", "availability", "rating", "brand", "category", "subcategory", "discount", "new", "color", "size", "attributes"],
"showBreadcrumbs": true,
"showCategoryBanner": true,
"showSubcategoryChips": true,
"showRatings": true,
"showDiscounts": true,
"showAvailability": true,
"suggestionsEnabled": true,
"searchHistoryEnabled": true
},
"productPage": {
"rating": { "enabled": true },
"reviews": {
"enabled": true,
"pageSize": 5,
"showSummary": true
},
"questions": {
"enabled": true,
"pageSize": 5
},
"tabs": {
"enabled": true,
"items": ["description", "specifications", "reviews", "questions", "delivery", "warranty"]
},
"relatedProducts": { "enabled": true }
},
2026-07-05 04:23:47 +04:00
"pages": [
{
"id": "page-home",
"key": "home",
"title": "Главная",
"route": { "path": "/", "exact": true },
"layoutProfile": "default",
"sections": [
{
"id": "home-hero",
"type": "hero",
"order": 1,
"widgets": [
{
"id": "widget-home-hero",
"type": "hero-widget",
"version": "1.0.0",
"props": {
"title": "Маркетплейс нового поколения",
"subtitle": "Запущен на configuration-driven SaaS платформе",
"ctaText": "Перейти в каталог"
}
}
]
},
{
"id": "home-categories",
"type": "categories",
"order": 2,
"widgets": [
{
"id": "widget-home-categories",
"type": "category-widget",
"version": "1.0.0",
"dataSource": {
"name": "categories",
"params": { "rootOnly": true, "limit": 12 }
}
}
]
},
{
"id": "home-featured",
"type": "featured-products",
"order": 3,
"widgets": [
{
"id": "widget-home-featured-carousel",
"type": "product-carousel-widget",
"version": "1.0.0",
"dataSource": {
"name": "products",
"params": { "preset": "featured", "limit": 10 }
}
}
]
},
{
"id": "home-banner",
"type": "banner",
"order": 4,
"widgets": [
{
"id": "widget-home-banner",
"type": "hero-widget",
"version": "1.0.0",
"props": {
"title": "Летняя распродажа",
"subtitle": "Скидки до 30%",
"ctaText": "Смотреть предложения"
}
}
]
},
{
"id": "home-footer-links",
"type": "footer-links",
"order": 5,
"widgets": [
{
"id": "widget-home-footer-links",
"type": "side-menu-widget",
"version": "1.0.0",
"dataSource": { "name": "navigation", "params": { "zone": "footer" } }
}
]
}
]
},
{
"id": "page-catalog",
"key": "catalog",
"title": "Каталог",
"route": { "path": "/catalog", "exact": true },
"layoutProfile": "side-menu-layout",
"sections": [
{
"id": "catalog-sidebar",
"type": "sidebar-categories",
"order": 1,
"widgets": [
{
"id": "widget-catalog-side-menu",
"type": "side-menu-widget",
"version": "1.0.0",
"dataSource": { "name": "categories", "params": { "tree": true } }
}
]
},
{
"id": "catalog-grid",
"type": "product-grid",
"order": 2,
"widgets": [
{
"id": "widget-catalog-product-grid",
"type": "product-grid-widget",
"version": "1.0.0",
"dataSource": {
"name": "products",
"params": { "sort": "priority_desc", "pageSize": 20 }
}
}
]
}
]
},
{
"id": "page-product",
"key": "product",
"title": "Карточка товара",
"route": { "path": "/product/:id", "exact": true },
"layoutProfile": "default",
"sections": [
{
"id": "product-main-grid",
"type": "product-grid",
"order": 1,
"widgets": [
{
"id": "widget-product-main",
"type": "product-grid-widget",
"version": "1.0.0",
"dataSource": {
"name": "productDetails",
"params": { "fromRoute": "id" }
}
}
]
},
{
"id": "product-recommendations",
"type": "product-carousel",
"order": 2,
"widgets": [
{
"id": "widget-product-recommendations",
"type": "product-carousel-widget",
"version": "1.0.0",
"dataSource": {
"name": "products",
"params": { "preset": "related", "limit": 12 }
}
}
]
},
{
"id": "product-cart",
"type": "featured-products",
"order": 3,
"widgets": [
{
"id": "widget-product-cart",
"type": "cart-widget",
"version": "1.0.0",
"dataSource": { "name": "cart", "params": {} }
}
]
}
]
}
],
"staticPages": [
{
"id": "static-about",
"key": "about",
"title": "О компании",
"route": { "path": "/about", "exact": true },
"content": {
"source": "cms",
"contentType": "html",
"value": "<h1>О компании</h1><p>Dexar Market - платформа маркетплейса для B2B/B2C продаж.</p>"
},
"visible": true
},
{
"id": "static-terms",
"key": "terms",
"title": "Условия использования",
"route": { "path": "/terms", "exact": true },
"content": {
"source": "cms",
"contentType": "html",
"value": "<h1>Условия использования</h1><p>Правила работы сервиса и обязательства сторон.</p>"
},
"visible": true
},
{
"id": "static-privacy",
"key": "privacy",
"title": "Политика конфиденциальности",
"route": { "path": "/privacy", "exact": true },
"content": {
"source": "cms",
"contentType": "html",
"value": "<h1>Политика конфиденциальности</h1><p>Порядок обработки персональных данных.</p>"
},
"visible": true
}
],
"features": {
"multiLanguage": true,
"multiCurrency": true,
"regionSelector": true,
"guestCheckout": true,
"searchEnabled": true,
"recommendationsEnabled": true
}
}
```
# 4. FEATURE REGISTRY TABLE
Ниже перечислены поддерживаемые возможности платформы в удобном формате: что это, где применяется и как выглядит в JSON.
## 4.1 Layout Features
- `default` (type: layout): базовый профиль витрины с верхней навигацией.
- `side-menu-layout` (type: layout): профиль с боковым меню категорий и контентной зоной.
- `grid-layout` (type: layout): плиточный профиль для плотного товарного листинга.
- `landing-page-layout` (type: layout): профиль лендинга с акцентом на hero/banner.
Пример использования layout:
```json
{
"layoutProfile": "side-menu-layout",
"layoutProfiles": {
"default": { "sectionSpacing": 24 },
"side-menu-layout": { "regions": ["header", "side", "content", "footer"] },
"grid-layout": { "grid": { "columnsDesktop": 5 } },
"landing-page-layout": { "sectionSpacing": 32 }
}
}
```
## 4.2 Navigation Features
- `logo` (type: navigation): блок логотипа в header.
- `side-menu` (type: navigation): триггер бокового меню.
- `category-menu` (type: navigation): навигация по категориям.
- `cart` (type: navigation): переход к корзине.
- `search` (type: navigation): точка входа в поиск.
- `language-switcher` (type: navigation): переключение языка.
- `currency-switcher` (type: navigation): переключение валюты.
Пример использования navigation:
```json
{
"navigation": {
"header": [
{ "type": "logo", "route": "/" },
{ "type": "side-menu", "route": "/catalog" },
{ "type": "category-menu", "route": "/catalog" },
{ "type": "search", "route": "/search" },
{ "type": "language-switcher" },
{ "type": "currency-switcher" },
{ "type": "cart", "route": "/cart" }
]
}
}
```
## 4.3 Section Features
- `hero` (type: section): главная промо-секция страницы.
- `categories` (type: section): блок категорий.
- `product-grid` (type: section): сетка товаров.
- `product-carousel` (type: section): карусель товаров.
- `sidebar-categories` (type: section): боковая колонка категорий.
- `featured-products` (type: section): выделенный блок рекомендованных товаров.
- `banner` (type: section): баннерная секция.
- `footer-links` (type: section): секция ссылок в футере.
Пример использования sections:
```json
{
"sections": [
{ "type": "hero", "order": 1 },
{ "type": "categories", "order": 2 },
{ "type": "featured-products", "order": 3 },
{ "type": "banner", "order": 4 },
{ "type": "footer-links", "order": 5 }
]
}
```
## 4.4 Widget Features
- `hero-widget` (type: widget): виджет hero-контента.
- `category-widget` (type: widget): виджет списка/сетки категорий.
- `product-grid-widget` (type: widget): виджет товарной сетки.
- `product-carousel-widget` (type: widget): виджет товарной карусели.
- `cart-widget` (type: widget): виджет корзины.
- `side-menu-widget` (type: widget): виджет бокового меню.
Пример использования widgets:
```json
{
"widgets": [
{ "type": "hero-widget", "version": "1.0.0" },
{ "type": "category-widget", "version": "1.0.0" },
{ "type": "product-grid-widget", "version": "1.0.0" },
{ "type": "product-carousel-widget", "version": "1.0.0" },
{ "type": "cart-widget", "version": "1.0.0" },
{ "type": "side-menu-widget", "version": "1.0.0" }
]
}
```
## 4.5 Feature Flags
- `multiLanguage` (type: feature): включает мультиязычность storefront.
- `multiCurrency` (type: feature): включает мультивалютный режим.
- `regionSelector` (type: feature): включает выбор региона.
- `guestCheckout` (type: feature): разрешает checkout без авторизации.
- `searchEnabled` (type: feature): включает поиск по каталогу.
- `recommendationsEnabled` (type: feature): включает рекомендательные блоки.
Пример использования feature flags:
```json
{
"features": {
"multiLanguage": true,
"multiCurrency": true,
"regionSelector": true,
"guestCheckout": true,
"searchEnabled": true,
"recommendationsEnabled": true
}
}
```
# 5. LAYOUT ENGINE EXPLANATION
Layout Engine применяет выбранный профиль layoutProfile для каждой страницы и определяет:
- контейнер страницы (ширина, внутренние отступы);
- интервалы между секциями;
- grid-параметры (колонки и gap);
- доступные regions (header/content/side/footer).
Как отличается side-menu-layout от default:
- default: акцент на центральный контент и верхнюю навигацию;
- side-menu-layout: добавляется регион side для боковой навигации и фильтров, контентный поток меняется на двухзонный.
Позиционирование виджетов:
- виджеты размещаются по секциям и регионам, заданным конфигурацией страницы;
- порядок и тип секций контролируются order и type;
- frontend не содержит hardcoded матриц layout.
Ключевой принцип: layout полностью декларативен, а не зашит в Angular-компоненты страниц.
# 6. STRICT RULES
## DO NOT
- Do NOT hardcode tenant logic in frontend.
- Do NOT define layout in Angular components.
- Do NOT call APIs inside widgets.
- Do NOT add project-specific conditions.
- Do NOT duplicate config logic across JSON files.
Дополнительные обязательные ограничения:
- Нельзя смешивать обязанности модулей конфигурации (theme, navigation, pages, features).
- Нельзя добавлять новые обязательные поля без повышения schemaVersion.
- Нельзя нарушать domain-to-tenant резолвинг альтернативными источниками истины.
# 7. EXTENSIBILITY MODEL
Платформа расширяется конфигурационно без изменений бизнес-логики frontend:
1. Новый виджет:
- Добавляется в widgetManifest.
- Привязывается к section через widgets[].type.
- Контент/данные подаются через props/dataSource.
2. Новый layout:
- Добавляется в layoutProfiles.
- Назначается страницам через pages[].layoutProfile.
3. Новая страница:
- Добавляется в pages с route, sections и widgets.
- Сразу участвует в runtime-рендеринге.
4. Контентные изменения:
- Меняются только JSON-конфигурации и backend-данные.
- Изменения контента не требуют модификации frontend-кода при сохранении контрактов.
Итоговая модель масштабирования:
- Tenant onboarding выполняется через домен, bootstrap и данные.
- Продукт расширяется через registry-подход.
- Архитектура остается стабильной при росте количества магазинов.