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
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
2026-07-09 00:45:36 +04:00
|
|
|
|
"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-подход.
|
|
|
|
|
|
- Архитектура остается стабильной при росте количества магазинов.
|