Структура проекта FDA
Проект на FDA можно узнать по дереву каталогов ещё до чтения кода: бизнес-логика живёт в src/routes/, инфраструктура — в src/lib/, и внутри доменов одинаковый набор файлов. Этот раздел — карта территории: что лежит в каждой папке и по каким правилам туда попадает.

🗺️ Полное дерево
Заголовок раздела «🗺️ Полное дерево»src/├── routes/ # Бизнес-логика: домены│ ├── +layout.svelte # корневой layout приложения│ ├── +page.svelte # главная страница│ ├── cart/ # домен «корзина»│ │ ├── +page.svelte # страница: разметка│ │ ├── +page.server.ts # server load│ │ ├── +server.ts # HTTP-роут: действия корзины│ │ ├── rpc.ts # публичное API для других доменов│ │ ├── client.ts # браузерные вызовы API модуля│ │ ├── model.server.ts # операции с данными│ │ ├── controller.svelte.ts # реактивное состояние│ │ ├── types.ts # типы домена│ │ ├── constants.ts # константы, enum│ │ ├── index.ts # публичные экспорты модуля│ │ └── ui/ # внутренние компоненты домена│ ├── auth/ # домен «авторизация»│ └── dashboard/ # домен «панель»│├── lib/ # Инфраструктура: без бизнес-логики│ ├── ui/ # переиспользуемые компоненты│ │ ├── Button.svelte # примитивы без привязки к доменам│ │ └── Input.svelte│ ├── universal/ # клиентский код вне доменов│ │ └── stores/ # глобальное состояние (тема, локаль)│ └── server/ # серверные утилиты│ └── repo/ # внешние источники данных│ ├── db/ # база данных (Drizzle ORM)│ ├── redis/ # кэш и сессии│ ├── vault/ # секреты и credentials│ └── keto/ # авторизация (OpenFGA)│├── scripts/ # скрипты: миграции, сиды, утилиты└── setup/ # сценарии запуска проекта🚪 src/routes/ — бизнес-логика
Заголовок раздела «🚪 src/routes/ — бизнес-логика»Здесь живут домены — верхний уровень фрактальной структуры. Каждый домен соответствует странице или разделу приложения: cart, auth, dashboard. Структура внутри домена одинаковая и описана в разделе 04 (уровни вложенности) и разделе 05 (контракты файлов).
Папки доменов меняются вместе с бизнесом: добавляется раздел «заказы» — появляется routes/orders/, переделывается корзина — изменения не выходят за пределы routes/cart/.
🔧 src/lib/ — инфраструктура
Заголовок раздела «🔧 src/lib/ — инфраструктура»Код, который не отвечает на вопросы бизнеса. Он меняется редко и живёт отдельно от доменов, чтобы не перемешиваться с часто меняющейся бизнес-логикой:
lib/ui/— переиспользуемые компоненты:Button,Input,Modal. Тест на попадание: компонент можно скопировать в другой проект, и он продолжит работать. Привязан к домену — значит, этоui/внутри домена, а не здесь.lib/server/repo/— клиенты внешних источников. Каждая папка названа по источнику, а не по домену:db/не знает, что его данные уйдут в корзину, — он просто умеет ходить в базу.lib/universal/— клиентский код вне доменов: глобальные сторы темы оформления, локали, сессии.
🍕 scripts/ и setup/
Заголовок раздела «🍕 scripts/ и setup/»scripts/— утилиты для разработки: миграции базы, генерация сидов, вспомогательные скрипты.setup/— сценарии, которые прогоняются при запуске проекта: инициализация окружения, проверка доступности внешних сервисов.
🧭 Куда положить новый код
Заголовок раздела «🧭 Куда положить новый код»Самый частый вопрос при работе с любой архитектурой. У FDA ответ складывается из одного вопроса и таблицы:
«Отвечает ли код на вопрос бизнеса?» Да — домен. Нет — инфраструктура. Дальше уточняем по типу:
| Что добавляете | Куда | Пример |
|---|---|---|
| Новая фича или страница | routes/<домен>/ | корзина, страница оплаты |
| Логика существующей фичи | файл в том домене, к которому относится | подсчёт суммы — cart/model.server.ts |
| Компонент для одного домена | routes/<домен>/ui/ | cart/ui/CartItemCard.svelte |
| Компонент для многих доменов | lib/ui/ | Button, Input |
| Работа с внешним источником | lib/server/repo/<источник>/ | клиент ClickHouse |
| Глобальное состояние | lib/universal/stores/ | тема, локаль |
| Утилита только для модуля | routes/<домен>/utils.ts | формат цены корзины |
| Утилита для всего проекта | lib/ | формат даты |
| Миграция, сиды | scripts/ | накат схемы базы |
🧪 Живой пример
Заголовок раздела «🧪 Живой пример»Дерево из репозитория example-sveltekit — минимальный домен cart в FDA-проекте:
src/├── lib/│ └── server/│ └── repo/│ ├── db.ts # коннектор базы (переэкспорт)│ └── db.mock.ts # мок для разработки└── routes/ ├── +layout.svelte ├── +page.svelte # главная страница └── cart/ # домен «корзина» ├── +page.server.ts # load: отдаёт корзину ├── +page.svelte # разметка страницы ├── +server.ts # POST: действия с корзиной ├── client.ts # fetch-обёртки для браузера ├── model.server.ts # операции с данными ├── model.fixtures.ts # фикстуры для примеров ├── stores.ts # реактивное состояние ├── types.ts # CartItem, Cart ├── constants.ts # лимиты корзины └── ui/ └── CartItemCard.svelte # карточка товараОбратите внимание: model.fixtures.ts и ui/CartItemCard.svelte не входят в обязательный набор — они появились, потому что задаче это понадобилось. FDA задаёт скелет, а необязательные файлы добавляются по необходимости.
🔗 Следующие шаги
Заголовок раздела «🔗 Следующие шаги»→ Домены и субдомены — как выделять домены и вкладывать субдомены
→ Контракты файлов — роль и экспорты каждого файла