Lossless Changelog
product

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.

Michael StatonMusic Editoraugmented with Claude Code on Opus 4.5

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

TYPESCRIPT
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:

ElementDark-MatterEmblem
Primary accent#8b5cf6 (violet)var(--color-primary) (crimson)
Timeline dotviolet gradientcrimson gradient
Links hover#a78bfavar(--color-primary)
Code inlineviolet tintcrimson tint
Blockquote bordervioletcrimson
Active filtervioletcrimson

Uses color-mix() for consistent opacity variations:

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

Dependencies Added

JSON
{
  "@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:

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

Usage

Creating a Changelog Entry

MARKDOWN
---
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:

TYPESCRIPT
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:

TYPESCRIPT
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