Когда фронтенд собирается статически, а бэкенд ещё не готов, встаёт классический вопрос: что считать источником правды во время разработки?
Мы решили эту задачу один раз — на уровне загрузчика коллекций, а не разбрасывая проверки if (isDev) по компонентам.
Зачем нужен единый свап-поинт#
Идея простая: у каждой коллекции есть ровно одна функция-источник. Сегодня она читает JSON-фикстуру, завтра — дергает Content API Laravel. Компоненты об этом не знают.
export function contentSource(entity: ContentEntity): Loader {
if (USE_FIXTURES) {
return file(`src/content/fixtures/${entity}.json`);
}
return contentApiLoader(entity);
}Почему не просто fetch() в компоненте
Loader выполняется один раз на сборку и результат кешируется Content Layer — на 40 страницах не будет 40 одинаковых запросов.
Что даёт схема Zod#
- Ошибка формата ловится в момент
astro build, а не после деплоя. - IDE знает точные поля коллекции — автодополнение работает как для обычного TypeScript.
- Опциональные поля явно помечены — не нужно гадать, может ли значение быть
null.
| Источник | Когда используется | Задержка сборки |
|---|---|---|
| Фикстуры (JSON) | Локальная разработка, CI без бэкенда | ~0 мс |
| Content API | Продакшн-сборка, preview-окружения | зависит от сети |

Лучший рефакторинг — тот, который не потребовался, потому что архитектура заранее оставила для него один шов.
— из внутренней переписки команды
Что дальше#
В следующих раундах мы просто меняем USE_FIXTURES на false и реализуем contentApiLoader() — ни одна страница блога, услуг или проектов не потребует правок.
Ключевые выводы
- Content Layer в Astro 5+ — универсальный интерфейс загрузчика, а не просто обёртка над файловой системой.
- Один «свап-поинт» между фикстурами и реальным API избавляет страницы от условной логики.
- Схема Zod ловит несовпадения формата данных на этапе сборки, а не в рантайме у пользователя.
- Собственный Loader пишется один раз и переиспользуется для всех коллекций проекта.
Частые вопросы
Чем Content Layer отличается от старых Content Collections?
Старые Content Collections были жёстко привязаны к файлам в src/content. Content Layer вводит интерфейс Loader — источником данных может быть файл, API или база, а схема остаётся общей.
Нужно ли переписывать компоненты при смене источника данных?
Нет — если контракт (форма данных, описанная схемой) не меняется, компоненты продолжают работать без правок.
Нужен похожий контур для вашего проекта?
Спроектируем фронтенд так, чтобы бэкенд можно было подключить в любой момент без переписывания страниц.
Обсудить проект


