lvwerra/science-timeline
Science Timeline
The org card can't display JS HTML embedded in the markdown. So the workaround is to render it in a model card (here) and export the rendered HTML. Steps:
- Edit the
const releasessection in embedded HTML here with the new release data - Export the static HTML with the buttons below
- If you are nice, prettify the resulting HTML
- Copy-paste the result into the Org README
- Tada!
<style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; } .timeline-container { max-width: 1000px; margin: 20px auto; padding: 20px; background: white; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .timeline-row { display: flex; margin-bottom: 20px; min-height: 120px; position: relative; } .timeline-row.reverse { flex-direction: row-reverse; } .month-box { flex: 1; padding: 10px; text-align: center; position: relative; } .month-arrow { width: 0; height: 0; border-top: 8px solid transparent; border-bottom: 8px solid transparent; border-left: 12px solid #666; margin: 0 auto 8px; } .reverse .month-arrow { border-left: none; border-right: 12px solid #666; } .month-title { font-weight: 600; font-size: 12px; color: #666; text-transform: uppercase; margin-bottom: 8px; } .event-list { font-size: 11px; color: #333; } .event-item { margin: 3px 0; padding: 2px 4px; background: #f8f9fa; border-radius: 3px; } .timeline-row::before { content: ''; position: absolute; top: 12px; left: 0; right: 0; height: 1px; background: #ddd; z-index: 1; } .month-box { z-index: 2; background: white; } </style>
<!-- ADD THESE BUTTONS WHEREVER YOU WANT THEM --> <div style="margin: 20px 0;"> <button onclick="exportStaticHTML()" style="background: #007bff; color: white; border: none; padding: 10px 20px; border-radius: 6px; cursor: pointer; margin-right: 10px;">📋 Export Static HTML</button> <button onclick="copyToClipboard()" style="background: #28a745; color: white; border: none; padding: 10px 20px; border-radius: 6px; cursor: pointer;">📋 Copy to Clipboard</button> </div>
<div id="static-output" style="display: none;"></div>
<div id="snake-timeline-container" style="max-width: 1000px; margin: 20px auto; padding: 20px; background: white; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"> Loading timeline... </div>
<script> // Release data with links const releases = [ { month: "2024-01", name: "🔥 Warming up", link: null }, { month: "2024-02", name: "⚙️ Nanotron Release", link: "https://github.com/huggingface/nanotron/" }, { month: "2024-02", name: "⛅ Lighteval Release", link: "https://github.com/huggingface/lighteval/" }, { month: "2024-02", name: "⚙️ Datatrove Release", link: "https://github.com/huggingface/datatrove/" }, { month: "2024-02", name: "⭐️ The Stack v2", link: "https://huggingface.co/datasets/bigcode/the-stack-v2" }, { month: "2024-02", name: "⭐️ StarCoder2", link: "https://huggingface.co/bigcode/starcoder2-15b" }, { month: "2024-03", name: "🪁 Zephyr Gemma", link: "https://huggingface.co/HuggingFaceH4/zephyr-7b-gemma-v0.1" }, { month: "2024-03", name: "🪐 Cosmopedia", link: "https://huggingface.co/datasets/HuggingFaceTB/cosmopedia" }, { month: "2024-04", name: "🍷 FineWeb", link: "https://huggingface.co/datasets/HuggingFaceFW/fineweb" }, { month: "2024-04", name: "🕵️ JAT Agent", link: "https://huggingface.co/blog/jat" }, { month: "2024-04", name: "🪁 Zephyr Mixtral", link: "HuggingFaceH4/zephyr-orpo-141b-A35b-v0.1" }, { month: "2024-04", name: "🐶 Idefics 2", link: "https://huggingface.co/HuggingFaceM4/idefics2-8bb" }, { month: "2024-04", name: "🏆 Community Leaderboards", link: "https://huggingface.co/blog/leaderboard-medicalllm" }, { month: "2024-05", name: "🦾 LeRobot Release", link: "https://github.com/huggingface/lerobot" }, { month: "2024-05", name: "📈 WSD Analysis", link: "https://arxiv.org/abs/2405.18392" }, { month: "2024-06", name: "🍷 FineWeb Report", link: "https://huggingface.co/spaces/HuggingFaceFW/blogpost-fineweb-v1f" }, { month: "2024-06", name: "🍷 FineWeb-Edu", link: "https://huggingface.co/datasets/HuggingFaceFW/fineweb-edu" }, { month: "2024-06", name: "🌺 Florence 2 Blog", link: "https://huggingface.co/blog/finetune-florence2" }, { month: "2024-06", name: "🏆 Open LLM Leaderboard v2", link: "https://huggingface.co/spaces/open-llm-leaderboard/blog" }, { month: "2024-06", name: "👩🏫 Stanford CS25", link: "https://www.youtube.com/watch?v=jm2hyJLFfN8" }, { month: "2024-07", name: "🛟 Ring attention", link: "https://x.com/HaojunZhao14/status/1815419356408336738" }, { month: "2024-07", name: "🦾 LeRobot TeleOps", link: "https://x.com/RemiCadene/status/1805583409382932620" }, { month: "2024-07", name: "🥇 Win AIMO", link: "https://x.com/lewtun/status/1808898804822720769" }, { month: "2024-07", name: "🐶 Docmatix", link: "https://huggingface.co/blog/docmatix" }, { month: "2024-07", name: "🤏 SmolLM", link: "https://huggingface.co/blog/smollm" }, { month: "2024-08", name: "🦾 LeRobot Tutorial", link: "https://github.com/huggingface/lerobot/blob/main/examples/7getstartedwithrealrobot.md" }, { month: "2024-08", name: "📣 Speech-to-Speech", link: "https://github.com/huggingface/speech-to-speech" }, { month: "2024-08", name: "🐶 Idefics 3", link: "https://huggingface.co/HuggingFaceM4/Idefics3-8B-Llama3" }, { month: "2024-08", name: "🤏 Instant SmolLM", link: "https://huggingface.co/spaces/HuggingFaceTB/instant-smollm" }, { month: "2024-09", name: "🦾 LeRobot Video", link: "https://x.com/aliberts/status/1828760527730082024" }, { month: "2024-09", name: "🎥 FineVideo", link: "https://huggingface.co/spaces/HuggingFaceFV/FineVideo-Explorer" }, { month: "2024-09", name: "📣 Speech-to-Speech Multilingual", link: "https://x.com/andimarafioti/status/1830862304906268725" }, { month: "2024-10", name: "🔎 LLM Evaluation Guidebook", link: "https://github.com/huggingface/evaluation-guidebook" }, { month: "2024-10", name: "🦾 LeRobot Hackathon", link: "https://x.com/ThomWolf/status/1851557379294286176" }, { month: "2024-10", name: "🗺️ FineTasks", link: "https://huggingface.co/spaces/HuggingFaceFW/blogpost-fine-tasks" }, { month: "2024-10", name: "⛅ Lighteval now Multilingual", link: "https://x.com/nathanhabib1011/status/1849160216438587466" }, { month: "2024-11", name: "🤏 SmolLM2", link: "https://huggingface.co/HuggingFaceTB/SmolLM2-1.7B-Instruct" }, { month: "2024-11", name: "🤓 SmolVLM", link: "https://huggingface.co/HuggingFaceTB/SmolVLM-Instruct" }, { month: "2024-12", name: "🔢 Number Tokenization Blog", link: "https://huggingface.co/spaces/huggingface/number-tokenization-blog" }, { month: "2024-12", name: "🥂 FineWeb 2", link: "https://huggingface.co/datasets/HuggingFaceFW/fineweb-2" }, { month: "2024-12", name: "📈 Scaling Test Time Compute", link: "https://huggingface.co/spaces/HuggingFaceH4/blogpost-scaling-test-time-compute" }, { month: "2024-12", name: "🤖 Picotron", link: "https://github.com/huggingface/picotron" }, { month: "2024-12", name: "📐 FineMath", link: "https://huggingface.co/datasets/HuggingFaceTB/finemath" }, // 2025 { month: "2025-01", name: "🧮 Math Verify", link: "https://x.com/HKydlicek/status/1881734376696041659" }, { month: "2025-01", name: "🐳 Open-R1", link: "https://github.com/huggingface/open-r1" }, { month: "2025-01", name: "🛠️ SmolAgents", link: "https://huggingface.co/docs/smolagents" }, { month: "2025-02", name: "🎥 SmolVLM2", link: "https://huggingface.co/blog/smolvlm2" }, { month: "2025-02", name: "🪐 Ultra-Scale Playbook", link: "https://huggingface.co/spaces/nanotron/ultrascale-playbook" }, { month: "2025-02", name: "🐋 OpenR1-Math-220k", link: "https://huggingface.co/datasets/open-r1/OpenR1-Math-220k" }, { month: "2025-02", name: "🕺 DABstep", link: "https://huggingface.co/blog/dabstep" }, { month: "2025-02", name: "🔎 Open Deep Research", link: "https://huggingface.co/blog/open-deep-research" }, { month: "2025-02", name: "📝 SmolLM2 report", link: "https://huggingface.co/papers/2502.02737" }, { month: "2025-02", name: "🤖 Pi0 Integration", link: "https://x.com/RemiCadene/status/1886823939856589296" }, { month: "2025-03", name: "📄 SmolDocling", link: "https://huggingface.co/ds4sd/SmolDocling-256M-preview" }, { month: "2025-03", name: "🧑🎓 DCLM-edu", link: "https://huggingface.co/datasets/HuggingFaceTB/dclm-edu" }, { month: "2025-03", name: "💾 Stack-edu", link: "https://huggingface.co/datasets/HuggingFaceTB/stack-edu" }, { month: "2025-03", name: "🏅 Olympic Coder", link: "https://huggingface.co/open-r1/OlympicCoder-7B" }, { month: "2025-03", name: "🌅 Leaderboard Sunset", link: "https://x.com/clefourrier/status/1900280339613860057" }, { month: "2025-03", name: "🔎 Find a Leaderboard", link: "https://huggingface.co/spaces/OpenEvals/find-a-leaderboard" }, { month: "2025-03", name: "🚗 LeKiwi", link: "https://x.com/RemiCadene/status/1896535455325442390" }, { month: "2025-04", name: "🪑 YourBench", link: "https://huggingface.co/spaces/yourbench/demo" }, { month: "2025-04", name: "🦾 SO-101", link: "https://x.com/RemiCadene/status/1916751964807057515" }, { month: "2025-04", name: "🧑🎓 DeepLearning AI Agent Course", link: "https://x.com/DeepLearningAI/status/1915081924302839984" }, { month: "2025-05", name: "🤏 nanoVLM", link: "https://github.com/huggingface/nanoVLM" }, { month: "2025-05", name: "📝 OpenR1-Codeforces", link: "https://huggingface.co/datasets/open-r1/codeforces" }, { month: "2025-05", name: "🧠 Mixture of Thoughts", link: "https://huggingface.co/datasets/open-r1/Mixture-of-Thoughts" }, { month: "2025-05", name: "💻 Open Computer Agent", link: "https://huggingface.co/spaces/smolagents/computer-agent" }, { month: "2025-05", name: "🐣 Reachy Mini", link: "https://x.com/Thom_Wolf/status/1928103448970473962" }, { month: "2025-06", name: "🤖 LeRobot Hackathon", link: "https://x.com/RemiCadene/status/1917118988959813699" }, { month: "2025-06", name: "🤖 SmolVLA", link: "https://huggingface.co/collections/lerobot/smolvla-683c072ec3ef6ab0fcb87e60" }, { month: "2025-06", name: "🖥️ ScreenSuite", link: "https://github.com/huggingface/screensuite" } ];
function createSnakeTimeline() { // Group by month const grouped = {}; releases.forEach(item => { if (!grouped[item.month]) grouped[item.month] = []; grouped[item.month].push(item); });
const months = Object.keys(grouped).sort().reverse(); // Reverse to show latest first
// Create rows of 4 months each const rows = []; for (let i = 0; i < months.length; i += 4) { rows.push(months.slice(i, i + 4)); }
let html = '<div style="font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', sans-serif; position: relative;">';
rows.forEach((row, rowIndex) => { const isReverse = rowIndex % 2 === 1; // For reverse rows, we need to reverse the month order, not the display order const displayRow = isReverse ? [...row].reverse() : row; const isLastRow = rowIndex === rows.length - 1;
// Row container - the flex direction should always be normal html += <div style="display: flex; margin-bottom: 32px; min-height: 140px; position: relative;">;
// Horizontal connecting line (aligned with arrows) html += <div style="position: absolute; top: 8px; left: 0; right: 0; height: 1px; background: #e0e0e0; z-index: 1;"></div>;
displayRow.forEach((monthKey, monthIndex) => { const [year, month] = monthKey.split('-'); const monthName = new Date(year, month - 1).toLocaleString('en', { month: 'short' }).toUpperCase(); const events = grouped[monthKey] || []; const isYearMarker = month === '01';
// Month container html += <div style="flex: 1; padding: 0 15px; text-align: center; position: relative; z-index: 2;">;
// Arrow (positioned to align with horizontal line) - flipped for reverse chronological order const arrowStyle = isReverse ? 'width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 10px solid #666; margin: 2px auto 12px;' : 'width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-right: 10px solid #666; margin: 2px auto 12px;';
html += <div style="${arrowStyle}"></div>;
// Month title const titleStyle = isYearMarker ? 'font-weight: 600; font-size: 14px; color: #1a1a1a; background: #f0f0f0; padding: 4px 12px; border-radius: 12px; margin-bottom: 16px; display: inline-block;' : 'font-weight: 500; font-size: 13px; color: #666; text-transform: uppercase; margin-bottom: 16px; letter-spacing: 0.5px;';
const titleText = isYearMarker ? ${monthName} ${year} : monthName; html += <div style="${titleStyle}">${titleText}</div>;
// Events html += <div style="font-size: 12px; color: #4a4a4a; max-width: 180px; margin: 0 auto; display: flex; flex-direction: column; gap: 6px;">; events.forEach(event => { if (event.link && event.link !== '#') { // Clickable event with link html += <a href="${event.link}" target="_blank" style="text-decoration: none; color: inherit;"> <div style="padding: 6px 8px; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; line-height: 1.4; transition: all 0.2s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.05); cursor: pointer;" onmouseover="this.style.transform='translateY(-1px)'; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.background='#e3f2fd'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 1px 2px rgba(0,0,0,0.05)'; this.style.background='#f8f9fa'">${event.name}</div> </a>; } else { // Non-clickable event html += <div style="padding: 6px 8px; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; line-height: 1.4; color: #6c757d;">${event.name}</div>; } }); html += </div>;
html += </div>; // Close month container });
// Add vertical connector if not the last row if (!isLastRow) { const connectorStyle = isReverse ? 'position: absolute; width: 1px; height: calc(100% + 32px); background: #e0e0e0; top: 8px; left: 0; z-index: 1;' : 'position: absolute; width: 1px; height: calc(100% + 32px); background: #e0e0e0; top: 8px; right: 0; z-index: 1;';
html += <div style="${connectorStyle}"></div>; }
html += </div>; // Close row });
html += '</div>';
// Insert the timeline const container = document.getElementById('snake-timeline-container'); if (container) { container.innerHTML = html; } return html; }
// Export functions - ADD THESE TO YOUR EXISTING SCRIPT function exportStaticHTML() { const staticHTML = createSnakeTimeline(); const output = document.getElementById('static-output'); if (!output) { // Create output div if it doesn't exist const outputDiv = document.createElement('div'); outputDiv.id = 'static-output'; outputDiv.style.cssText = 'background: #f8f9fa; border: 1px solid #ddd; padding: 15px; border-radius: 6px; font-family: monospace; font-size: 12px; max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; margin-top: 15px;'; document.body.appendChild(outputDiv); } output.style.display = 'block'; output.textContent = <div id="snake-timeline-container" style="max-width: 1000px; margin: 20px auto; padding: 20px; background: white; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"> ${staticHTML} </div>; }
function copyToClipboard() { const output = document.getElementById('static-output'); if (output && output.textContent) { navigator.clipboard.writeText(output.textContent).then(() => { alert('✅ Static HTML copied to clipboard!'); }); } else { alert('⚠️ Please export first!'); } }
// Run with multiple fallbacks setTimeout(createSnakeTimeline, 100); setTimeout(createSnakeTimeline, 500); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createSnakeTimeline); } else { createSnakeTimeline(); } </script>
