Стартер мой, поэтому текст ниже устроен так: сначала что в нем правда хорошо, потом чего в нем нет вовсе, и в конце то, на чем я споткнулся сам, собирая на нем этот блог. Хвалить свое легко, поэтому вторая и третья части длиннее первой.
Что это по цифрам
1683 строки в src, 8 Astro-компонентов, 3 страницы, 6 интеграций, 13
зависимостей и 5 дев-зависимостей. Репозиторий создан в апреле 2026, последняя
правка в августе, три звезды, один автор. Это не фреймворк и не тема, а
заготовка на пару вечеров работы, которую не хочется писать заново каждый раз.
Стек без сюрпризов: Astro 7 в статике, Tailwind v4 через @tailwindcss/vite,
TypeScript в строгом режиме, Biome вместо ESLint и Prettier, Bun как пакетный
менеджер.
Идея: один файл под правку
Главное решение стартера - весь проект настраивается из main.config.ts, и это
98 строк. Там URL, название, локали, Open Graph, цвета темы, подтверждения
владения доменом, аналитика и флаги фич.
Звучит как обычный config.js, но разница в том, что рядом лежат две вещи:
контракт в src/config/types.ts и проверки в src/config/validate.ts, которые
падают на старте dev и build.
export type AnalyticsProvider<TId> =
| { readonly enabled: false }
| { readonly enabled: true; readonly id: TId };Это дискриминированный union, и он делает невозможной целую категорию ошибок: включить аналитику без идентификатора нельзя, потому что не скомпилируется. То же самое с IndexNow, который без ключа существовать не может.
Прием не новый, но в стартерах он встречается редко: обычно конфиг это объект с десятком необязательных полей и абзац в README о том, какие из них обязательны, когда включена такая-то фича. Здесь эту роль выполняет компилятор.
Проверка сборки, а не намерений
Второе, что стартер делает всерьез, - bun run verify. Это линт, типы, сборка и
177 строк валидатора, который открывает каждую страницу в dist и проверяет:
- есть ли
<title>и мета-описание, - есть ли canonical,
- на месте ли набор Open Graph,
- парсится ли JSON-LD как JSON,
- проставлен ли
<html lang>, - сколько на странице
h1, - стоит ли
noindexна 404, - существуют ли в
distвсе локальные ссылки на ассеты.
Разница между «я добавил мета-теги» и «в собранном HTML они есть» - это ровно та разница, из-за которой SEO-правки обычно уезжают незамеченными. Валидатор проверяет второе.
Фичи выключаются честно: enabled: false не оставляет ни файла в dist, ни
тега в HTML, ни строки в robots.txt. Я проверял это на своей правке -
добавлял комментарии и прогонял сборку в обоих состояниях флага. Ноль следов.
Агентский слой
В репозитории лежат AGENTS.md и девять скиллов в .agents/skills/:
архитектура, стиль кода, зависимости, разработка фич, i18n, SEO, Tailwind,
TypeScript, валидация. Симлинки в .claude/skills/ дают тот же набор Claude
Code и Codex.
Это не украшение. Скилл starter-tailwind прямо запрещает хардкодить цвета
мимо токенов, starter-dependencies перечисляет удаленные пакеты и причины,
чтобы их не вернули обратно, starter-validation описывает, что считать
выполненной задачей. Агент, который читает эти файлы, ведет себя в проекте
предсказуемее, чем без них.
Чего в нем нет
Дальше честная часть.
Лицензии нет. У репозитория не проставлена лицензия вообще. Формально это значит, что права не переданы никому: клонировать «стартер» и строить на нем коммерческий проект юридически нельзя. Для заготовки, которую создают ровно затем, чтобы ее клонировали, это самая крупная недоделка.
CI нет. Папки .github в репозитории нет. bun run verify существует, но
ничто не мешает запушить сломанную сборку - проверка держится на дисциплине.
Тестов нет. Ни одного файла с тестами. Для 1683 строк, где половина - генерация артефактов и валидация конфига, это заметно: и валидатор конфигурации, и SEO-чекер - это ровно тот код, который тестируется легко и окупается быстро.
Репозиторий не помечен как template. «Use this template» на GitHub не работает, остается клонировать и отвязывать историю руками. При этом история - один коммит, то есть посмотреть, что менялось между версиями, нельзя.
Контента нет вообще. Ни content collections, ни примера блога, ни mdx
файла - при том, что @astrojs/mdx в зависимостях есть. Три страницы: главная,
ее английская версия и 404.
Темной темы нет. В токенах одна палитра.
Несколько зависимостей стоят «на вырост». @iconify-json/mdi не
используется ни разу, astro-icon подключен с пустым include: {},
@tailwindcss/typography загружен через @plugin, но класс prose в стартере
не встречается. На вес готового сайта это не влияет - Tailwind v4 генерирует
классы по факту использования, а Astro не бандлит неиспользуемое, - но в
установке и в списке зависимостей они есть.
На чем я споткнулся
Этот блог собран на стартере, и три вещи всплыли только в реальной работе.
Сборка на Cloudflare Pages падает из коробки
Самое серьезное. @dualmark/astro@0.10.0 - последняя версия - объявляет peer
astro@^6.1.10, а в стартере стоит Astro 7. Bun такой конфликт пропускает
молча, поэтому локально все ставится и работает. Cloudflare Pages ставит
зависимости через npm install и падает:
npm error ERESOLVE unable to resolve dependency tree
npm error Found: astro@7.2.4
npm error Could not resolve dependency:
npm error peer astro@"^6.1.10" from @dualmark/astro@0.10.0Деплой не начинается вообще. Лечится файлом .npmrc с legacy-peer-deps=true
или переключением сборки на Bun в настройках хостинга, но узнать об этом можно
только на первом деплое. В стартере ни того, ни другого нет.
Блог придется писать целиком
Ожидаемо, но масштаб я недооценил. Чтобы получить обычный блог, поверх стартера
пришлось написать: описание коллекции, выборку постов, карточку, сетку,
компонент статьи, стили для всех тегов markdown, подмену тегов через components
у <Content />, компоненты иллюстрации и галереи, обертку таблицы с
прокруткой и блок кода с шапкой. Это десяток файлов и несколько часов.
Стартер про SEO-каркас, а не про контент, и в README это сказано. Но если вы идете за блогом - вы идете не за этим.
Сборка markdown-двойников требует ручной работы
llms.txt и markdown-версии страниц собираются из явно перечисленных
staticPages и sections в astro.config.mjs. Добавили страницу - идите
дописывать ее в два места, иначе она в двойники не попадет. README об этом
предупреждает честно, но это ровно тот вид ручной синхронизации, который
разъезжается первым.
Линт покрывает не все
biome.json исключает public/ и src/components/SEO/Analytics/**, и на это
есть причины: Biome переформатирует SVG в public/ и не парсит инлайновый
JavaScript внутри .astro - поддержка .astro у него экспериментальная. Причины
задокументированы в AGENTS.md, но факт остается: часть кода вне проверки.
Кому подходит
Подходит, если вы делаете статические сайты на Astro регулярно и одинаково: лендинги, корпоративные страницы, документацию. Тогда стартер экономит несколько вечеров на SEO-обвязке, которую иначе каждый раз пишешь заново и каждый раз забываешь половину.
Подходит, если вам близка идея, что конфигурация должна проверяться
компилятором, а результат - валидатором по dist, а не глазами.
Не подходит, если нужен готовый блог, набор UI-компонентов или тема. Здесь их нет и не планируется - это каркас, а не витрина.
Не подходит, если нужна юридическая чистота: без лицензии брать чужой код в коммерческий проект нельзя.
Что бы я исправил первым
По убыванию важности: лицензия, .npmrc или документированный способ собрать на
npm-хостинге, GitHub Actions с bun run verify, тесты на валидатор конфигурации
и SEO-чекер, отметка репозитория как template.
Первые два - это полчаса работы, и они превращают заготовку «для себя» в заготовку, которую можно давать другим.
