Настроить портал
Развертывание шаблона под новый портал — название, репозиторий, навигация и заглушки.
Настройка нового портала сводится к правке lib/portal.config.ts. Компоненты и
layout читают значения оттуда.
Обязательный минимум
Название и описание
export const portalConfig = {
name: 'Payment Gateway Documentation',
shortName: 'PG Docs',
tagline: 'Документация платежного шлюза',
description: 'Подключение, спецификации API и эксплуатационные материалы.',
// ...
};| Поле | Где отображается |
|---|---|
name | Шаблон <title> всех страниц, Open Graph-изображения. |
shortName | Подпись рядом с логотипом в навбаре. |
tagline | Заголовок hero-блока главной страницы. |
description | Подзаголовок hero-блока и meta description. |
Координаты репозитория
git: {
user: 'ReactiveEngineering',
repo: 'payment-gateway-docs',
branch: 'main',
},Отсюда формируются ссылка на репозиторий в навбаре и кнопка «View on GitHub» на каждой странице документации.
Проверьте имя репозитория
Несовпадение repo с фактическим именем репозитория даёт битые ссылки на
каждой странице документации — внешне портал при этом работает нормально.
Список продуктов
products: [
{
slug: 'payment-gateway',
title: 'Payment Gateway',
description: 'Платежный шлюз: подключение, API и эксплуатация.',
icon: 'CreditCard',
},
],slug — имя каталога в content/docs/. Подробнее:
Добавить продукт.
Адрес портала
NEXT_PUBLIC_SITE_URL=https://docs.example.comЗначение попадает в metadataBase и делает Open Graph-ссылки абсолютными.
Связанные порталы и навигация
Массив externalPortals формирует и пункты верхней навигации, и карточки в
нижней части главной страницы.
externalPortals: [
{
title: 'Swagger',
description: 'Интерактивные спецификации OpenAPI.',
href: 'https://swagger.example.com',
external: true,
},
],| Поле | Назначение |
|---|---|
href | Внутренний путь или полный внешний адрес. |
external | true — ссылка открывается в новой вкладке. |
Чтобы убрать блок связанных порталов целиком, оставьте массив пустым — раздел на главной странице не отрендерится.
Эта навигация отображается только на главной странице и на заглушках. В
разделе документации она скрыта: боковое меню там отведено под структуру
документации, а возврат на / выполняется по логотипу в его заголовке.
Поведение бокового меню
links={[]}
sidebar={{ defaultOpenLevel: EXPAND_ALL_LEVELS }}
tabMode="auto"| Параметр | Действие |
|---|---|
links={[]} | Убирает навигацию портала из бокового меню. |
sidebar.defaultOpenLevel | Разворачивает разделы при первой отрисовке: папка открыта, если defaultOpenLevel >= depth. Константа EXPAND_ALL_LEVELS заведомо больше любой реальной вложенности, поэтому раскрыто всё дерево — включая разделы, добавленные позже. |
tabs | Список продуктов для переключателя, см. ниже. |
tabMode="auto" | Рисует переключатель выпадающим списком над боковым меню. |
Как свернуть дерево
Значение Fumadocs по умолчанию — 0, все папки свёрнуты. Уменьшите
defaultOpenLevel до 1, чтобы открыть только верхний уровень. Поведение
отдельной папки переопределяется полем defaultOpen в её meta.json.
Переключатель продуктов на корневой странице
Fumadocs строит вкладки из каталогов с "root": true, но рисует выпадающий
список только пока какая-то вкладка активна. На /docs читатель находится
вне любого продукта, поэтому переключатель исчезал именно там, где он нужнее
всего.
Поэтому список вкладок собирается вручную, и первым элементом идёт обзорная страница:
const tabs: LayoutTab[] = [
{
title: 'Обзор портала',
description: 'Точка входа и правила навигации по порталу',
url: docsRoute,
icon: <House />,
},
...getLayoutTabs(tree),
];Вкладка без привязки к дереву страниц ($folder) активна по вложенному URL,
поэтому /docs делает её активной — как и любая страница внутри. Выпадающий
список выбирает последнюю подходящую вкладку, отсюда порядок: внутри
продукта побеждает его собственная вкладка, на корне остаётся только обзор.
Обзорная запись попадает и в сам список — это одновременно путь назад к /docs.
Страницы-заглушки
/swagger и /flows по умолчанию показывают страницу «раздел в подготовке».
Тексты и планируемый адрес задаются в конфигурации:
placeholders: {
swagger: {
title: 'Swagger-портал',
eyebrow: 'Раздел в подготовке',
description: 'Здесь появится интерактивная спецификация OpenAPI.',
target: 'https://swagger.example.com',
},
},Замена заглушки редиректом
import { redirect } from 'next/navigation';
import { portalConfig } from '@/lib/portal.config';
export default function SwaggerPage() {
redirect(portalConfig.placeholders.swagger.target);
}Альтернатива без страницы — редирект на уровне конфигурации Next.js:
const config = {
reactStrictMode: true,
output: 'standalone',
async redirects() {
return [
{
source: '/swagger',
destination: 'https://swagger.example.com',
permanent: false,
},
];
},
};Удаление раздела
Удалите каталог app/swagger/ и соответствующую запись из externalPortals и
placeholders.
Смена языка интерфейса
Атрибут lang задан в app/layout.tsx:
<html lang="ru" suppressHydrationWarning>Подписи навигации находятся в lib/layout.shared.tsx, тексты главной страницы —
в app/page.tsx и lib/portal.config.ts.
Брендинг
Палитра, шрифты и логотипы описаны в разделе Бренд и стили.

