Skip to content

Spec-Driven Development (SDD) — Design Document

Problem

  • API-контракт между фронтом и бэком описан в разрозненных markdown-файлах
  • Zod-схемы на фронте живут отдельно от бэкенда — нет единого источника правды
  • Нет автоматической валидации соответствия кода спецификации
  • Документация (ADR, гайды, UI, help) разбросана по разным репозиториям

Solution

Единый documentation hub в отдельном репозитории partizap-docs/ с OpenAPI spec как источником правды для API и VitePress как платформой для всей документации.

Architecture

Repository

  • URL: https://gitlab.partizap.ru/root/partizap-docs
  • Локально: partizap/dev/partizap-docs/ (рядом с backend, frontend, nginx)

Structure

partizap-docs/
├── specs/
│   └── openapi.yaml                 # OpenAPI 3.1 — единый контракт API
├── docs/
│   ├── api/                         # API reference (рендерится из openapi.yaml)
│   ├── dev/                         # Внутренняя dev-документация
│   │   ├── adr/                     # Architecture Decision Records
│   │   ├── architecture.md
│   │   └── runbook.md
│   ├── guides/                      # Гайды для партнёров / интеграторов
│   ├── help/                        # Продуктовая документация (FAQ, инструкции)
│   └── ui/                          # UI-документация
│       ├── components/              # Описание компонентов (props, usage, примеры)
│       ├── design-tokens.md         # Цвета, типографика, spacing
│       ├── layouts.md               # Лейауты и паттерны
│       └── patterns.md              # UX-паттерны (формы, фильтры, модалки)
├── .vitepress/
│   └── config.ts                    # Навигация, sidebar, плагины
├── package.json
└── .gitlab-ci.yml

Tech Stack

ComponentToolReason
Doc siteVitePressVue-экосистема (как фронт), лёгкий, markdown
API docsvitepress-openapiРендерит OpenAPI прямо в VitePress
Spec linting@redocly/cliВалидация openapi.yaml в CI
DeployСтатика на nginxУже есть инфра, zero cost

SDD Workflow

Принцип

Спеку всегда предлагает бэкенд. Фронтенд — потребитель.

Если фронтендеру нужен новый эндпоинт — он создаёт задачу бэкендеру, а не правит спеку сам.

Scenario A: Backend — новый/изменённый API

Рабочие директории: partizap-backend/ + partizap-docs/

1. Описываешь фичу словами
2. Claude обновляет partizap-docs/specs/openapi.yaml
3. Ты ревьюишь diff в openapi.yaml
4. Claude реализует эндпоинт в partizap-backend/
   ├─ Action класс
   ├─ route в routes.php
   └─ тесты
5. Коммит в оба репозитория

Scenario B: Frontend — реализация по спеке

Рабочие директории: partizap-frontend/ + partizap-docs/

1. Фронтендер читает обновлённый openapi.yaml
2. Claude реализует клиентскую часть в partizap-frontend/
   ├─ Zod-схема (если новые типы)
   ├─ API-вызов в entity/feature
   └─ UI-компонент
3. При необходимости обновляет partizap-docs/docs/ui/

Scenario C: Frontend — чисто UI задача (без API)

Рабочие директории: partizap-frontend/ + partizap-docs/

1. Claude обновляет partizap-docs/docs/ui/ (описание компонента)
2. Claude реализует в partizap-frontend/

Summary Table

Тип измененияКто правит спекуРепозиторииSDD?
Новый эндпоинтБэкендерdocs + backendДа
Изменение ответа APIБэкендерdocs + backendДа
Новый UI-компонентdocs (ui/) + frontendНет
Смена дизайна/layoutdocs (ui/) + frontendНет
Новое поле в форме, уходящее в APIБэкендерdocs + backend → frontendДа
Рефакторинг фронт-кодаfrontend onlyНет
Продуктовый гайд / FAQdocs (help/) onlyНет

CLAUDE.md Integration

В CLAUDE.md бэкенда добавить:

markdown
## API Spec (SDD)
- Единый источник правды: ../partizap-docs/specs/openapi.yaml
- Перед созданием/изменением API — сначала обнови спеку в partizap-docs
- После изменения спеки — коммит в partizap-docs

В CLAUDE.md фронта добавить:

markdown
## API Spec (SDD)
- Единый источник правды: ../partizap-docs/specs/openapi.yaml
- Читай спеку перед реализацией API-вызовов
- Не правь openapi.yaml — это ответственность бэкенда
- При изменении UI-компонентов — обновляй ../partizap-docs/docs/ui/

Deploy

CI/CD (partizap-docs/.gitlab-ci.yml)

yaml
stages:
  - lint
  - build
  - deploy

lint:spec:
  stage: lint
  script:
    - npx @redocly/cli lint specs/openapi.yaml

build:docs:
  stage: build
  script:
    - npm ci && npm run build
  artifacts:
    paths: [.vitepress/dist]

deploy:docs:
  stage: deploy
  script:
    - scp -r .vitepress/dist/* server:/var/www/docs/
  only: [main]

Nginx

В https://gitlab.partizap.ru/d_vyaznikov/nginx добавить server block:

nginx
server {
    server_name docs.partizap.ru;
    root /var/www/docs;

    location / {
        # Пока за cookie-auth (как dev.partizap.ru)
        # Потом: /help/ и /api/ — публичные, /dev/ — за auth
        try_files $uri $uri/ /index.html;
    }
}

Access Control (future)

  • Сейчас: всё за nginx cookie-auth
  • Потом: публичные секции (/help/, /api/, /guides/) открыты, /dev/ за auth

Code Generation (hybrid approach)

WhatHowWhen
TypeScript typesopenapi-typescript (auto)CI или pre-commit hook
Zod schemasClaude вручную по спекеПри реализации фичи на фронте
API client callsClaude вручную по спекеПри реализации фичи на фронте
Backend Action codeClaude вручную по спекеПри реализации фичи на бэке

Автогенерация TypeScript типов гарантирует соответствие спеке. Zod-схемы и бизнес-логика — Claude, т.к. требуют контекст.

Migration Plan

  1. Создать репозиторий https://gitlab.partizap.ru/root/partizap-docs
  2. Инициализировать VitePress + vitepress-openapi
  3. Написать первичный openapi.yaml по существующим 99 эндпоинтам (можно итеративно)
  4. Перенести ADR из partizap-backend/approved/partizap_ADR/docs/dev/adr/
  5. Перенести RUNBOOK из dev/docs/RUNBOOK.mddocs/dev/runbook.md
  6. Настроить CI/CD + nginx server block
  7. Обновить CLAUDE.md в обоих репозиториях
  8. Начать работать по SDD-workflow