🔹 Вариант 1. Два проекта внутри одного монорепо
- Создаёшь в корне что-то вроде:
/apps /site1 /site2 /packages /ui (общие компоненты)
- В
apps/site1
иapps/site2
будут своиastro.config.mjs
, страницы и сборка. - Общие компоненты подключаются через
packages/ui
. - Билд каждого проекта делается отдельно:
cd apps/site1 && npm run build cd apps/site2 && npm run build
- На деплое просто указываешь разные выходные папки (
dist
) на разные URL.
👉 Это самый гибкий и правильный способ, если проекты реально разные.
🔹 Вариант 2. Один проект, разные “режимы”
Если у тебя один astro
-проект, но нужны два билда:
- Можно завести несколько
astro.config.mjs
(напримерastro.config.site1.mjs
иastro.config.site2.mjs
). - В
package.json
прописать разные скрипты:{ "scripts": { "build:site1": "astro build --config astro.config.site1.mjs", "build:site2": "astro build --config astro.config.site2.mjs" } }
- В каждом конфиге указывать:
- свой
base
илиsite
для генерации ссылок, - разные entry-папки для страниц (
src/pages_site1
,src/pages_site2
), - но общий доступ к компонентам (
src/components
).
- свой
🔹 Вариант 3. Один билд → разные домены
Если проекты отличаются только роутингом или контентом, можно:
- Сгенерировать один билд и раздавать его под разными URL через настройки хостинга/прокси.
- Но это подходит только если проекты почти идентичные.
✅ Итого: да, в Astro можно держать несколько “проектов” в одном репо и даже собирать их из одних и тех же компонентов. Выбор подхода зависит от того, насколько сильно эти проекты должны различаться.
Отлично 👍
Если контент отличается, а дизайн и компоненты общие — тебе подойдёт вариант 2 с двумя конфигами. Ниже пример структуры и настроек.
📁 Структура проекта
project/
├─ src/
│ ├─ components/ # общие компоненты
│ ├─ pages_site1/ # страницы первого сайта
│ ├─ pages_site2/ # страницы второго сайта
│ └─ layouts/ # общие лейауты
├─ astro.config.site1.mjs
├─ astro.config.site2.mjs
├─ package.json
⚙️ Конфиги
astro.config.site1.mjs
import { defineConfig } from "astro/config";
export default defineConfig({
root: "./src/pages_site1", // где искать страницы
outDir: "./dist/site1", // куда билдить
site: "https://site1.example.com", // URL для генерации ссылок
});
astro.config.site2.mjs
import { defineConfig } from "astro/config";
export default defineConfig({
root: "./src/pages_site2",
outDir: "./dist/site2",
site: "https://site2.example.com",
});
📜 Скрипты в package.json
{
"scripts": {
"dev:site1": "astro dev --config astro.config.site1.mjs",
"dev:site2": "astro dev --config astro.config.site2.mjs",
"build:site1": "astro build --config astro.config.site1.mjs",
"build:site2": "astro build --config astro.config.site2.mjs"
}
}
✅ Как это работает
npm run dev:site1
→ поднимается dev-сервер для первого сайта.npm run dev:site2
→ dev-сервер второго.- После билда ты получаешь:
которые можно залить на разные URL.dist/ site1/ site2/
👉 В src/components/
и src/layouts/
кладёшь общие части.
👉 В src/pages_site1/
и src/pages_site2/
кладёшь уникальные страницы и контент.
👉 Если нужен общий контент (например Markdown-посты) — можно завести ещё src/content/
и подключать оттуда.
Отличный вопрос 👌
Для локальной разработки у тебя будет два дев-сервера, каждый со своим конфигом. То есть ты выбираешь, какой проект сейчас разрабатывать.
🔹 Вариант 1. Запуск через скрипты
В package.json
мы уже прописали:
{
"scripts": {
"dev:site1": "astro dev --config astro.config.site1.mjs --port 4321",
"dev:site2": "astro dev --config astro.config.site2.mjs --port 4322"
}
}
npm run dev:site1
→ поднимается сервер для сайта 1 (например на http://localhost:4321).npm run dev:site2
→ поднимается сервер для сайта 2 (например на http://localhost:4322).
👉 Порты лучше указать разные, иначе Astro будет ругаться на конфликт.
🔹 Вариант 2. Параллельный запуск
Если хочется одновременно держать оба проекта поднятыми, можно поставить concurrently:
npm install concurrently --save-dev
И добавить в package.json
:
{
"scripts": {
"dev:site1": "astro dev --config astro.config.site1.mjs --port 4321",
"dev:site2": "astro dev --config astro.config.site2.mjs --port 4322",
"dev:all": "concurrently \"npm run dev:site1\" \"npm run dev:site2\""
}
}
Теперь npm run dev:all
запустит оба проекта одновременно.
🔹 Вариант 3. Monorepo (NX / Turborepo / pnpm workspaces)
Если захочешь разнести сайты по папкам /apps/site1
и /apps/site2
, то дев-серверы будут запускаться отдельно из каждой папки. Это чуть более “enterprise”, но и чище для больших проектов.
Да, всё верно 👍
В одном Astro-проекте ты можешь держать несколько конфигураций билдов, хоть десяток.
Astro устроен так, что:
🔹 Почему это работает
- Изоляция билдов
Каждый билд использует свойastro.config.*.mjs
и собирается в свою папку (dist/site1
,dist/site2
, …). Поэтому никакого конфликта нет — сборки полностью независимы. - Компоненты на React / Vue / Svelte / Solid и т.д.
Astro рендерит их в “острова” (islands). Каждый остров получает свою среду выполнения, поэтому React-компоненты не пересекаются с Vue или Svelte.
Даже если ты вsite1
используешь React, а вsite2
— Vue, это будет работать без проблем. - Оптимизация бандла
При сборке Astro автоматически включит только те зависимости, которые реально нужны конкретному сайту. Например, если вsite1
у тебя нет Vue-компонентов, Vue в бандл не попадёт.
🔹 Возможные нюансы
- Если у тебя общие компоненты (например
src/components/Button.astro
) и они зависят от конкретного фреймворка, то при сборке других сайтов этот фреймворк может подтянуться.
👉 Решается разделением:components/react/
,components/vue/
, и подключаешь только нужное. - Если используешь разные CSS-фреймворки (например Tailwind и UnoCSS в разных сайтах) — тогда лучше держать отдельные конфиги (иначе могут наложиться стили).
🔹 Вывод
👉 Да, можно в одном Astro-проекте держать несколько билдов, хоть на разные домены.
👉 Конфликтов между React / Vue / Svelte не будет — Astro сам разделяет их окружения.
👉 Главное — грамотно организовать структуру и конфиги, чтобы каждая сборка тянула только нужное.
О, супер-идея 🚀
Astro как раз отлично подходит для подхода “constructor / design system → несколько сайтов”. Ты можешь держать общую библиотеку компонентов, а затем собирать из них разные билды (сайты), каждый со своим контентом и конфигом.
📁 Структура проекта с 3 сайтами
Пример: один сайт на React-компонентах, второй на Vue, третий — чисто на Markdown+Astro.
project/
├─ src/
│ ├─ components/
│ │ ├─ ui/ # универсальные Astro-компоненты
│ │ ├─ react/ # React-компоненты
│ │ ├─ vue/ # Vue-компоненты
│ │ └─ svelte/ # (по желанию)
│ ├─ layouts/ # общие лейауты
│ ├─ pages_site1/ # сайт 1 (React)
│ ├─ pages_site2/ # сайт 2 (Vue)
│ ├─ pages_site3/ # сайт 3 (Markdown)
│ └─ content/ # общий контент (md/mdx)
├─ astro.config.site1.mjs
├─ astro.config.site2.mjs
├─ astro.config.site3.mjs
├─ package.json
⚙️ Конфиги
astro.config.site1.mjs
— сайт с React
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
export default defineConfig({
root: "./src/pages_site1",
outDir: "./dist/site1",
integrations: [react()],
site: "https://site1.example.com",
});
astro.config.site2.mjs
— сайт с Vue
import { defineConfig } from "astro/config";
import vue from "@astrojs/vue";
export default defineConfig({
root: "./src/pages_site2",
outDir: "./dist/site2",
integrations: [vue()],
site: "https://site2.example.com",
});
astro.config.site3.mjs
— чисто Markdown + Astro
import { defineConfig } from "astro/config";
export default defineConfig({
root: "./src/pages_site3",
outDir: "./dist/site3",
site: "https://site3.example.com",
});
📜 package.json
{
"scripts": {
"dev:site1": "astro dev --config astro.config.site1.mjs --port 4321",
"dev:site2": "astro dev --config astro.config.site2.mjs --port 4322",
"dev:site3": "astro dev --config astro.config.site3.mjs --port 4323",
"build:site1": "astro build --config astro.config.site1.mjs",
"build:site2": "astro build --config astro.config.site2.mjs",
"build:site3": "astro build --config astro.config.site3.mjs"
}
}
🔨 Использование конструктора
- В
/src/components/ui/
кладёшь “чистые” Astro-компоненты (Header.astro
,Footer.astro
,Card.astro
). - В
/src/components/react/
и/src/components/vue/
— более сложные интерактивные элементы. - В каждой
pages_siteX
ты собираешь страницы из этого конструктора:--- import Header from '../components/ui/Header.astro'; import FancyChart from '../components/react/FancyChart.jsx'; --- <Header title="Мой React-сайт" /> <FancyChart />
Astro при сборке:
- В site1 подтянет React и только те компоненты, что реально нужны.
- В site2 подтянет Vue и только используемые компоненты.
- В site3 не будет ни React, ни Vue (только Astro + Markdown).
✅ Что это даёт
- Единый набор компонентов = меньше дублирования.
- Можно делать новые сайты “из кубиков”, не копируя код.
- Каждая сборка остаётся изолированной → нет конфликтов React/Vue/Svelte.
- Проект масштабируется: можно хоть 10 билдов собрать.
Крутой вопрос 🙌
Если ты делаешь конструктор и хочешь собирать сайты из «кубиков», то репо действительно может быстро раздуться. Но есть несколько способов держать его в порядке.
🔹 Как не разрастить репо
-
Монорепо-подход
Вместо одного жирного Astro-проекта можно завести структуру вида:/apps /site1 /site2 /site3 /packages /ui # общие Astro-компоненты /blocks # готовые секции (hero, gallery, form и т.п.) /content # общий контент (md/mdx, json, yml)
→ Тогда новые сайты живут в
/apps
, а компоненты переиспользуются из/packages
. -
Хранить контент отдельно
- Саму «сборку» сайтов держать в Astro-репо.
- А контент (JSON/MD/MDX/другой формат) можно вынести в отдельный репозиторий или CMS (например Sanity, Contentful, Strapi).
- Astro будет просто подтягивать данные во время билда.
-
Компоненты-«кирпичи»
- Вместо копипаста страниц — делать универсальные блоки:
Hero.astro
,Features.astro
,CTA.astro
. - Страницы описывать декларативно в JSON/MDX → меньше кода, меньше дублирования.
- Вместо копипаста страниц — делать универсальные блоки:
🔹 Пример: генерация страницы из JSON
/src/content/pages/landing.json
{
"title": "Главная страница",
"blocks": [
{
"type": "Hero",
"props": { "title": "Добро пожаловать", "subtitle": "Сайт №1" }
},
{
"type": "Features",
"props": { "items": ["Быстро", "Удобно", "Надёжно"] }
},
{ "type": "CTA", "props": { "button": "Попробовать" } }
]
}
/src/pages/[slug].astro
---
import blocks from '../components/blocks'; // словарь: { Hero, Features, CTA }
import pageData from '../content/pages/landing.json';
const { title, blocks: pageBlocks } = pageData;
---
<html>
<head><title>{title}</title></head>
<body>
{pageBlocks.map(({ type, props }) => {
const Block = blocks[type];
return <Block {...props} />;
})}
</body>
</html>
/src/components/blocks/index.js
import Hero from "./Hero.astro";
import Features from "./Features.astro";
import CTA from "./CTA.astro";
export default { Hero, Features, CTA };
🔹 Вариант с MD/MDX (для себя)
Astro уже из коробки поддерживает Markdown:
src/content/blog/post1.md
src/content/pages/landing.mdx
А ты можешь их обогащать JSX/компонентами.
post1.md:
---
title: "Первый пост"
date: "2025-09-09"
---
Привет! Это мой первый пост.
<Hero title="MDX блок внутри Markdown" />
🔹 Вариант с CMS (для заказчиков)
Astro умеет подключаться к любым headless CMS через fetch/SDK:
Популярные варианты:
- Sanity → удобно для структурированного контента (гибкая схема).
- Contentful → стабильная SaaS CMS, UI понятен заказчикам.
- Strapi → self-hosted, если нужен полный контроль.
- Directus → похож на Strapi, но очень простой UI.
Пример (Astro + Sanity):
// src/lib/sanity.js
import { createClient } from "@sanity/client";
export const client = createClient({
projectId: "xxxx",
dataset: "production",
apiVersion: "2025-09-01",
useCdn: true,
});
---
import { client } from "../lib/sanity";
const posts = await client.fetch(`*[_type == "post"]{title, body}`);
---
<ul>
{posts.map(post => <li>{post.title}</li>)}
</ul>
🔹 Гибридная модель
Ты можешь настроить разные источники в одном проекте:
- MD/MDX для системных страниц (тебе удобно быстро править).
- CMS для заказчика → он меняет контент без Git.
Например:
src/content/pages/*.mdx
— твои тестовые страницы.- CMS (Sanity/Contentful) → блог/портфолио/новости, которые заказчик меняет.
Astro всё это стянет во время билда → сайты собираются в единый билд.