Редакционный сайт на Nuxt 4 для статей и локальных видео. Контент хранится отдельно от компонентов, валидируется перед сборкой и не требует правок Vue-кода при публикации.
- полностью переработаны главная, каталог статей, статья, видеотека, видео, календарь, страницы проекта, контактов и конфиденциальности;
- 24 исходные статьи перенесены в Markdown и добавлены ещё 12 материалов;
- каждая статья находится в своей папке вместе с обложкой и дополнительными изображениями;
- каждое видео находится в своей папке вместе с
config.yml, постером иvideo.mp4; - удалены случайные просмотры, лайки и неработающая регистрация;
- добавлены sitemap, RSS, robots.txt, JSON-LD, canonical URL, Open Graph, health-check и защитные HTTP-заголовки;
- Docker-контейнер запускается от непривилегированного пользователя, с read-only filesystem и проверкой здоровья;
- контент автоматически проверяется и собирается перед
dev,buildиgenerate.
Требуется Node.js 22.18 или новее.
cp .env.example .env
npm ci
npm run devНа Windows команды выполняются из PowerShell или cmd так же, без cp:
Copy-Item .env.example .env
npm ci
npm run devВерсия 2.0.1 запускает Nuxt CLI напрямую через текущий node.exe. Это устраняет Error: spawn EINVAL, возникавшую в версии 2.0.0 на Windows с Node.js 24.
Проверка production-сборки:
npm run check
npm run previewДля репозитория добавлен GitHub Actions workflow: он проверяет контент, TypeScript, Nuxt-сборку и отдельно собирает Docker-образ.
content/
├── site.json
├── articles/
│ └── article-slug/
│ ├── article.md
│ ├── cover.svg
│ └── optional-photo.webp
└── videos/
└── video-slug/
├── config.yml
├── poster.svg
└── video.mp4
Подробная памятка находится в content/README.md.
npm run new:article -- poliv-grushi-letom "Как поливать грушу летом"npm run new:video -- poliv-teplicy "Полив теплицы утром"Новые материалы создаются как черновики. После заполнения поставьте status: "published" и запустите:
npm run content:buildОсновные тексты главной страницы, сезонный блок и подпись футера находятся в content/site.json.
Переменные окружения:
NUXT_PUBLIC_SITE_URL=https://dacha-praktik.ru
NUXT_PUBLIC_CONTACT_EMAIL=editor@dacha-praktik.ruПосле смены домена обязательно обновите обе переменные: они используются в canonical URL, sitemap, RSS и Open Graph.
Video binaries and cover images are deliberately not stored in Git. Their names, sizes and SHA-256 checksums are committed in content/media-manifest.json; a bad or incomplete download will therefore never be served accidentally. After syncing, content/ is their only local copy: Nuxt serves it directly at /media/..., including HTTP Range support for video. No files are copied into public/ or a second video directory.
Before the first deployment, upload every object from the manifest to private HTTPS storage at the same relative path. For example, videos/podvyazka-tomatov-v-teplice/video.mp4 must be available as <DECOY_MEDIA_BASE_URL>/videos/podvyazka-tomatov-v-teplice/video.mp4.
Cloudflare R2 is supported directly. Set DECOY_R2_ENDPOINT, DECOY_R2_BUCKET, DECOY_R2_ACCESS_KEY_ID and DECOY_R2_SECRET_ACCESS_KEY in decoy/.env. Use an Object Read & Write key only for uploading; deployment servers need a separate Object Read-only key. Node.js and npm are not required on the host: Docker runs both media tools. Then download and verify all decoy media:
docker compose run --rm --build media-syncRun the sync on the server before starting the application. It skips intact local files and downloads only missing or changed files. The token is used only for the server-to-storage download; visitors receive media from this server, not from the object storage. The server needs only Docker Compose; npm is neither installed nor invoked on the host.
When adding or replacing video locally, upload it to storage and run this before committing:
cd decoy
npm run media:manifest
docker compose run --rm --build media-uploadCommit the updated manifest, config and poster — never the video binary.
Сервис ожидает существующую внешнюю сеть reverse-proxy-network:
docker network create reverse-proxy-network
cp .env.example .env
docker compose run --rm --build media-sync
docker compose up -d --buildКонтейнер слушает порт 3000 только внутри Docker-сети. TLS и публичный маршрут должны завершаться на Traefik или другом reverse proxy.
| Команда | Назначение |
|---|---|
npm run dev |
сборка контента, Nuxt dev server и наблюдение за content/ |
npm run content:check |
проверка метаданных и файлов без перезаписи output |
npm run content:build |
генерация JSON-индексов и копирование медиа |
npm run source:check |
синтаксическая проверка TypeScript и <script> в Vue |
npm run typecheck |
проверка контента, Nuxt-типов и TypeScript |
npm run build |
production-сборка |
npm run check |
полный цикл проверок и сборки |
Полный список действий перед публикацией: PRODUCTION_CHECKLIST.md.
В архиве лежат короткие валидные MP4-заставки, чтобы проигрыватель и Docker-сборка работали сразу. В config.yml таких роликов стоит placeholder: true. Замените video.mp4, обновите duration, поставьте placeholder: false и при необходимости измените текст note.