---
title: "Вертикальні пресети (SSOT)"
description: "Іменовані пресети обирають спільні або локальні каталоги клону; під час збірки платформа об’єднується з накладенням клону"
locale: "uk"
---
# Вертикальні пресети (SSOT)

White-label-клони Ring використовують **одну кодову базу платформи**: `ring-platform.org`. Вертикалі обираються **назвою пресету** в `ring-config.json`. Типізовані каталоги розташовані в `features/*/presets/.ts` (а головна сторінка — у `components/pages/home-presets/.tsx`).

## Два джерела модулів пресетів

|| Джерело | Що там розташовано | Коли має перевагу |
||--------|------------------|--------------|
|| **Платформа** (`ring-platform.org`) | Спільні ніші (`platform`, `agricultural`, …) | База кожної збірки |
|| **Директорія проєкту клону** (наприклад, `ring-greenfood-live`) | Брендинг, `ring-config.json`, **custom** `.ts` + накладення реєстру | **Перезаписує при конфлікті** після копіювання платформи |

### Об’єднання під час збірки (істина клону має перевагу)

Використовуйте **`ringdom-clone-build`** (ringdom-mcp):

1. Скопіюйте найновішу `ring-platform.org` → тимчасова директорія збірки (пропускаються `node_modules` / `.next` / `.git`)
2. Скопіюйте **всі** файли з директорії проєкту клону в цю тимчасову директорію — **конфлікти перезаписуються**
3. Виконайте збірку Docker / CI з тимчасової директорії

```text
ringdom-clone-build({ project_name: "ring-greenfood-live", dry_run?: true })
→ .ringdom-build//
```

Не очікуйте, що одного тонкого накладення достатньо для застосунку, який можна запустити — спочатку виконайте об’єднання.

## Два рівні вмісту

|| Рівень | Що | Де |
||------|------|--------|
|| **1 — дані** | Списки категорій, токени бейджів, мітки | Відображення `ring-config.json` + `locales/` |
|| **2 — типізована логіка** | Каталоги сутностей, zod/forms, UI полів ніші | `features/*/presets/.ts` (платформа та/або накладення клону) |

## Ключі конфігурації

```json
{
  "entities": { "preset": "platform" },
  "home": { "preset": "platform" },
  "productFields": { "preset": "platform" },
  "productBadges": { "preset": "platform" },
  "productFieldsPresets": {
    "platform": { "storeCategories": ["commerce", "education", "…"] },
    "agricultural": { "storeCategories": ["organic-produce", "honey-sweets", "…"] }
  },
  "productBadgesPresets": {
    "platform": { "productBadges": ["new", "featured", "popular"] },
    "agricultural": { "productBadges": ["organic", "local", "regenerative"] }
  }
}
```

GreenFood встановлює `entities` / `productFields` / `productBadges` у значення `"agricultural"`, а `home.preset` — у `"mvm-landing"`.

### Аксесори (SSOT іменованого пресету)

Усі використовують налаштований рядок `*.preset`. Якщо сингулярний ключ не встановлено, **entities** і **productBadges** повертаються до `productFields.preset`, а потім до `"platform"` — без жорстко заданої логіки `if/else` для ніші.

- `getEntitiesPreset()` → реєстр `features/entities/presets`
- `getHomePreset()` → реєстр `components/pages/home-presets`
- `getProductFieldsPreset()` / `getProductFieldsPresets()`
- `getProductBadgesPreset()` / `getProductBadgesPresets()`

## Реєстр сутностей

```
features/entities/presets/
  types.ts             # EntityTypeCatalog contract
  platform.ts          # export const entityTypes (26 industries)
  agricultural.ts      # healthy-living UI catalog (lightweight)
  agricultural-erp.ts  # heavy ERP field catalogs — async-only via loadErpEntityTypes()
  index.ts             # ENTITIES_PRESET_REGISTRY + getEntityTypes()
```

**Правило:** назви пресетів з’являються в ring-config і карті реєстру. Споживачі викликають `getEntityTypes()` / `getEntityTypeList()` — ніколи не імпортують `agricultural.ts` безпосередньо.

**Власна ніша в клоні:** додайте `features/entities/presets/.ts` у проєкт клону, накладіть `index.ts`, щоб зареєструвати її, встановіть `entities.preset` у цю назву, а потім виконайте `ringdom-clone-build`.

**Дисципліна бандла:** синхронні каталоги — це легкі списки UI. Важкі каталоги полів ERP розташовані в модулях `*-erp.ts`, які завантажуються лише асинхронно через `loadErpEntityTypes()`.

### Шари текстів / піктограм (без жорстко заданих рядків UI)

- **Каталог** (`presets/.ts`): id, emoji, англійські резервні назви/описи
- **Тексти**: `locales/*/modules/entities.json` → `types.` + `types.Desc`
- **Візуальна тема**: `components/entities/entity-type-icons.tsx` `TYPE_VISUALS` map
- **Рендеринг**: `useEntityTypeLabel()` / `useEntityTypeDescription()` — спочатку i18n, потім резервний текст каталогу

## Реєстр головних сторінок

```
components/pages/
  home.tsx                       # platform default landing
  home-presets/mvm-landing.tsx   # multi-vendor-marketplace e-commerce landing
  home-content-resolver.tsx      # HOME_PRESET_REGISTRY + getHomePreset()
```

### Додати спільну вертикаль (платформа)

1. Додайте `features/entities/presets/.ts` (+ необов’язковий `-erp.ts`)
2. Додайте один рядок у `ENTITIES_PRESET_REGISTRY` (+ `ERP_CATALOG_REGISTRY`, якщо потрібно)
3. Необов’язкова головна сторінка → `components/pages/home-presets/.tsx`
4. Необов’язкові карти рівня 1 у `productFieldsPresets` / `productBadgesPresets`
5. Ключі i18n у `locales/*/modules/entities.json`
6. Задокументуйте id пресету в `ring-config.template.json`

Цільовий список: `platform`, `agricultural`, потім `tourism`, `sport`, `business`, `pet`, `auto`, `connect`, `technopark`, `manufacturing`.

## Тонке виключення (поширення)

`.reggie-propagate-exclude.json` захищає шляхи **лише накладення** від перезапису Reggie:

- `ring-config.json`
- `public/logo*.svg`, `favicon.ico`, `public/branding/`
- `locales/{en,uk,ru}/config.json`, `vendor.json`
- Власні `features/*/presets/.ts` (+ накладення реєстру), якщо їх ще не передано в upstream
- **Роз’єм рівня 3:** лише `lib/overlay/registry.ts` (карти). Не виключайте `lib/overlay/types.ts` або `lib/overlay/runtime.ts` — це SSOT платформи.

### Роз’єм рівня 3 overlay (платформа) + plug (клон)

|| Шлях | Власник | Роль |
||------|------|------|
|| `lib/overlay/types.ts` | Платформа | Контракти |
|| `lib/overlay/runtime.ts` | Платформа | `loadOverlayMessages` / `resolveOverlayHomeRail` |
|| `lib/overlay/registry.ts` | Порожні карти платформи; **карти накладає клон** | Завантажувачі доменних функцій |

Споживачі імпортують із `@/lib/overlay/runtime`. Клони ніколи не дублюють завантажувачі в `registry.ts`.

Чекліст оператора (calculator / Order Lab): [Ringization playbook](/docs/customization/ringization-playbook.md).

Джерелом поширення залишається **`ring-platform.org`** → клони для спільного коду. Власні пресети клону залишаються в директорії клону й мають перевагу під час `ringdom-clone-build`.

## Перемикання GreenFood

```text
ensure ring-config: entities/productFields/productBadges = agricultural, home = mvm-landing
keep branding + locale deltas in ring-greenfood-live
ringdom-clone-build({ project_name: "ring-greenfood-live" })
build/deploy from .ringdom-build/ring-greenfood-live/
```

## Застаріле

- Жорстко заданий `if (productPreset === 'agricultural')` в аксесорах
- Окремі для кожного клону `custom-types.ts` / `overrides.ts` без модуля іменованого пресету
- `switch (vertical)` у коді функцій — використовуйте реєстр
- Збірка Docker-образів із тонкого накладення без об’єднання з платформою
