Files
marketplaces/docs/platform/00-bootstrap-example.md
sdarbinyan 1a8f916942
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
feat(catalog): implement sprint 10 advanced search experience
2026-07-09 00:55:50 +04:00

747 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 }
},
"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-подход.
- Архитектура остается стабильной при росте количества магазинов.