Keep a Changelog
Keep a Changelog: A Comprehensive Blueprint
Overview
This blueprint documents our standardized approach to maintaining comprehensive changelogs for both code and content changes. Our implementation leverages Astro's content collections system to create a robust, scalable changelog infrastructure that automatically processes and renders changelog entries across multiple categories.
Slides for the ADHD
The Problem We're Solving
Traditional changelog management faces several challenges:
- Fragmented Documentation: Changes scattered across commit messages, pull requests, and ad-hoc notes
- Inconsistent Formatting: No standardized structure for documenting changes
- Poor Discoverability: Changes buried in version control history
- Context Loss: Missing rationale and impact information
- Manual Overhead: Time-consuming to maintain and update
Our Solution: Multi-Category Changelog System
We've implemented a sophisticated changelog system that separates concerns into distinct categories:
- Content Changes (
changelog--content
): Documentation, specifications, and content updates - Code Changes (
changelog--code
): Technical implementations, bug fixes, and feature additions - Client-Specific Changes (
changelog--laerdal
): Client-specific customizations and updates
Render Pipeline Deep Dive
Our changelog render pipeline is implemented in
/site/src/pages/log/[slug].astro
and follows a sophisticated multi-step process:Step 1: Collection Loading and Processing
typescript
export async function getStaticPaths() {
const contentEntries = await getCollection('changelog--content');
const codeEntries = await getCollection('changelog--code');
const laerdalEntries = await getCollection('changelog--laerdal');
What happens here:
- Astro's
getCollection()
function loads all markdown files from each changelog collection - Collections are defined in
content.config.ts
using glob loaders that scan specific directories - Each collection uses
resolveContentPath()
to handle environment-specific path resolution (monorepo vs. deployed)
Step 2: Entry Processing with Slugification
typescript
const processedContentEntries = processEntries(contentEntries)
const processedCodeEntries = processEntries(codeEntries)
const processedLaerdalEntries = processEntries(laerdalEntries)
The
processEntries()
function performs critical transformations:- Slug Generation: Converts file paths to URL-friendly slugs using
getReferenceSlug()
- Title Extraction: Generates titles from filenames if not provided in frontmatter
- Data Normalization: Ensures consistent data structure across all entries
- Sorting: Alphabetically sorts entries by title for predictable ordering
Example transformation:
- File:
2025-01-17_implement-changelog-system.md
- Slug:
2025-01-17_implement-changelog-system
- Title:
2025-01-17_implement-changelog-system
(if no frontmatter title)
Step 3: Static Path Generation
typescript
const contentPaths = processedContentEntries.map(entry => {
return {
params: { slug: 'content-' + entry.slug },
props: {
entry,
contentType: 'changelog'
}
};
});
Path generation logic:
- Prefixing: Each category gets a unique prefix (
content-
,code-
,laerdal-
) - Collision Prevention: Prefixes ensure no URL conflicts between categories
- Props Passing: Entry data and content type passed to component for rendering
Generated URLs:
- Content:
/log/content-2025-01-17_implement-changelog-system
- Code:
/log/code-2025-01-17_fix-render-pipeline
- Laerdal:
/log/laerdal-2025-01-17_client-customization
Step 4: Component Rendering Pipeline
typescript
const { entry, contentType } = Astro.props;
const contentData = {
path: Astro.url.pathname,
id: entry.id,
title: entry.data?.title,
contentType,
...entry.data
};
Data preparation for rendering:
- Path Context: Current URL path for navigation and breadcrumbs
- Content Identification: Unique ID and title for the entry
- Type Classification: Content type for styling and categorization
- Frontmatter Spreading: All frontmatter data available to components
Step 5: Layout Composition
typescript
<Layout
title={entry.data.title || "Changelog Entry"}
frontmatter={entry.data}
>
<OneArticle
Component={OneArticleOnPage}
title={entry.data.title || "Changelog Entry"}
content={entry.body}
markdownFile={entry.id}
data={contentData}
/>
</Layout>
Rendering architecture:
- Layout Wrapper: Provides site-wide structure, SEO metadata, and navigation
- Article Component: Handles markdown rendering and article-specific features
- Content Processing: Markdown body processed through Astro's built-in renderer
- Metadata Integration: Frontmatter data integrated into page metadata
Content Collection Configuration
Our changelog collections are defined in
content.config.ts
: typescript
const changelogContentCollection = defineCollection({
loader: glob({pattern: "**/*.md", base: resolveContentPath("changelog--content")}),
schema: z.object({}).passthrough()
});
const changelogCodeCollection = defineCollection({
loader: glob({pattern: "**/*.md", base: resolveContentPath("changelog--code")}),
schema: z.object({}).passthrough()
});
Key configuration decisions:
- Glob Loaders: Automatically discover all markdown files in collection directories
- Passthrough Schema: Flexible schema allows any frontmatter structure
- Environment Resolution:
resolveContentPath()
handles monorepo vs. deployed environments
File Organization Strategy
text
content/
├── changelog--content/ # Content and documentation changes
│ ├── 2025-01-17_01.md # Timestamped entries
│ ├── reports/ # Automated reports
│ └── ...
├── changelog--code/ # Technical implementation changes
│ ├── 2025-01-17_01.md
│ ├── 2025-01-17_02.md # Multiple entries per day
│ └── ...
└── changelog--laerdal/ # Client-specific changes
├── 2025-01-17_01.md
└── ...
Naming conventions:
- Date Prefixes:
YYYY-MM-DD_
for chronological ordering - Sequential Numbering:
_01
,_02
for multiple entries per day - Descriptive Names: Clear, actionable titles in filenames
Frontmatter Standards
Required Fields
yaml
---
title: "Implement Multi-Category Changelog System"
date_created: 2025-01-17
date_modified: 2025-01-17
status: "Completed"
category: "Infrastructure"
---
Optional Enhancement Fields
yaml
---
authors: ["Michael Staton"]
tags: ["Astro", "Content-Collections", "Infrastructure"]
related_entries: ["2025-01-16_01", "2025-01-15_02"]
impact_level: "High"
breaking_changes: false
---
Integration Points
1. Astro Content Collections
- Type Safety: TypeScript integration for entry types
- Build-Time Processing: Static generation for optimal performance
- Hot Reloading: Development-time updates without restart
2. Slugification Utilities
- Consistent URLs: Standardized slug generation across all content
- Reference Resolution: Cross-linking between entries and content
- Path Normalization: Handles special characters and spaces
3. Layout System
- Consistent Styling: Unified appearance across all changelog entries
- SEO Optimization: Proper metadata and structured data
- Navigation Integration: Breadcrumbs and related content links
Workflow Integration
Content Creation Workflow
- Identify Change Type: Determine appropriate collection (content/code/client)
- Create Entry File: Use standardized naming convention
- Write Frontmatter: Include required and relevant optional fields
- Document Changes: Clear, actionable descriptions with context
- Link Related Items: Cross-reference related entries and content
Automated Processing
- File Discovery: Glob loaders automatically detect new entries
- Processing Pipeline:
processEntries()
normalizes and enhances data - Static Generation: Build-time rendering for optimal performance
- URL Generation: Automatic routing with category prefixes
Benefits of This Approach
For Developers
- Separation of Concerns: Clear boundaries between content and code changes
- Automated Processing: Minimal manual intervention required
- Type Safety: TypeScript integration prevents runtime errors
- Hot Reloading: Immediate feedback during development
For Content Creators
- Markdown Simplicity: Familiar writing format with powerful features
- Flexible Schema: No rigid structure requirements
- Cross-Referencing: Easy linking between related entries
- Version Control: Full history and collaboration through Git
For Users
- Discoverability: Centralized location for all changes
- Categorization: Easy filtering by change type
- Consistent Format: Predictable structure across all entries
- Rich Metadata: Context and impact information readily available
Advanced Features
Cross-Collection Linking
markdown
Related changes:
- [[changelog--code/2025-01-17_01.md|Technical Implementation]]
- [[changelog--content/2025-01-16_01.md|Documentation Update]]
Automated Reports
- Change Summaries: Automated generation of change reports
- Impact Analysis: Cross-reference analysis between entries
- Trend Tracking: Historical analysis of change patterns
Client-Specific Customization
- Dedicated Collections: Separate changelog streams per client
- Custom Routing: Client-specific URL patterns
- Filtered Views: Client-only changelog displays
Future Enhancements
Planned Improvements
- RSS Feeds: Automated feed generation for changelog subscriptions
- Search Integration: Full-text search across all changelog entries
- API Endpoints: Programmatic access to changelog data
- Notification System: Automated alerts for significant changes
Scalability Considerations
- Performance Optimization: Pagination for large changelog collections
- Caching Strategy: Intelligent caching for frequently accessed entries
- Archive Management: Automated archiving of older entries
Implementation Guidelines
Best Practices
- Atomic Entries: One logical change per changelog entry
- Clear Titles: Descriptive, actionable titles
- Context Inclusion: Why the change was made, not just what
- Impact Documentation: Who is affected and how
- Consistent Timing: Regular, predictable update schedule
Quality Standards
- Proofreading: All entries reviewed before publication
- Link Validation: Ensure all cross-references are valid
- Metadata Completeness: Required fields always populated
- Categorization Accuracy: Entries in appropriate collections
Conclusion
Our Keep-a-Changelog system represents a sophisticated approach to change documentation that balances automation with flexibility. By leveraging Astro's content collections, we've created a system that scales with our needs while maintaining consistency and discoverability.
The render pipeline's step-by-step processing ensures that every changelog entry is properly categorized, formatted, and integrated into our broader content ecosystem. This approach not only improves transparency but also creates a valuable historical record of our project's evolution.
The system's modular design allows for easy extension and customization, making it adaptable to different project needs and organizational requirements. As we continue to refine and enhance this system, it will remain a cornerstone of our transparent development and content creation practices.