
Timeline Generator
- 7 installs
- 2 repo stars
- Updated August 1, 2026
- vishalsachdev/claude-skills
Helps with ai & agent building tasks.
About
timeline-generator is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- timeline-generator
- AI & Agent Building
- AI-coding skill
Timeline Generator by the numbers
- 7 all-time installs (skills.sh)
- +1 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #12,489 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vishalsachdev/claude-skills --skill timeline-generatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7 |
|---|---|
| repo stars | ★ 2 |
| Last updated | August 1, 2026 |
| Repository | vishalsachdev/claude-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Timeline Generator
Overview
This skill generates professional, interactive timeline visualizations using vis-timeline.js. Timelines are ideal for displaying chronological events with rich context including descriptions, notes, and category groupings. The skill creates a complete MicroSim package suitable for embedding in educational content or documentation sites built with MkDocs.
When to Use This Skill
Use this skill when users request:
- Historical timelines: Family histories, organizational milestones, historical periods
- Project timelines: Development phases, product roadmaps, release schedules
- Event sequences: Course schedules, curriculum timelines, process flows
- Category-based timelines: Multi-track timelines with filtering capabilities
- Interactive visualizations: Need for hover tooltips, clickable events, zoom/pan navigation
Common trigger phrases:
- "Create a timeline showing..."
- "Visualize the history of..."
- "Build an interactive timeline for..."
- "Show chronological events for..."
Workflow
Step 1: Gather Timeline Requirements
Before generating the timeline, collect information about:
1. Timeline content:
- What is the subject/title of the timeline?
- What time period does it cover?
- What are the specific events to display?
2. Event data (for each event):
- Event headline/title (required)
- Date (year, month, day - year is required)
- Description text (required)
- Category/group (optional, for filtering)
- Historical context notes (optional, for tooltips)
3. Category filtering:
- Ask: "Would you like category filter buttons in the viewer?"
- If yes, gather category names and colors
- If not provided, create logical categories from the event data
4. Integration context:
- Standalone page
- Embedded in MkDocs documentation
- Part of educational content
IMPORTANT: If the user has not provided a specific event list, prompt them:
"I'll create an interactive timeline for you. Please provide the events you'd like to include with:
- Event title/headline
- Date (at least the year)
- Description
- Category (optional)
- Any additional context notes for tooltips (optional)
>
Would you also like category filter buttons to allow viewing specific types of events?"
Step 2: Create Directory Structure
Create a new directory for the MicroSim following this pattern:
docs/sims/<timeline-name>/
├── main.html # Main visualization file
├── timeline.json # Event data in TimelineJS format
└── index.md # Documentation (if part of MkDocs)Naming convention: Use kebab-case (lowercase with hyphens) for directory names that are descriptive and URL-friendly (e.g., project-history-timeline, course-schedule, family-heritage-timeline).
Step 3: Create timeline.json Data File
Generate a JSON file following this structure:
{
"title": "Timeline Title",
"events": [
{
"start_date": {
"year": "2024",
"month": "1",
"day": "15",
"display_date": "January 15, 2024"
},
"text": {
"headline": "Event Title",
"text": "Detailed description of the event."
},
"group": "Category Name",
"notes": "Additional context that appears in the tooltip."
}
]
}Key data structure notes:
yearis required instart_datemonthanddayare optional (default to 1 if omitted)display_dateis optional (for custom date formatting)groupis the category used for filteringnotesprovides tooltip/hover text with additional context- All text fields support basic HTML formatting
Data preparation guidelines: 1. Sort events chronologically (oldest to newest) 2. Use consistent category names across related events 3. Keep headlines concise (5-10 words) 4. Provide substantive descriptions (2-4 sentences) 5. Add historical context in notes for educational value
Step 4: Create main.html with vis-timeline
Generate the main HTML file with the following structure:
1. HTML boilerplate with proper meta tags 2. vis-timeline CDN imports:
- JS:
https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.js - CSS:
https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.css
3. Styled header with timeline title and subtitle 4. Category filter controls (if requested) 5. Timeline container div 6. Info panel with legend and event details 7. JavaScript implementation:
- Load timeline.json data
- Convert to vis-timeline format
- Create color scheme for categories
- Initialize timeline with options
- Implement category filtering
- Handle event selection for detail display
Key vis-timeline configuration elements:
// Color scheme for categories
const categoryColors = {
'Category 1': '#color1',
'Category 2': '#color2',
// ... more categories
};
// Convert JSON events to vis-timeline format
allItems = data.events.map((event, index) => {
const year = event.start_date.year;
const month = event.start_date.month || 1;
const day = event.start_date.day || 1;
const startDate = new Date(parseInt(year), month - 1, day);
return {
id: `event-${index}`,
content: event.text.headline,
start: startDate,
title: event.notes || event.text.headline,
className: event.group.replace(/\s+/g, '-').toLowerCase(),
style: `background-color: ${categoryColors[event.group]}; color: white;`,
category: event.group,
eventData: event
};
});
// Timeline options
const options = {
width: '100%',
height: '600px',
margin: { item: 20, axis: 40 },
orientation: 'top',
zoomMin: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
zoomMax: 1000 * 60 * 60 * 24 * 365 * 1200, // 1200 years
tooltip: {
followMouse: true,
template: function(item) {
return item.notes || '';
}
},
stack: true,
selectable: true
};Important implementation features:
1. Category filtering: Filter button implementation
function filterCategory(category) {
if (category === 'all') {
timelineData.clear();
timelineData.add(allItems);
} else {
const filtered = allItems.filter(item => item.category === category);
timelineData.clear();
timelineData.add(filtered);
}
timeline.fit();
}2. Event detail display: Show full event information on click
timeline.on('select', function(properties) {
if (properties.items.length > 0) {
showEventDetails(properties.items[0]);
}
});3. Color-coded events: Apply category colors to timeline items 4. Responsive tooltips: Show context notes on hover 5. Legend display: Visual guide for category colors
Design considerations:
- Use a professional color scheme (distinct, accessible colors)
- Provide clear visual hierarchy
- Ensure text readability against colored backgrounds
- Include hover effects for interactivity
- Make the layout responsive for different screen sizes
Step 5: Create index.md Documentation
If the timeline is part of a MkDocs site, create comprehensive documentation:
# [Timeline Title]
[Brief description of what this timeline visualizes]
[Run the [Timeline Name]](./main.html)
[View the Raw Timeline Data](timeline.json)
## Overview
[Detailed explanation of the timeline's purpose, content, and coverage]
## Features
### Interactive Elements
- **Zoom and Pan**: Click and drag to pan, scroll to zoom in/out
- **Event Details**: Click any event to see full details below the timeline
- **Hover Tooltips**: Hover over events to see historical context notes
- **Category Filtering**: Use filter buttons to view specific event categories
### Visual Design
- **Color-coded categories**: Each event category has a distinct color
- **Responsive layout**: Works on desktop, tablet, and mobile devices
- **Legend**: Visual guide showing category colors and meanings
## Data Structure
The timeline data is stored in `timeline.json` following this format:
[Include JSON structure example]
## Customization Guide
### Adding New Events
1. Open `timeline.json`
2. Add a new event object to the `events` array
3. Reload the page to see your changes
### Changing Colors
To modify category colors, edit the `categoryColors` object in `main.html`:
[Code example]
### Adjusting Time Range
To change the zoom limits, modify the `zoomMin` and `zoomMax` options:
[Code example]
## Technical Details
- **Timeline Library**: vis-timeline 7.7.3
- **Data Format**: TimelineJS-compatible JSON
- **Browser Compatibility**: Modern browsers (Chrome, Firefox, Safari, Edge)
- **Dependencies**: vis-timeline.js (loaded from CDN)
## Use Cases
This timeline pattern can be adapted for:
- Historical education
- Project planning and tracking
- Course schedules and curricula
- Organizational history
- Personal timelines and biographiesDocumentation best practices: 1. Provide clear usage instructions 2. Include code examples for common customizations 3. Explain the data format thoroughly 4. Link to external resources (vis-timeline docs) 5. Suggest related use cases
Step 6: Integrate into Navigation (MkDocs)
If using MkDocs, add the timeline to the navigation in mkdocs.yml:
nav:
- MicroSims:
- Introduction: sims/index.md
- [Timeline Name]: sims/[timeline-name]/index.md
- [Other sims...]: ...Place the entry in a logical position based on:
- Related content (group similar visualizations)
- Alphabetical order
- Chronological order of creation
Step 7: Test and Validate
Before considering the timeline complete:
1. Data validation:
- Verify timeline.json is valid JSON
- Check all dates parse correctly
- Confirm all events have required fields
- Validate category names are consistent
2. Visual testing:
- Open
main.htmldirectly in browser - Test with
mkdocs serveif applicable - Check timeline spans entire date range
- Verify all events are visible and properly spaced
- Test on different screen sizes
3. Interactive testing:
- Zoom in/out to verify scale limits
- Pan across the full timeline
- Hover over events to check tooltips
- Click events to verify detail display
- Test category filter buttons (if present)
- Check "All Events" filter restores full view
4. Content review:
- Proofread all event text
- Verify historical accuracy
- Check that context notes provide value
- Ensure descriptions are complete
5. Browser compatibility:
- Test on Chrome, Firefox, Safari, Edge
- Verify CDN resources load correctly
- Check console for JavaScript errors
Best Practices
Data Preparation
1. Date accuracy: Use precise dates when available 2. Chronological order: Sort events in JSON for easier maintenance 3. Consistent categories: Use standardized category names 4. Rich context: Provide substantive descriptions and notes 5. Source validation: Verify historical facts and dates
Category Design
1. Limit categories: 3-6 categories works best for filtering 2. Meaningful groupings: Categories should reflect natural divisions 3. Balanced distribution: Aim for relatively even event distribution 4. Clear naming: Use descriptive, non-overlapping category names 5. Color accessibility: Choose colors with sufficient contrast
Visual Design
1. Color coding: Use distinct, visually appealing colors 2. Text readability: Ensure white text on colored backgrounds is clear 3. Legend placement: Make the legend visible and understandable 4. Responsive sizing: Timeline should work on all screen sizes 5. Loading states: Consider showing a loading indicator
Documentation
1. Usage examples: Show how to interact with the timeline 2. Data format: Clearly document the JSON structure 3. Customization: Provide code snippets for common changes 4. Attribution: Credit data sources when appropriate 5. Educational context: Explain why the timeline matters
MkDocs Integration
1. Direct linking: Provide links to both main.html and timeline.json 2. Iframe embedding: Can use iframe for inline display if desired 3. Navigation placement: Group with related content 4. Cross-references: Link to related pages or timelines
Common Variations
Simple Timeline (No Categories)
Omit the category filtering UI and use a single color:
const categoryColors = {
'Default': '#2d5016'
};Vertical Timeline
Change orientation for a vertical layout:
options: {
orientation: 'left' // or 'right'
}Range Events
For events with duration, add an end_date:
{
"start_date": {"year": "2020", "month": "1"},
"end_date": {"year": "2021", "month": "12"},
"text": {"headline": "Multi-year Project"}
}Embedded Media
Add images or videos to events (requires additional configuration).
Troubleshooting
Timeline Not Displaying
Solution: Check browser console for errors, verify timeline.json loads correctly, ensure CDN resources are accessible.
Events Overlapping
Solution: Increase margin.item value in options or enable stack: true for automatic vertical stacking.
Zoom Too Fast/Slow
Solution: Adjust zoomMin and zoomMax values based on your date range.
Filter Buttons Not Working
Solution: Verify category names match exactly between JSON data and filter buttons, check JavaScript console for errors.
Dates Parsing Incorrectly
Solution: Ensure month values are 1-12, not 0-11. The conversion to JavaScript Date handles this in the code.
References
This skill uses the following assets and references:
Assets
- vis-timeline CDN:
- JS:
https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.js - CSS:
https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.css - No local assets required (vis-timeline loaded from CDN)
References
- vis-timeline Documentation
- TimelineJS3 Data Format (compatible structure)
- vis-timeline GitHub Repository
Example Implementation
See the timeline example at /docs/sims/timeline/ for a complete reference implementation showcasing McCreary family heritage timeline.
License
This skill is provided under the same license as the claude-skills repository. The vis-timeline library is licensed under Apache-2.0/MIT dual license.
Timeline Generator Resources
This directory contains generic template files for creating interactive timeline visualizations using vis-timeline.js.
Template Files
template-timeline.json
Generic event data file demonstrating the JSON structure for timeline events. This sample includes:
- 6 sample events spanning 2020-2021
- 4 categories (Planning, Development, Launch, Maintenance)
- Complete data structure with all optional fields
Placeholders: None (this is a complete working example)
template-main.html
Generic HTML template for the timeline viewer. Contains placeholders that should be replaced:
{{TIMELINE_TITLE}}- The main title of the timeline (e.g., "Project History Timeline"){{TIMELINE_SUBTITLE}}- Subtitle or tagline (e.g., "Major milestones from 2020-2021"){{FILTER_CONTROLS}}- Either an empty string or the filter controls HTML block{{TIMELINE_DESCRIPTION}}- Brief description of the timeline's purpose{{LEGEND}}- Either an empty string or the legend HTML block{{CATEGORY_COLORS}}- JavaScript object defining category colors
Filter Controls Block
If the user wants category filtering, use this structure:
<div class="controls">
<div class="filter-group">
<label>Filter:</label>
<button class="filter-btn active" onclick="filterCategory('all')">All Events</button>
<button class="filter-btn" onclick="filterCategory('Category1')">Category1</button>
<button class="filter-btn" onclick="filterCategory('Category2')">Category2</button>
<!-- Add more buttons as needed -->
</div>
</div>If no filtering is wanted, replace {{FILTER_CONTROLS}} with an empty string.
Legend Block
If the user wants category filtering, include a legend:
<div class="legend">
<div class="legend-item">
<div class="legend-color" style="background-color: #8b0000;"></div>
<span>Category1</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background-color: #1e3a8a;"></div>
<span>Category2</span>
</div>
<!-- Add more legend items as needed -->
</div>If no filtering, this can be omitted or replaced with an empty string.
Category Colors Object
Example JavaScript object:
{
'Planning': '#8b0000',
'Development': '#1e3a8a',
'Launch': '#1e5631',
'Maintenance': '#7c2d12'
}Recommended color palette for up to 6 categories:
#8b0000(dark red)#1e3a8a(dark blue)#1e5631(dark green)#7c2d12(dark brown)#6b21a8(purple)#b45309(orange)
template-index.md
Generic documentation template for MkDocs integration. Contains placeholders:
{{TIMELINE_TITLE}}- The main title{{TIMELINE_OVERVIEW_TEXT}}- One-sentence overview{{DETAILED_DESCRIPTION}}- 2-3 paragraph detailed description{{CATEGORY_FILTERING_FEATURE}}- Either the filtering feature description or empty string
If category filtering is enabled, use:
- **Category Filtering**: Use filter buttons to view specific event categoriesUsage Instructions
When generating a timeline:
1. Gather requirements from the user (see SKILL.md Step 1) 2. Create directory structure: docs/sims/<timeline-name>/ 3. Generate timeline.json with user's event data 4. Generate main.html by replacing placeholders in template-main.html 5. Generate index.md by replacing placeholders in template-index.md 6. Test the timeline by opening main.html in a browser
Example Workflow
User wants: "Create a timeline of company milestones from 2015-2023"
1. Ask for events, categories, whether they want filtering
2. Create: docs/sims/company-milestones-timeline/
3. Generate timeline.json with their events
4. Replace placeholders:
- {{TIMELINE_TITLE}} → "Company Milestones Timeline"
- {{TIMELINE_SUBTITLE}} → "Major achievements from 2015-2023"
- {{CATEGORY_COLORS}} → Object with their categories
- etc.
5. Save as main.html and index.md
6. Test and validateColor Selection Guidelines
Choose colors that:
- Have sufficient contrast (dark colors work best with white text)
- Are visually distinct from each other
- Follow a logical scheme (e.g., chronological progression, thematic grouping)
- Are accessible (avoid red-green combinations for colorblind users)
Common Customizations
No Category Filtering
- Set
{{FILTER_CONTROLS}}to empty string - Set
{{LEGEND}}to empty string - Use single color in
{{CATEGORY_COLORS}} - In template-index.md, remove filtering feature text
Few Events (< 10)
- Adjust timeline height to 400px instead of 600px
- Reduce zoomMin to show shorter time spans
Many Events (> 50)
- Increase timeline height to 800px
- Consider grouping related events
- Use clearer category distinctions
Long Time Spans (> 100 years)
- Increase zoomMax value appropriately
- Consider showing only decades on initial load
Reference Implementation
See /docs/sims/timeline/ for a complete working example (McCreary Family Heritage Timeline) that demonstrates:
- 60+ events spanning 1500+ years
- 4 distinct categories with filtering
- Rich historical context in notes
- Full documentation integration
{{TIMELINE_TITLE}}
{{TIMELINE_OVERVIEW_TEXT}}
Run the {{TIMELINE_TITLE}}
View the Raw Timeline Data
Overview
{{DETAILED_DESCRIPTION}}
Features
Interactive Elements
- Zoom and Pan: Click and drag to pan, scroll to zoom in/out
- Event Details: Click any event to see full details below the timeline
- Hover Tooltips: Hover over events to see historical context notes
{{CATEGORY_FILTERING_FEATURE}}
Visual Design
- Color-coded categories: Each event category has a distinct color
- Responsive layout: Works on desktop, tablet, and mobile devices
- Legend: Visual guide showing category colors and meanings
Data Structure
The timeline data is stored in timeline.json following this format:
{
"title": "Timeline Title",
"events": [
{
"start_date": {
"year": "2024",
"month": "1",
"day": "15",
"display_date": "January 15, 2024"
},
"text": {
"headline": "Event Title",
"text": "Detailed description of the event."
},
"group": "Category Name",
"notes": "Additional context that appears in the tooltip."
}
]
}Customization Guide
Adding New Events
1. Open timeline.json 2. Add a new event object to the events array following the structure above 3. Ensure the year field is present in start_date 4. Assign the event to a category using the group field 5. Save and reload the page to see your changes
Changing Colors
To modify category colors, edit the categoryColors object in main.html:
const categoryColors = {
'Category1': '#8b0000',
'Category2': '#1e3a8a',
'Category3': '#1e5631',
// Add more categories as needed
};Adjusting Time Range
To change the zoom limits, modify the zoomMin and zoomMax options in main.html:
zoomMin: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years minimum zoom
zoomMax: 1000 * 60 * 60 * 24 * 365 * 1200, // 1200 years maximum zoomModifying Filter Buttons
To add or modify category filter buttons, update the controls section in main.html:
<div class="filter-group">
<label>Filter:</label>
<button class="filter-btn active" onclick="filterCategory('all')">All Events</button>
<button class="filter-btn" onclick="filterCategory('YourCategory')">Your Category</button>
</div>Technical Details
- Timeline Library: vis-timeline 7.7.3
- Data Format: TimelineJS-compatible JSON
- Browser Compatibility: Modern browsers (Chrome, Firefox, Safari, Edge)
- Dependencies:
- vis-timeline.js (loaded from CDN)
- vis-timeline.css (loaded from CDN)
Use Cases
This timeline pattern can be adapted for:
- Historical education and chronological learning
- Project planning and tracking
- Course schedules and curricula
- Organizational history and milestones
- Personal timelines and biographies
- Event sequences and process flows
References
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TIMELINE_TITLE}}</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis-timeline/7.7.3/vis-timeline-graph2d.min.css" rel="stylesheet" />
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
min-height: 100vh;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #2d5016 0%, #4a7c2f 100%);
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
margin: 0 0 10px 0;
font-size: 2.5em;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.header p {
margin: 0;
font-size: 1.1em;
opacity: 0.95;
}
.controls {
padding: 20px 30px;
background: #f8f9fa;
border-bottom: 2px solid #e9ecef;
display: flex;
gap: 15px;
flex-wrap: wrap;
align-items: center;
}
.filter-group {
display: flex;
gap: 10px;
align-items: center;
}
.filter-group label {
font-weight: 600;
color: #495057;
}
.filter-btn {
padding: 8px 16px;
border: 2px solid #dee2e6;
background: white;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
font-weight: 500;
}
.filter-btn:hover {
background: #e9ecef;
}
.filter-btn.active {
background: #2d5016;
color: white;
border-color: #2d5016;
}
#timeline {
height: 600px;
border: none;
}
.info-panel {
padding: 20px 30px;
background: #f8f9fa;
border-top: 2px solid #e9ecef;
}
.info-panel h3 {
margin: 0 0 10px 0;
color: #2d5016;
}
.info-panel p {
margin: 5px 0;
line-height: 1.6;
color: #495057;
}
.legend {
display: flex;
gap: 20px;
flex-wrap: wrap;
margin-top: 15px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
}
.legend-color {
width: 20px;
height: 20px;
border-radius: 4px;
border: 2px solid #dee2e6;
}
.vis-item {
border-width: 2px;
border-radius: 6px;
font-weight: 500;
}
.vis-item.vis-selected {
border-width: 3px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
/* Custom tooltip styling */
.vis-tooltip {
background: white !important;
border: 2px solid #2d5016 !important;
border-radius: 8px !important;
padding: 12px 16px !important;
box-shadow: 0 4px 12px rgba(0,0,0,0.2) !important;
max-width: 400px !important;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
color: #495057 !important;
line-height: 1.5 !important;
white-space: normal !important;
word-wrap: break-word !important;
font-size: 0.95em !important;
}
.event-details {
margin-top: 20px;
padding: 20px;
background: white;
border-radius: 8px;
border: 2px solid #e9ecef;
display: none;
}
.event-details.active {
display: block;
}
.event-details h4 {
margin: 0 0 10px 0;
color: #2d5016;
font-size: 1.3em;
}
.event-details .event-meta {
color: #6c757d;
font-size: 0.9em;
margin-bottom: 15px;
}
.event-details .event-description {
line-height: 1.6;
margin-bottom: 15px;
}
.event-details .event-notes {
background: #f8f9fa;
padding: 15px;
border-left: 4px solid #2d5016;
margin-top: 15px;
font-style: italic;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>{{TIMELINE_TITLE}}</h1>
<p>{{TIMELINE_SUBTITLE}}</p>
</div>
{{FILTER_CONTROLS}}
<div id="timeline"></div>
<div class="info-panel">
<h3>About This Timeline</h3>
<p>{{TIMELINE_DESCRIPTION}}</p>
<p><strong>Instructions:</strong> Hover over events to see historical context notes. Click and drag to pan, scroll to zoom, click on events for full details.</p>
{{LEGEND}}
<div id="eventDetails" class="event-details"></div>
</div>
</div>
<script>
let timeline;
let allItems;
let timelineData;
let eventsMap = new Map();
// Color scheme for categories
const categoryColors = {{CATEGORY_COLORS}};
// Load and process the JSON data
async function loadData() {
try {
const response = await fetch('timeline.json');
const data = await response.json();
// Convert events to vis-timeline format
allItems = data.events.map((event, index) => {
// Parse date from start_date object
const year = event.start_date.year;
const month = event.start_date.month || 1;
const day = event.start_date.day || 1;
const startDate = new Date(parseInt(year), month - 1, day);
const group = event.group || 'Other';
const id = `event-${index}`;
// Store full event data for detail display
eventsMap.set(id, event);
return {
id: id,
content: event.text.headline,
start: startDate,
title: event.notes || event.text.headline, // Use notes for tooltip
className: group.replace(/\s+/g, '-').toLowerCase(),
style: `background-color: ${categoryColors[group]}; color: white; border-color: ${categoryColors[group]};`,
category: group,
eventData: event,
notes: event.notes || ''
};
});
createTimeline();
} catch (error) {
console.error('Error loading timeline data:', error);
document.getElementById('timeline').innerHTML =
'<div style="padding: 40px; text-align: center; color: #dc3545;">Error loading timeline data. Please ensure timeline.json is in the same directory.</div>';
}
}
function createTimeline() {
const container = document.getElementById('timeline');
timelineData = new vis.DataSet(allItems);
const options = {
width: '100%',
height: '600px',
margin: {
item: 20,
axis: 40
},
orientation: 'top',
zoomMin: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
zoomMax: 1000 * 60 * 60 * 24 * 365 * 1200, // 1200 years
tooltip: {
followMouse: true,
overflowMethod: 'cap',
delay: 300,
template: function(item) {
// Get the item data
const itemData = timelineData.get(item.id);
if (!itemData) return item.content;
const notes = itemData.notes || '';
// Only show notes, not the headline (which is already visible on the timeline item)
if (notes) {
return notes;
} else {
return ''; // Return empty if no notes
}
}
},
stack: true,
maxHeight: 600,
selectable: true,
multiselect: false
};
timeline = new vis.Timeline(container, timelineData, options);
// Add click event listener
timeline.on('select', function(properties) {
if (properties.items.length > 0) {
const itemId = properties.items[0];
showEventDetails(itemId);
} else {
hideEventDetails();
}
});
// Fit the timeline to show all items
timeline.fit();
}
function showEventDetails(itemId) {
const event = eventsMap.get(itemId);
if (!event) return;
const detailsDiv = document.getElementById('eventDetails');
const year = event.start_date.year;
let html = `
<h4>${event.text.headline}</h4>
<div class="event-meta">
<strong>Year:</strong> ${year} |
<strong>Category:</strong> ${event.group}
</div>
<div class="event-description">
${event.text.text}
</div>
`;
if (event.notes) {
html += `
<div class="event-notes">
<strong>Historical Context:</strong><br>
${event.notes}
</div>
`;
}
detailsDiv.innerHTML = html;
detailsDiv.classList.add('active');
}
function hideEventDetails() {
const detailsDiv = document.getElementById('eventDetails');
detailsDiv.classList.remove('active');
}
function filterCategory(category) {
// Update button states
document.querySelectorAll('.filter-btn').forEach(btn => {
btn.classList.remove('active');
});
event.target.classList.add('active');
// Filter items
if (category === 'all') {
timelineData.clear();
timelineData.add(allItems);
} else {
const filtered = allItems.filter(item => item.category === category);
timelineData.clear();
timelineData.add(filtered);
}
hideEventDetails();
timeline.fit();
}
// Initialize the timeline when page loads
window.addEventListener('load', loadData);
</script>
</body>
</html>
{
"title": "Sample Timeline",
"events": [
{
"start_date": {
"year": "2020",
"month": "1",
"day": "15"
},
"text": {
"headline": "Project Initiated",
"text": "The project was formally initiated with stakeholder approval and budget allocation."
},
"group": "Planning",
"notes": "This milestone marked the official start of the project after months of preparation and proposal development."
},
{
"start_date": {
"year": "2020",
"month": "3",
"day": "1"
},
"text": {
"headline": "Team Assembled",
"text": "Core team members were recruited and onboarded to begin the development phase."
},
"group": "Planning",
"notes": "The team included developers, designers, and project managers from multiple departments."
},
{
"start_date": {
"year": "2020",
"month": "5",
"day": "10"
},
"text": {
"headline": "First Prototype Released",
"text": "Initial prototype completed and released for internal testing and feedback."
},
"group": "Development",
"notes": "The prototype demonstrated core functionality and validated key technical approaches."
},
{
"start_date": {
"year": "2020",
"month": "8",
"day": "20"
},
"text": {
"headline": "Beta Testing Begins",
"text": "Beta version released to select external users for comprehensive testing."
},
"group": "Development",
"notes": "Over 100 beta testers participated, providing valuable feedback that shaped the final release."
},
{
"start_date": {
"year": "2020",
"month": "11",
"day": "1"
},
"text": {
"headline": "Official Launch",
"text": "Product officially launched to the public with full feature set and documentation."
},
"group": "Launch",
"notes": "The launch included a marketing campaign, press releases, and user onboarding materials."
},
{
"start_date": {
"year": "2021",
"month": "2",
"day": "15"
},
"text": {
"headline": "First Major Update",
"text": "First significant update released with new features and improvements based on user feedback."
},
"group": "Maintenance",
"notes": "This update addressed the top 20 feature requests from the community and fixed reported issues."
}
]
}