# 02. Спецификация bootstrap.json

## Назначение
Bootstrap JSON является главным конфигурационным документом витрины. Он определяет структуру страниц, секций, виджетов, тему и подключение источников данных.

## Поведение системы
- Frontend загружает bootstrap.json на старте runtime.
- Конфигурация валидируется по обязательным полям.
- После валидации строится UI без хардкода tenant-логики.

## Обязательные свойства
- schemaVersion: string
- tenant: object
- theme: object
- layout: object
- pages: array
- apiEndpoints: object

### Обязательные свойства tenant
- id: string
- slug: string
- host: string
- defaultLocale: string
- supportedLocales: string[]

### Обязательные свойства страницы
- id: string
- key: string
- route.path: string
- sections: array

### Обязательные свойства секции
- id: string
- type: string
- order: number
- widgets: array

### Обязательные свойства виджета
- id: string
- type: string
- version: string

### Поддерживаемые layout.type
- default
- sidebar-left
- carousel-home
- minimal

## Опциональные свойства
- featureFlags
- localization
- seo
- permissions
- branding
- navigation
- footer
- catalog
- productPage
- userExperience
- staticPages
- widgetRegistry
- visibility
- layout
- dataSource

## Строгие правила
- Поля обязательной схемы не могут быть null.
- route.path должен быть уникальным в рамках tenant.
- id страниц, секций и виджетов должен быть уникальным в своей области.
- В одной секции порядок order не может дублироваться.
- Виджеты не содержат backend URL в props; URL управляются только apiEndpoints.
- Для виджетов допустимы metadata поля: order, padding, visibility.desktop/tablet/mobile.
- Для footer links/legal/payout icons источник истины — bootstrap JSON.
- Для staticPages контент поддерживается в формате multilingual HTML и рендерится только через safe sanitizer.
- Для productPage допускаются только feature-конфиги (enabled/pageSize/tabs/showSummary), без доменных данных отзывов и вопросов.
- Для catalog допускаются только UI/feature-конфиги (layout/sorts/filters/visibility toggles), без товарных данных.

### Catalog Config (опционально)
- catalog.layout: grid | large-grid | compact-grid | list
- catalog.navigationMode: default | left-category-navigation | mega-category-layout | top-category-carousel
- catalog.defaultSort: relevance | latest | price_asc | price_desc | rating | popular | discount
- catalog.availableSorts: string[]
- catalog.enabledFilters: string[]
- catalog.showBreadcrumbs: boolean
- catalog.showCategoryBanner: boolean
- catalog.showSubcategoryChips: boolean
- catalog.showRatings: boolean
- catalog.showDiscounts: boolean
- catalog.showAvailability: boolean
- catalog.suggestionsEnabled: boolean
- catalog.searchHistoryEnabled: boolean

### Product Engagement Config (опционально)
- productPage.rating.enabled: boolean
- productPage.reviews.enabled: boolean
- productPage.reviews.pageSize: number
- productPage.reviews.showSummary: boolean
- productPage.questions.enabled: boolean
- productPage.questions.pageSize: number
- productPage.tabs.enabled: boolean
- productPage.tabs.items: array (description/specifications/reviews/questions/delivery/warranty)
- productPage.relatedProducts.enabled: boolean

### User Experience Config (опционально)
- userExperience.wishlist.enabled: boolean
- userExperience.wishlist.headerBadgeEnabled: boolean
- userExperience.compare.enabled: boolean
- userExperience.compare.maxItems: number
- userExperience.compare.hideIdenticalDefault: boolean
- userExperience.compare.highlightDifferencesDefault: boolean
- userExperience.recentlyViewed.enabled: boolean
- userExperience.recentlyViewed.maxItems: number
- userExperience.recentlyViewed.widgetEnabled: boolean
- userExperience.share.enabled: boolean
- userExperience.continueBrowsing.enabled: boolean
- userExperience.savedSearches.enabled: boolean
- userExperience.savedSearches.maxItems: number

Правило:
- Для userExperience допускаются только feature-конфиги (flags/limits/default behaviors), без пользовательских списков (wishlist/compare/recentlyViewed/saved searches) и без product payloads.

## Пример полного минимального bootstrap
```json
{
  "schemaVersion": "1.0.0",
  "tenant": {
    "id": "tenant-default",
    "slug": "default",
    "host": "default.marketplace.com",
    "defaultLocale": "ru",
    "supportedLocales": ["ru", "en"]
  },
  "theme": {
    "themeId": "default-light",
    "palette": {
      "primary": "#497671",
      "textPrimary": "#1e3c38",
      "backgroundPrimary": "#ffffff"
    }
  },
  "apiEndpoints": {
    "catalog": { "baseUrl": "https://api.marketplace.com" },
    "bootstrap": { "path": "/bootstrap" }
  },
  "pages": [
    {
      "id": "page-home",
      "key": "home",
      "route": { "path": "/", "exact": true },
      "sections": [
        {
          "id": "section-hero",
          "type": "hero",
          "order": 1,
          "widgets": [
            { "id": "widget-hero", "type": "hero", "version": "1.0.0" }
          ]
        }
      ]
    }
  ]
}
```

## Ответственность Frontend
- Валидировать обязательные поля до рендера.
- Применять значения опциональных полей только при наличии.
- Прекращать инициализацию при критической невалидности схемы.

## Ответственность Backend
- Отдавать tenant-specific bootstrap.json.
- Поддерживать schemaVersion и changelog контракта.
- Не включать frontend-специфические runtime-хуки в JSON.
