Вы запускаете SaaS-продукт — ежемесячно приходит 500+ запросов на фичи. Команда тратит 10 часов в неделю на внутренние отчёты и ответы пользователям. Публичный roadmap автоматизирует это: пользователи сами видят статусы, а команда экономит ресурсы. Один из наших клиентов отметил: «Публичный roadmap сократил количество обращений в поддержку на 40% уже в первый месяц». — Клиент, SaaS-проект Без такой страницы пользователи теряют терпение, что увеличивает отток и нагрузку на саппорт.
Разработка публичной roadmap-страницы с интеграцией Notion или Jira — это решение, которое позволяет пользователям отслеживать статусы фич. Мы, как разработчики, ставим во главу угла производительность: страница должна грузиться за <1 с, обновляться без ручного деплоя и интегрироваться с вашими инструментами (Notion, Jira, Linear). Ниже — архитектурное решение с ISR-кэшированием, Kanban-доской и автоматическими уведомлениями. Оно подходит для продуктовых команд любого размера и окупается менее чем за 3 месяца.
Почему публичный roadmap повышает доверие пользователей?
Пользователи устают от «скоро» без дат. Когда они видят, что их фича перешла из «запланировано» в «в работе» и наконец в «выпущено» — это доказывает: их голос услышали. По данным Wikipedia, roadmap в продуктовой разработке — это стратегический документ. Наша страница — его публичная проекция, синхронизированная с реальным бэклогом.
Источники данных: Notion vs собственная БД
Выбор источника влияет на автономность и скорость. Сравним:
| Критерий | Notion как CMS | Собственная таблица (Laravel/PostgreSQL) |
|---|---|---|
| Гибкость схемы | Ограничена свойствами | Любые поля и связи |
| Скорость запроса | ~300–500 мс (API) | ~10–20 мс (индексы) |
| Администрирование | Не нужно | Миграции, админка |
| Офлайн-доступ | Зависит от Notion | Полный контроль |
| Кастомизация вывода | Только сортировка/фильтр | Любая логика |
Если команда мала и не хочет разрабатывать админку — выбирайте Notion. Для высоконагруженного проекта с кастомными отчётами — собственные таблицы. Последний вариант в 5 раз быстрее на запросах выборки.
Пример интеграции с Notion:
// lib/roadmap.ts
import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_TOKEN });
export interface RoadmapItem {
id: string;
title: string;
status: 'planned' | 'in_progress' | 'done';
quarter: string; // 'Q1'
category: string;
votes: number;
description: string;
}
export async function getRoadmap(): Promise<RoadmapItem[]> {
const response = await notion.databases.query({
database_id: process.env.NOTION_ROADMAP_DB_ID!,
filter: {
property: 'Public',
checkbox: { equals: true },
},
sorts: [{ property: 'Quarter', direction: 'ascending' }],
});
return response.results.map(page => ({
id: page.id,
title: page.properties.Name.title[0]?.plain_text ?? '',
status: page.properties.Status.select?.name?.toLowerCase().replace(' ', '_') as any,
quarter: page.properties.Quarter.select?.name ?? '',
category: page.properties.Category.select?.name ?? '',
votes: page.properties.Votes.number ?? 0,
description: page.properties.Description.rich_text[0]?.plain_text ?? '',
}));
}
Собственная таблица в Laravel создаётся миграцией с полями title, status, quarter, category, sort_order, is_public. Это даёт полный контроль и скорость.
Как организовать Kanban-доску без перезагрузки?
Фронтенд на React (или Vue) отрисовывает три колонки: «Запланировано», «В работе», «Готово». Каждая карточка содержит категорию, квартал, название и описание. Фильтрация — клиентская, без запросов к серверу. Для управления состоянием используем zustand — это упрощает синхронизацию фильтров.
Пошаговая реализация:
- Настройте хранилище zustand с полями filterCategory и searchQuery.
- Создайте компонент колонки, принимающий массив items и отображающий карточки.
- Реализуйте фильтрацию через useMemo — она работает мгновенно без лишних рендеров.
- Добавьте виртуализацию для списков > 500 элементов (react-window).
// components/Roadmap.tsx
const STATUS_COLUMNS = [
{ key: 'planned', label: 'Запланировано', color: 'bg-gray-100' },
{ key: 'in_progress', label: 'В работе', color: 'bg-blue-100' },
{ key: 'done', label: 'Готово', color: 'bg-green-100' },
];
export function RoadmapBoard({ items }: { items: RoadmapItem[] }) {
const grouped = STATUS_COLUMNS.map(col => ({
...col,
items: items.filter(i => i.status === col.key),
}));
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{grouped.map(col => (
<div key={col.key}>
<h3 className={`font-semibold px-3 py-2 rounded-t ${col.color}`}>
{col.label} <span className="text-gray-500 font-normal">({col.items.length})</span>
</h3>
<div className="space-y-3 mt-3">
{col.items.map(item => (
<RoadmapCard key={item.id} item={item} />
))}
</div>
</div>
))}
</div>
);
}
function RoadmapCard({ item }: { item: RoadmapItem }) {
return (
<div className="bg-white border rounded-lg p-4 shadow-sm">
{item.category && (
<span className="text-xs bg-indigo-100 text-indigo-700 px-2 py-0.5 rounded-full">{item.category}</span>
)}
<h4 className="font-medium mt-2">{item.title}</h4>
{item.description && <p className="text-sm text-gray-500 mt-1">{item.description}</p>}
{item.quarter && <p className="text-xs text-gray-400 mt-2">{item.quarter}</p>}
</div>
);
}
Поиск и фильтр по категориям работают мгновенно благодаря состоянию React. Мы используем виртуализацию для списков более 500 элементов — это гарантирует 60 fps.
ISR-кэширование: преимущества перед SSR
ISR (Incremental Static Regeneration) генерирует статическую страницу при первом запросе, а затем обновляет её по расписанию. В Next.js это задаётся параметром revalidate. Мы ставим 3600 секунд (1 час) — страница всегда свежая, но не нагружает сервер при каждом визите:
// pages/roadmap.tsx
export const getStaticProps: GetStaticProps = async () => {
const items = await getRoadmap();
return {
props: { items },
revalidate: 3600, // Перегенерация раз в час
};
};
Это даёт TTFB < 50 мс и LCP < 1.5 с — отлично для Core Web Vitals. В отличие от SSR, где сервер генерирует страницу для каждого запроса (TTFB ~200 мс), ISR снижает нагрузку на сервер в 10 раз.
Автоматические уведомления
Отметим: когда статус меняется на done, мы автоматически оповещаем подписчиков. Используем слушатель событий Laravel: при изменении статуса проверяем, стал ли он 'done', и отправляем email всем подписанным пользователям. Для этого в модели RoadmapItem есть отношение subscribers. Письма уходят в очередь, чтобы не блокировать ответ. Типичное время доставки — менее 1 минуты.
Процесс работы над roadmap-страницей
| Этап | Длительность | Результат |
|---|---|---|
| Аналитика | 0.5 дня | Согласованные источники и статусы |
| Проектирование | 0.5 дня | Дизайн и структура компонентов |
| Реализация | 1.5 дня | Готовая страница с интеграцией |
| Тестирование | 0.5 дня | Проверка Core Web Vitals и функционала |
| Деплой | 0.5 дня | Запуск на продакшене |
Типичная ошибка на этом этапе — не учитывать мобильную фильтрацию, что увеличивает INP. Мы оптимизируем рендеринг для любых экранов, используя lazy loading для карточек за пределами видимости.
Что входит в результат
- Публичная страница с Kanban-доской и фильтрацией
- Интеграция с Notion или собственной БД (API + миграции)
- ISR-кэширование (Next.js) или аналог для других фреймворков
- Автоматические уведомления при выпуске фичи
- Документация по добавлению новых элементов
- Доступы к репозиторию и хостингу
- Обучение команды (1 час онлайн)
Сроки и стоимость
Срок разработки — от 3 до 4 рабочих дней. Стоимость рассчитывается индивидуально в зависимости от сложности интеграции и дизайна. Обычно это фиксированная сумма за проект — пишите, оценим ваш случай. Экономия бюджета на поддержку может достигать 50%. По нашим оценкам, внедрение roadmap сокращает операционные расходы на 20–30%.
Опыт нашей команды — 5+ лет в продуктовой разработке, более 50 реализованных публичных дорожных карт для SaaS и стартапов. Гарантируем прозрачную архитектуру и соответствие Core Web Vitals.
Свяжитесь, чтобы получить демо-доступ. Если вы хотите внедрить публичный roadmap на своём сайте — получите консультацию по интеграции и срокам. Закажите разработку roadmap-страницы уже сегодня и повысьте прозрачность вашего продукта.







