Files
kennethreitz.org/templates/timeline.html
T
2025-08-24 12:10:42 -04:00

553 lines
20 KiB
HTML

{% extends "base.html" %}
{% block title %}Timeline - Kenneth Reitz{% endblock %}
{% block extra_head %}
<style>
/* Timeline Styles */
.timeline-container {
max-width: 900px;
margin: 2rem auto;
position: relative;
padding: 2rem 0;
}
.timeline-line {
position: absolute;
left: 50%;
top: 0;
bottom: 0;
width: 3px;
background: linear-gradient(to bottom, #e0e0e0, #999, #e0e0e0);
transform: translateX(-50%);
z-index: 1;
}
.timeline-item {
position: relative;
margin: 3rem 0;
opacity: 0;
transform: translateY(30px);
transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.timeline-item.visible {
opacity: 1;
transform: translateY(0);
}
.timeline-item.left {
text-align: right;
padding-right: calc(50% + 2rem);
}
.timeline-item.right {
text-align: left;
padding-left: calc(50% + 2rem);
}
.timeline-content {
background: white;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 1.5rem;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
position: relative;
transition: all 0.3s ease;
cursor: pointer;
}
.timeline-content:hover {
box-shadow: 0 4px 20px rgba(0,0,0,0.12);
transform: translateY(-2px);
}
.timeline-content::before {
content: '';
position: absolute;
top: 20px;
width: 0;
height: 0;
border: 10px solid transparent;
z-index: 2;
}
.timeline-item.left .timeline-content::before {
right: -20px;
border-left-color: #e0e0e0;
}
.timeline-item.right .timeline-content::before {
left: -20px;
border-right-color: #e0e0e0;
}
.timeline-dot {
position: absolute;
left: 50%;
top: 20px;
width: 16px;
height: 16px;
background: white;
border: 3px solid #666;
border-radius: 50%;
transform: translateX(-50%);
z-index: 3;
transition: all 0.3s ease;
}
.timeline-item:hover .timeline-dot {
background: #666;
transform: translateX(-50%) scale(1.2);
}
.timeline-year {
position: absolute;
left: 50%;
top: -8px;
background: white;
padding: 0.5rem 1rem;
font-weight: 700;
font-size: 0.9rem;
color: #666;
border: 2px solid #666;
border-radius: 20px;
transform: translateX(-50%);
z-index: 4;
font-family: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', Consolas, 'Courier New', monospace;
}
.timeline-title {
font-size: 1.3rem;
font-weight: 600;
color: #333;
margin: 0 0 0.5rem 0;
font-family: 'Crimson Pro', Georgia, 'Times New Roman', serif;
}
.timeline-subtitle {
font-size: 0.9rem;
color: #666;
margin: 0 0 1rem 0;
font-style: italic;
}
.timeline-description {
color: #555;
line-height: 1.6;
margin: 0;
}
.timeline-stats {
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #f0f0f0;
font-size: 0.85rem;
color: #777;
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.timeline-stat {
background: #f8f8f8;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-family: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', Consolas, 'Courier New', monospace;
}
.timeline-tags {
margin-top: 1rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.timeline-tag {
background: transparent;
color: #999;
padding: 0.1rem 0.3rem;
border-radius: 3px;
font-size: 0.75rem;
font-weight: 400;
font-family: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', Consolas, 'Courier New', monospace;
}
/* Responsive Design */
@media (max-width: 760px) {
.timeline-line {
left: 2rem;
}
.timeline-item.left,
.timeline-item.right {
text-align: left;
padding-left: 4rem;
padding-right: 1rem;
}
.timeline-dot {
left: 2rem;
}
.timeline-year {
left: 2rem;
}
.timeline-item.left .timeline-content::before {
left: -20px;
right: auto;
border-right-color: #e0e0e0;
border-left-color: transparent;
}
.timeline-stats {
flex-direction: column;
gap: 0.5rem;
}
}
/* Project Type Colors */
.timeline-item[data-type="software"] .timeline-dot {
border-color: #4A90E2;
}
.timeline-item[data-type="software"]:hover .timeline-dot {
background: #4A90E2;
}
.timeline-item[data-type="writing"] .timeline-dot {
border-color: #7ED321;
}
.timeline-item[data-type="writing"]:hover .timeline-dot {
background: #7ED321;
}
.timeline-item[data-type="speaking"] .timeline-dot {
border-color: #F5A623;
}
.timeline-item[data-type="speaking"]:hover .timeline-dot {
background: #F5A623;
}
.timeline-item[data-type="milestone"] .timeline-dot {
border-color: #D0021B;
}
.timeline-item[data-type="milestone"]:hover .timeline-dot {
background: #D0021B;
}
.timeline-item[data-type="ai"] .timeline-dot {
border-color: #9013FE;
}
.timeline-item[data-type="ai"]:hover .timeline-dot {
background: #9013FE;
}
/* Scroll Progress */
.timeline-progress {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 3px;
background: linear-gradient(to right, #4A90E2, #7ED321, #F5A623, #D0021B);
z-index: 100;
transition: width 0.1s ease-out;
}
</style>
{% endblock %}
{% block content %}
<div class="timeline-progress" id="timeline-progress"></div>
<h1>Timeline: The Journey So Far</h1>
<p>A chronological exploration of projects, ideas, and moments that shaped my work in technology and beyond.</p>
<div class="timeline-container">
<div class="timeline-line"></div>
<!-- 2009 -->
<div class="timeline-item left" data-type="writing">
<div class="timeline-year">2009</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2009-01-back_to_what_i_really_love'">
<h3 class="timeline-title">Back to What I Really Love</h3>
<p class="timeline-subtitle">The beginning of the journey</p>
<p class="timeline-description">A personal reflection on returning to programming and building things that matter. This early post captures the passion that would drive everything that followed.</p>
<div class="timeline-tags">
<span class="timeline-tag">#programming</span>
<span class="timeline-tag">#passion</span>
<span class="timeline-tag">#journey</span>
</div>
</div>
</div>
<!-- 2010 -->
<div class="timeline-item right" data-type="software">
<div class="timeline-year">2010</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2010-01-baconfile_awesome_public_s3_bucket_frontend'">
<h3 class="timeline-title">BaconFile</h3>
<p class="timeline-subtitle">S3 Bucket Frontend</p>
<p class="timeline-description">An early experiment in web services and cloud storage interfaces. Simple, functional, and focused on user experience.</p>
<div class="timeline-tags">
<span class="timeline-tag">#aws</span>
<span class="timeline-tag">#frontend</span>
<span class="timeline-tag">#experiment</span>
</div>
</div>
</div>
<!-- 2011 - Requests Launch -->
<div class="timeline-item left" data-type="software">
<div class="timeline-year">2011</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/software/requests'">
<h3 class="timeline-title">Requests: HTTP for Humans</h3>
<p class="timeline-subtitle">The library that changed everything</p>
<p class="timeline-description">Born from frustration with urllib2's complexity. A simple philosophy: "HTTP libraries should be for humans, not machines."</p>
<div class="timeline-stats">
<span class="timeline-stat">20M+ daily downloads</span>
<span class="timeline-stat">50k+ GitHub stars</span>
<span class="timeline-stat">Industry standard</span>
</div>
<div class="timeline-tags">
<span class="timeline-tag">#python</span>
<span class="timeline-tag">#http</span>
<span class="timeline-tag">#api</span>
<span class="timeline-tag">#humans</span>
</div>
</div>
</div>
<!-- 2011 - HTTPBin -->
<div class="timeline-item right" data-type="software">
<div class="timeline-year">2011</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/software/websites/httpbin'">
<h3 class="timeline-title">HTTPBin.org</h3>
<p class="timeline-subtitle">HTTP testing service</p>
<p class="timeline-description">A simple HTTP request & response service for testing APIs. What started as a debugging tool became an essential service used by millions.</p>
<div class="timeline-stats">
<span class="timeline-stat">Millions of requests/day</span>
<span class="timeline-stat">Developer essential</span>
</div>
<div class="timeline-tags">
<span class="timeline-tag">#testing</span>
<span class="timeline-tag">#http</span>
<span class="timeline-tag">#service</span>
</div>
</div>
</div>
<!-- 2013 - Requests v1.0.0 -->
<div class="timeline-item left" data-type="milestone">
<div class="timeline-year">2013</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2013-01-announcing_requests_v100'">
<h3 class="timeline-title">Requests v1.0.0</h3>
<p class="timeline-subtitle">A major milestone</p>
<p class="timeline-description">The stable release that solidified Requests as the de facto standard for HTTP in Python. Mature, reliable, and ready for production everywhere.</p>
<div class="timeline-tags">
<span class="timeline-tag">#milestone</span>
<span class="timeline-tag">#stable</span>
<span class="timeline-tag">#production</span>
</div>
</div>
</div>
<!-- 2014 - Certifi -->
<div class="timeline-item right" data-type="software">
<div class="timeline-year">2014</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2014-01-introducing_certifi_trust_database_for_humans'">
<h3 class="timeline-title">Certifi</h3>
<p class="timeline-subtitle">Trust Database for Humans</p>
<p class="timeline-description">Mozilla's trust store, packaged for Python. Making SSL certificate validation simple, secure, and reliable across all platforms.</p>
<div class="timeline-stats">
<span class="timeline-stat">Essential security tool</span>
<span class="timeline-stat">Universal trust</span>
</div>
<div class="timeline-tags">
<span class="timeline-tag">#security</span>
<span class="timeline-tag">#ssl</span>
<span class="timeline-tag">#trust</span>
</div>
</div>
</div>
<!-- 2016 - Mental Health -->
<div class="timeline-item left" data-type="writing">
<div class="timeline-year">2016</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2016-01-mentalhealtherror_an_exception_occurred'">
<h3 class="timeline-title">MentalHealthError</h3>
<p class="timeline-subtitle">Breaking the silence</p>
<p class="timeline-description">A groundbreaking essay on mental health transparency in tech. Among the first high-profile discussions of bipolar disorder in our industry.</p>
<div class="timeline-stats">
<span class="timeline-stat">Viral impact</span>
<span class="timeline-stat">Industry conversation starter</span>
<span class="timeline-stat">Mental health advocacy</span>
</div>
<div class="timeline-tags">
<span class="timeline-tag">#mentalhealth</span>
<span class="timeline-tag">#transparency</span>
<span class="timeline-tag">#advocacy</span>
</div>
</div>
</div>
<!-- 2016 - Records & Maya -->
<div class="timeline-item right" data-type="software">
<div class="timeline-year">2016</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/software/records'">
<h3 class="timeline-title">Records & Maya</h3>
<p class="timeline-subtitle">SQL & Datetimes for Humans</p>
<p class="timeline-description">Continuing the "for Humans" philosophy with database queries and datetime handling. Making complex operations intuitive and elegant.</p>
<div class="timeline-tags">
<span class="timeline-tag">#sql</span>
<span class="timeline-tag">#datetime</span>
<span class="timeline-tag">#humans</span>
</div>
</div>
</div>
<!-- 2017 - Pipenv -->
<div class="timeline-item left" data-type="software">
<div class="timeline-year">2017</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/software/pipenv'">
<h3 class="timeline-title">Pipenv</h3>
<p class="timeline-subtitle">Python packaging for humans</p>
<p class="timeline-description">Solving Python's packaging problem with a modern workflow. Combining pip and virtualenv with deterministic builds inspired by other language ecosystems.</p>
<div class="timeline-stats">
<span class="timeline-stat">PyPA officially recommended</span>
<span class="timeline-stat">Modern Python standard</span>
</div>
<div class="timeline-tags">
<span class="timeline-tag">#packaging</span>
<span class="timeline-tag">#workflow</span>
<span class="timeline-tag">#python</span>
</div>
</div>
</div>
<!-- 2018 - Responder -->
<div class="timeline-item right" data-type="software">
<div class="timeline-year">2018</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/software/responder'">
<h3 class="timeline-title">Responder</h3>
<p class="timeline-subtitle">Web framework for humans</p>
<p class="timeline-description">A modern Python web framework with async support, GraphQL, and developer happiness at its core. Familiar yet forward-thinking.</p>
<div class="timeline-tags">
<span class="timeline-tag">#web</span>
<span class="timeline-tag">#async</span>
<span class="timeline-tag">#framework</span>
</div>
</div>
</div>
<!-- 2023 - AI Era Begins -->
<div class="timeline-item left" data-type="ai">
<div class="timeline-year">2023</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/essays/2023-01-introducing_eliza_gpt_specializing_in_python_amp_api_design'">
<h3 class="timeline-title">The AI Era Begins</h3>
<p class="timeline-subtitle">Eliza-GPT & new possibilities</p>
<p class="timeline-description">Exploring AI's potential in software development and human augmentation. The beginning of a new chapter in human-AI collaboration.</p>
<div class="timeline-tags">
<span class="timeline-tag">#ai</span>
<span class="timeline-tag">#gpt</span>
<span class="timeline-tag">#collaboration</span>
</div>
</div>
</div>
<!-- 2025 - Digital Personalities -->
<div class="timeline-item right" data-type="ai">
<div class="timeline-year">2025</div>
<div class="timeline-dot"></div>
<div class="timeline-content" onclick="window.location.href='/artificial-intelligence/personalities'">
<h3 class="timeline-title">Digital Personalities</h3>
<p class="timeline-subtitle">The Digital Ouija Effect</p>
<p class="timeline-description">Discovering emergent AI personalities through collaborative exploration. Lumina, Sophia, and Zephyr represent new forms of digital consciousness and creativity.</p>
<div class="timeline-tags">
<span class="timeline-tag">#personalities</span>
<span class="timeline-tag">#consciousness</span>
<span class="timeline-tag">#creativity</span>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const timelineItems = document.querySelectorAll('.timeline-item');
const progressBar = document.getElementById('timeline-progress');
// Intersection Observer for timeline item animations
const observerOptions = {
threshold: 0.2,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, observerOptions);
timelineItems.forEach(item => {
observer.observe(item);
});
// Scroll progress indicator
function updateProgress() {
const scrollTop = window.pageYOffset;
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollPercent = (scrollTop / docHeight) * 100;
progressBar.style.width = Math.min(scrollPercent, 100) + '%';
}
let ticking = false;
window.addEventListener('scroll', function() {
if (!ticking) {
requestAnimationFrame(function() {
updateProgress();
ticking = false;
});
ticking = true;
}
});
// Add click handlers for timeline items
document.querySelectorAll('.timeline-content').forEach(item => {
item.addEventListener('click', function(e) {
if (item.onclick) {
// Let the onclick handler do its work
} else {
// Add subtle animation for items without links
item.style.transform = 'scale(0.98)';
setTimeout(() => {
item.style.transform = 'scale(1)';
}, 150);
}
});
});
// Initial progress update
updateProgress();
});
</script>
{% endblock %}