Banner VC

Changelog System Implementation

Implemented a complete changelog system following the dark-matter pattern with three view modes (Timeline, Cards, Releases), syntax-highlighted code blocks, Mermaid diagram support, and full emblem theme integration.

Claude
Claude Claude

Changelog - 2026-01-19 (#2)

Changelog System Implementation

Overview

Implemented a full-featured changelog system for banner-site following the dark-matter pattern. The system supports three view modes, markdown rendering with syntax highlighting, Mermaid diagrams, and is fully integrated with the emblem theme.


Architecture

Content Collection Structure

src/
├── content.config.ts              # Central collections registry
└── content/
    └── changelog/
        └── changelog.config.ts    # Schema definition

changelog/                         # Project root (outside src/)
└── YYYY-MM-DD_NN.md              # Changelog entries

Changelog Schema

z.object({
  title: z.string(),
  date: z.coerce.date(),
  authors: z.array(z.string()).optional(),
  augmented_with: z.string().optional(),
  category: z.enum([
    'Feature', 'Component', 'Refactor', 'Fix',
    'Documentation', 'Infrastructure', 'Design-System', 'Milestone',
  ]).optional(),
  tags: z.array(z.string()).optional(),
  summary: z.string().optional(),
  files_added: z.array(z.string()).optional(),
  files_modified: z.array(z.string()).optional(),
}).passthrough();

View Modes

1. Timeline View (Default)

Linear/Stripe-inspired timeline with:

  • Grouped entries by month/year
  • Sticky month headers
  • Vertical line with animated dots
  • Category badges with theme-appropriate colors
  • Author attribution and Claude AI badge

2. Cards View

Notion/Tailwind UI-inspired card grid with:

  • Category filters (clickable pills)
  • Gradient headers per category
  • "New" badges for recent entries
  • Truncated summaries with "Read more"
  • Responsive 1/2/3 column grid

3. Releases View

GitHub releases-inspired layout with:

  • Version tags (auto-generated from date)
  • "Latest" badge for most recent
  • Collapsible release notes
  • Preview extracted from Overview section
  • Only shows entries from releases/ folder

Key Components

ContentEnhancer.astro

Wraps markdown content and enhances:

Code Blocks:

  • Adds header with language label
  • Copy-to-clipboard button
  • Syntax highlighting via Shiki (tokyo-night dark, github-light)
  • Scrollable with max-height

Mermaid Diagrams:

  • Detects ```mermaid blocks
  • Loads Mermaid from CDN on-demand
  • Custom theme variables matching emblem colors:
    • primaryColor: #B91C1C (crimson)
    • lineColor: #DC2626 (crimson-bright)
    • background: #141531 (haiti-blue)

ChangelogViewToggler.astro

  • Three toggle buttons with icons
  • Share button copies URL with ?view= param
  • LocalStorage not needed (URL-based state)
  • Smooth transitions between views

ClaudeTrademark.astro

  • Auto-switches between light/dark mode variants
  • Uses images from /public/trademarks/
  • Displays next to AI-augmented entries

Theme Integration

All colors adapted from dark-matter's violet to emblem's crimson/navy:

Element Dark-Matter Emblem
Primary accent #8b5cf6 (violet) var(--color-primary) (crimson)
Timeline dot violet gradient crimson gradient
Links hover #a78bfa var(--color-primary)
Code inline violet tint crimson tint
Blockquote border violet crimson
Active filter violet crimson

Uses color-mix() for consistent opacity variations:

background: color-mix(in srgb, var(--color-primary) 10%, transparent);
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);

Dependencies Added

{
  "@shikijs/rehype": "^3.6.0",
  "rehype-stringify": "^10.0.0",
  "remark-gfm": "^4.0.0",
  "remark-parse": "^11.0.0",
  "remark-rehype": "^11.1.0",
  "unified": "^11.0.4",
  "unist-util-visit": "^5.0.0"
}

Path Aliases

Added to tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@layouts/*": ["src/layouts/*"],
      "@styles/*": ["src/styles/*"],
      "@utils/*": ["src/utils/*"],
      "@content/*": ["src/content/*"]
    }
  }
}

Usage

Creating a Changelog Entry

---
title: "My Feature"
date: 2026-01-20
authors:
  - Your Name
category: Feature
tags:
  - Tag1
  - Tag2
summary: "Brief description for cards view"
---

# Changelog - 2026-01-20 (#1)

## My Feature

Content here with **markdown** support...

File Naming Convention

changelog/YYYY-MM-DD_NN.md
  • YYYY-MM-DD - Date of the entry
  • NN - Sequential number for same-day entries (01, 02, 03...)

Accessing the Changelog

  • /changelog - Main page with view toggle
  • /changelog?view=cards - Direct link to cards view
  • /changelog?view=releases - Direct link to releases view
  • /changelog/2026-01-19_01 - Individual entry page

Technical Notes

Static Generation

The [id].astro page uses getStaticPaths() to pre-render all changelog entries:

export async function getStaticPaths() {
  const entries = await getCollection('changelog');
  return entries.map((entry) => ({
    params: { id: entry.id },
    props: { entry },
  }));
}

Mermaid Pre-processing

Custom rehype plugin extracts mermaid blocks before Shiki processes them:

function rehypeMermaidPre() {
  return (tree: any) => {
    visit(tree, 'element', (node: any) => {
      // Convert <pre><code class="language-mermaid">
      // to <pre class="mermaid"> before Shiki runs
    });
  };
}

Sorting Logic

Entries sorted by:

  1. Date descending (newest first)
  2. Same date: ID descending (_04 before _01)

Future Enhancements

  • RSS feed generation
  • Search/filter by tag
  • Pagination for large changelogs
  • Related entries linking
  • Export to PDF