FrontBean — расширенная документация
Эта страница дополняет README и описывает проект подробнее: структуру папок, окружение, внутренние модули, паттерны, рецепты и тонкости эксплуатации.
- Стек: Nuxt 4 (Vue 3 + TypeScript), Tailwind CSS 4, shadcn‑nuxt UI, @nuxt/image, @nuxt/icon, @nuxt/content, @nuxtjs/i18n, @nuxtjs/sitemap, ESLint + Prettier.
- Бэкенд взаимодействие: собственный HTTP‑клиент поверх ofetch с единым источником заголовков и перехватчиками.
- Типы API: генерация из OpenAPI схемы (@hey-api/openapi-ts) в shared/types.
- Док‑раздел UI (/docs) включается только когда активирован флаг окружения NUXT_ENABLE_CONTENT=true. В продакшене по умолчанию раздел отключён.
Требования и запуск
Запуск с nuxt/content и без него
Раздел /docs и модуль @nuxt/content включаются только когда задано NUXT_ENABLE_CONTENT=true.
- Dev с документацией: установить в .env
NUXT_ENABLE_CONTENT=trueи выполнитьnpm run dev. - Prod-сборка без документации: не задавайте флаг и выполните
npm run build && npm run preview. - Node.js >= 21.7.2 (см. engines в package.json)
- Любой пакетный менеджер: npm / pnpm / yarn / bun
Команды:
# Установка зависимостей
npm install
# Локальная разработка
npm run dev
# Сборка production
npm run build
# Предпросмотр собранного билда
npm run preview
# Генерация типов из OpenAPI
npm run generate:openapi-ts
Переменные окружения (.env)
Проект использует runtimeConfig Nuxt. Значения читаются на сервере (private runtime config) и не попадают в клиентский бандл.
- NUXT_API_BASE — базовый адрес бэкенда (например, https://api.example.com)
- NUXT_API_AUTH — строка для заголовка Authorization; автоматически добавляется только в dev или если base содержит «servertest»
- NUXT_API_TOKEN — токен, который будет подставлен в заголовок X-Access-Token
- NUXT_PORT — порт, на котором запуститься приложение
- NUXT_HOST — хост, на котором запуститься приложение
Пример .env:
NUXT_API_BASE=https://api.example.com
NUXT_API_AUTH=Basic xxxxxx
NUXT_API_TOKEN=YOUR_TOKEN
NUXT_PORT=5173
NUXT_HOST=0.0.0.0
Тонкости:
- Строки без лишних пробелов и кавычек. Для Basic/Token схем не добавляйте слово «Bearer», если оно уже включено.
- Эти переменные не доступны на клиенте (public runtimeConfig их не содержит). Для клиентских запросов используйте серверные маршруты‑прокси.
Структура папок
Ниже упрощённое дерево с пояснениями основных каталогов и ключевых файлов.
frontBean/
├─ app/ # Приложение Nuxt: страницы, макеты, компоненты, стили
│ ├─ app.vue # Корневой компонент приложения
│ ├─ assets/
│ │ └─ css/tailwind.css # Входная точка Tailwind CSS 4
│ ├─ components/
│ │ └─ ui/
│ │ └─ button/
│ │ ├─ UIButton.vue # Пример UI-компонента (shadcn-нэйминг, без префикса)
│ │ └─ button.ts # Варианты/типы кнопок
│ ├─ layouts/
│ │ └─ docs.vue # Макет для раздела UI-доков (dev-only)
│ ├─ middleware/ # (не используется для скрытия /docs)
│ │ └─ ...
│ └─ pages/
│ └─ docs/
│ ├─ index.vue # Точка входа UI-доков
│ └─ ui/
│ └─ buttons.vue # Пример страницы с демо кнопок
│
├─ content/
│ └─ docs/
│ └─ index.md # Эта расширенная документация (Nuxt Content)
│
├─ server/ # Серверная часть (Nitro)
│ ├─ api/
│ │ └─ init.ts # Агрегация стартовых данных из удалённого API
│ └─ utils/
│ └─ http.ts # Кастомный HTTP-клиент на базе ofetch
│
├─ i18n/
│ └─ locales/
│ ├─ ru.json # Русская локаль
│ └─ en.json # Английская локаль
│
├─ shared/ # Общие модули и сгенерированные типы
│ └─ types/ # Результат генерации @hey-api/openapi-ts
│
├─ public/ # Статика, шрифты, изображения
├─ modules/ # (опционально) Пользовательские модули Nuxt
├─ lib/ # Внутренние утилиты/библиотеки (если есть)
├─ configs/
│ └─ tsconfig.app.json # Доп. tsconfig для области app/
│
├─ components.json # Конфиг shadcn-nuxt (директория компонентов и др.)
├─ nuxt.config.ts # Конфигурация Nuxt
├─ openapi-ts.config.ts # Конфиг генерации типов из OpenAPI
├─ eslint.config.mjs # ESLint конфигурация
├─ tsconfig.json # Базовый TS-конфиг
└─ README.md # Краткая документация
Конфигурация Nuxt (nuxt.config.ts)
Ключевые моменты:
- alias:
- #shared → ./shared
- #modules → ./modules
- #server → ./server
- #lib → ./lib
- components → ./app/components/
- modules: @nuxt/eslint, @nuxt/icon, @nuxt/image, shadcn-nuxt, @vueuse/nuxt, @nuxtjs/i18n, @nuxtjs/sitemap, @nuxt/content
- css: ./app/assets/css/tailwind.css (Tailwind CSS 4 через Vite плагин @tailwindcss/vite)
- i18n: локали ru/en, стратегия no_prefix, автоопределение языка с cookie i18n_redirected
- runtimeConfig: apiBase, apiAuth, apiToken (private); public: { isDev }
HTTP‑клиент (server/utils/http.ts)
Класс HttpClient инкапсулирует $fetch с перехватчиками и единым источником заголовков. Экспортируется экземпляр serverHttp и вспомогательная функция httpRequest.
Особенности:
- Базовый URL берётся из runtimeConfig.apiBase.
- Заголовки собираются из defaults клиента + per-request, нормализуются и устанавливаются строго в хук onRequest.
- Авто‑инъекции:
- X-Access-Token ← runtimeConfig.apiToken (если не задан в запросе).
- Authorization ← runtimeConfig.apiAuth (только в dev или если apiBase содержит «servertest»; регистронезависимо).
- Поддержка перехватчиков onRequest, onResponse, onError на уровне клиента и конкретного запроса.
- Гибкая обработка ответа: parseAs: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'response' (raw Response через instance.raw).
- Ошибки приводятся к ApiError со свойствами status, statusText, method, url, data, cause.
Пример использования в серверном обработчике:
import { defineEventHandler } from 'h3';
import { serverHttp, ApiError } from 'server/utils/http';
export default defineEventHandler(async (event) => {
try {
const data = await serverHttp.get('/api/example/', {
params: { page: 1 }
});
return data;
} catch (e) {
if (e instanceof ApiError) {
return { message: e.message, status: e.status, details: e.data };
}
throw e;
}
});
Важно:
- Не используйте serverHttp на клиенте: private runtimeConfig (apiBase/apiAuth/apiToken) недоступен на клиентской стороне. Для браузерных вызовов вызывайте ваши серверные маршруты (например, /api/...) или предусмотрите публичный прокси.
- Если baseURL не задан — будет выброшен ApiError("Base URL is not defined"). Проверьте .env и переменные в окружении деплоя.
Серверные маршруты
GET /api/init
Агрегирует начальные данные параллельными запросами:
- /api/configs/
- /api/menus/
- /api/feedback/
Возвращает объект: { configs, menus, feedback }.
Ошибки ApiError преобразуются в JSON с корректным HTTP‑статусом.
Генерация типов из OpenAPI
Конфиг: openapi-ts.config.ts
- input.path строится из
${NUXT_API_BASE}/api/schema.yaml - В запрос подстановки схемы прокидывается заголовок Authorization из
NUXT_API_AUTH - Вывод: каталог
shared/types - Плагины:
@hey-api/typescript
Запуск:
npm run generate:openapi-ts
Советы:
- При изменении схемы включён
watch: true, но при проблемах с авторизацией перезапустите команду вручную. - Типы доступны через алиас #shared, например
import type { SomeType } from '#shared/types/types.gen'.
Мультиязычность (@nuxtjs/i18n)
- Локали: ru (по умолчанию), en
- Стратегия:
no_prefix— без префикса в URL - Файлы переводов:
i18n/locales/ru.json,i18n/locales/en.json - Автоопределение языка: включено, cookie
i18n_redirected, редирект только с корня (redirectOn: 'root')
Добавление новой локали:
- Создайте файл переводов в
i18n/locales/<code>.json. - Добавьте запись в
nuxt.config.ts→i18n.locales. - При необходимости поменяйте
defaultLocale.
SEO подсказки:
- При стратегии без префикса учитывайте
<html lang>и мета‑теги для корректной индексации.
UI, стили и иконки
- Tailwind CSS 4 подключён через Vite плагин
@tailwindcss/vite(см. nuxt.config.ts → vite.plugins). - shadcn-nuxt:
- prefix: '' (компоненты без префикса)
- componentDir:
./app/components/shadcn - настройки в
components.json
- @nuxt/icon — иконки через компонент
<Icon name="..." />(см. примеры в docs макете). - @nuxt/image — оптимизация изображений; используйте
<NuxtImg>вместо<img>.
Пример использования UI кнопки:
<script setup lang="ts">
import UIButton from 'components/ui/button/Button.vue'
</script>
<template>
<UIButton variant="primary" size="m">Отправить</UIButton>
</template>
Док‑раздел UI (/docs)
- Макет:
app/layouts/docs.vue— левое меню, слот контента. - Страницы примеров:
app/pages/docs/**/*. В продакшене по умолчанию отсутствуют, если NUXT_ENABLE_CONTENT не задан или равен false. - Чтобы открыть локально: запустите
npm run devи перейдите наhttp://localhost:3000/docs.
Качество кода
- ESLint:
eslint.config.mjs(Vue + TS правила) - Prettier: форматирование кода
- Devtools: включены (
devtools.enabled = true) для удобной отладки
Рецепты
1. Добавить серверный эндпоинт
- Создайте файл, например
server/api/users.get.ts. - Используйте
serverHttpдля запроса к внешнему API.
import { defineEventHandler } from 'h3';
import { serverHttp } from '#server/utils/http';
export default defineEventHandler(async () => {
return serverHttp.get('/api/users/');
});
2. Использовать HTTP‑клиент с перехватчиками
import { serverHttp } from '#server/utils/http';
serverHttp.get('/api/example/', {
interceptors: {
onRequest: ({ url, init }) => console.debug('→', init.method, url.toString()),
onResponse: ({ response }) => console.debug('←', response.status),
onError: ({ error }) => console.error('×', error)
}
});
3. Добавить страницу
- Создайте
app/pages/my-page.vue. Nuxt автоматически добавит маршрут/my-page.
4. Добавить локаль
- См. раздел «Мультиязычность». Не забудьте обновить
i18n.localesи файл переводов.
5. Добавить UI‑компонент
- Поместите компонент в
app/components/ui/<block>/<Name>.vueи используйте через алиасcomponents.
Тонкости и частые проблемы
- 401/403 в dev: проверьте
NUXT_API_AUTHи что dev режим действительно включён (на клиент Authorization не подставляется). - 401 в prod: заголовок Authorization автоматически НЕ подставляется. Настройте бэкенд или используйте серверные токены.
- 500 от /api/init: проверьте доступность
${NUXT_API_BASE}и корректность путей/api/configs/,/api/menus/,/api/feedback/. - Base URL is not defined: убедитесь, что переменная
NUXT_API_BASEзадана в окружении процесса (PM2, Docker, сервер хостинга и т.д.). - CORS: выполняйте запросы к внешнему API из серверных обработчиков, а не напрямую из браузера.
Плагины Nitro: счётчики и sitemap
README описывает два плагина (вставка счётчиков/мета и подмена sitemap URL-ов). Если они отсутствуют в текущей ревизии проекта, ориентируйтесь на документацию:
- counters.ts: hook
render:responseдля вставки HTML‑фрагментов из/api/configs/в head/body. - sitemap.ts: hook
sitemap:resolved(@nuxtjs/sitemap) и подменаctx.urlsданными из/api/sitemaps/.
Полезные ссылки
- Nuxt 4: https://nuxt.com
- ofetch: https://github.com/unjs/ofetch
- @hey-api/openapi-ts: https://github.com/hey-api/openapi-ts
- @nuxt/content: https://content.nuxt.com
- @nuxt/image: https://image.nuxt.com
- @nuxt/icon: https://github.com/nuxt/icon
- @nuxtjs/i18n: https://i18n.nuxtjs.org
- shadcn-nuxt: https://github.com/unovue/shadcn-nuxt