Разработка страницы changelog с историей обновлений
Changelog — хронологический список изменений продукта: новые функции, улучшения, исправления. Правильно оформленный changelog удерживает пользователей и снижает отток — люди видят, что продукт развивается.
Структура записи
Каждая запись содержит: дату, версию (если ПО), тип изменения, заголовок, описание, иногда скриншот или GIF.
Типы изменений: New (новая функция), Improved (улучшение), Fixed (баг-фикс), Deprecated (устаревшее).
Markdown-файлы как источник данных
Простой подход — хранить changelog в Markdown-файлах в репозитории:
content/changelog/
├── 2025-03-15.md
├── 2025-02-28.md
└── 2025-01-10.md
---
date: 2025-03-15
version: "2.4.0"
---
## New: Интеграция с Telegram
Теперь вы можете получать уведомления о новых заказах прямо в Telegram. ...
## Improved: Скорость загрузки каталога
Оптимизировали запросы к базе данных — страница каталога загружается на 40% быстрее.
## Fixed: Ошибка при оплате через Apple Pay в Safari
// lib/changelog.ts
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
export function getChangelogEntries() {
const dir = path.join(process.cwd(), 'content/changelog');
return fs.readdirSync(dir)
.filter(f => f.endsWith('.md'))
.sort().reverse()
.map(filename => {
const raw = fs.readFileSync(path.join(dir, filename), 'utf-8');
const { data, content } = matter(raw);
return { ...data, content, slug: filename.replace('.md', '') };
});
}
Страница changelog
// app/changelog/page.tsx (Next.js App Router)
export default async function ChangelogPage() {
const entries = getChangelogEntries();
return (
<div className="max-w-2xl mx-auto py-12">
<h1 className="text-3xl font-bold mb-10">Что нового</h1>
<div className="space-y-12">
{entries.map(entry => (
<article key={entry.slug}>
<div className="flex items-center gap-3 mb-4">
<time className="text-sm text-gray-500">
{new Date(entry.date).toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' })}
</time>
{entry.version && (
<span className="text-xs bg-gray-100 px-2 py-0.5 rounded font-mono">v{entry.version}</span>
)}
</div>
<div className="prose prose-sm" dangerouslySetInnerHTML={{ __html: renderMarkdown(entry.content) }} />
</article>
))}
</div>
</div>
);
}
RSS-лента для changelog
// ChangelogFeedController
public function rss(): Response
{
$entries = ChangelogEntry::latest('published_at')->take(20)->get();
$xml = view('feeds.changelog-rss', compact('entries'))->render();
return response($xml)->header('Content-Type', 'application/rss+xml');
}
Email-рассылка при публикации
// При публикации записи — отправка подписчикам
public function handle(ChangelogEntryPublished $event): void
{
$subscribers = ChangelogSubscriber::all();
foreach ($subscribers->chunk(100) as $chunk) {
Mail::to($chunk->pluck('email'))->queue(new ChangelogDigestMail($event->entry));
}
}
Сроки
Страница changelog с Markdown-источником, RSS-лентой и подпиской по email: 2 рабочих дня.







