The Timeline Atlas
153 years of football tactical evolution, analyzed in Hex
What It Is
An interactive web app analyzing 48,891 FIFA matches from 1872 to 2025, showing how football evolved from 5.4 goals/match (offensive chaos) to 2.6 goals/match (defensive mastery) to 2.7 goals/match (modern equilibrium).
Built entirely in Hex: 28 Python cells for data, 18 metric cells for KPIs, 30+ explore cells for validation, 20+ markdown cells for narrative, and 8 custom HTML panels via IPython.display for Timeline Atlas design. Published with one click.
The Problem
What does 153 years of Football evolution tell us about the modern game?
Why does football look the way it is today?
What has repeatedly played a role in the best performances and results over time?
Based on historical context, from football fans to teams, sponsors and executives, what can FIFA stakeholders expect from the 2026 FIFA World Cup and how can each position for their best game?
The Solution
The Timeline Atlas uses Hex's complete toolkit to deliver an interactive journey through six tactical eras:
Data (Hex Python): Loaded 48,891 matches, classified into 6 eras, calculated 108 metrics
KPIs (Hex Metrics): 18 metric cells displaying goals/match, home advantage, scoring rates
Validation (Hex Explore): 30+ explore charts confirming patterns
Storytelling (Hex Markdown): 20+ narrative cells structuring the story
Enhancement (Hex HTML): 8 custom panels with Panel navigation and Timeline Atlas design
Publishing (Hex App): One-click deploy, 8 panels visible, 112 prep cells hidden
Dataset: International football results from 1872 to 2025
What I Found
The arc: 5.4 → 4.3 → 4.2 → 3.7 → 2.6 → 2.7 goals per match across six eras.
Pioneer (1870s-80s): 5.4 goals/match, 63% high-scoring | Attack at all costs
Formation (1890s-1910s): 4.3 goals/match | A gradual transition
WM Revolution (1920s-40s): 4.2 goals/match, 0.74 home advantage peak | Defense dominates
Total Football (1950s-60s): 3.7 goals/match | Fluidity beats rigidity
Defensive (1970s-80s): 2.6 goals/match, 27% shutouts | Rock bottom
Modern (1990s-2000s): 2.7 goals/match | Balance restored via rule changes
Key insights:
- Defensive tactics won (52% scoring decline)
- Home advantage peaked then fell 43% (globalization effect)
- 1970s-80s defensive crisis forced rule changes (backpass rule increased scoring)
- Modern 2.7 goals = tactical equilibrium, sustainable for 2026
How Hex Powered It
The Layered Approach
Foundation (Hex Native): Used Hex Python cells for data engineering (pandas processing 48,891 rows). Used Hex metric cells for instant KPI display. Used Hex explore cells to validate every pattern before custom development.
Enhancement (Hex Custom):
When I needed Timeline Atlas design fidelity (cream grid backgrounds, orange/teal palette, panel navigation), I used Hex's IPython.display.HTML() to render custom panels—still in Hex Python cells, still leveraging Hex's dependencies.
Publishing (Hex Infrastructure):
SetCellsInApp() to show only 8 panels, hide 112 prep cells. One publish button click. Hex handled hosting, responsive design and all. Done.
The Hex Edge
Versatility: Used Python cells, metric cells, explore cells, markdown cells, AND custom HTML—all in one Hex notebook.
Reactive execution: 120+ cells with complex dependencies worked seamlessly via Hex's dependency graph.
Publishing: Complex multi-panel app deployed with one click.
AI integration: Hex Notebook Agent generated 3,500+ lines using Hex's own tools and Hex Thread
Development Journey
What Worked
- Hex Python for data: Pandas in Hex cells processed 48,891 matches easily
- Hex explore for validation: Drag-drop charts confirmed patterns in seconds
- Hex dependencies: Changed classification logic once, 100+ downstream cells updated automatically
- Hex publishing: One click, app live, no deployment headaches
What Failed (and How It was Fixed)
Charts disappeared in published app
- Problem:
fig.to_json()broke Hex's HTML parser - Fix: Used
pyo.plot(output_type='div')for Hex-compatible rendering
Dependency errors
- Problem: Cells referenced undefined variables on publish
- Fix: Reordered cells, hardcoded static values
Navigation buttons invisible
- Problem: CSS conflicts with Hex defaults
- Fix: Unique class prefixes (
.pioneer-btn,.formation-btn)
Panel dots stuck
- Problem: Nav recreated on each panel switch
- Fix: Moved nav outside panels, updated via JavaScript
Content overflow
- Problem: Negative margins broke layout
- Fix: Explicit max-width containers
Variable collisions
- Problem: Hex's global scope inherited names
- Fix: Unique prefixes per era
Total: 6 Hex-specific bugs, 6 fixes, ~8 hours debugging
All issues were about understanding Hex's framework (publishing, dependencies, CSS, scope). Once learned, solutions were straightforward.
What Makes This Different
Hybrid Hex architecture: Most projects use Hex Python or explore cells. This uses Python + metrics + explore + markdown + custom HTML, all working together.
Panel navigation: 27 sub-panels with dot indicators and dynamic buttons for easier navigation
Design system: Complete custom Timeline Atlas design system implementation (3px borders, 30px radius, 8px shadows, Nunito 800 typography) while staying in Hex.
Scale: 8 custom HTML panels following identical template, proving the approach is repeatable.
Hex-powered end-to-end: From CSV ingestion to published app, every step happened in Hex.
The Numbers
120+ Hex cells | 48,891 matches | 6 eras | 108 metrics | 24 charts | 8 panels | 3,800 lines of code | All in Hex
Key Lessons
- Start with Hex native tools (metric/explore cells) for rapid prototyping
- Hex's IPython.display enables custom UI when design matters
- Understand Hex's publishing constraints (dependency order, rendering approaches)
- Namespace carefully (global scope persists across cells)
- Hex Notebook Agent accelerates development (3x faster with Hex-literate assistance)
- Hybrid approaches work (native + custom = best of both)
The Bottom Line
From 5.4 to 2.7 goals per match across 153 years—defensive tactics beat attack at all costs, then rule changes restored balance.
Built entirely in Hex using 120+ cells across its complete toolkit: Python for data, metrics for KPIs, explore for validation, markdown for narrative, custom HTML via IPython.display for design, and one-click publishing to deploy.
For 2026: Expect ~2.7 goals/match—tactical equilibrium is here to stay.
Powered by Hex from start to finish
Log in or sign up for Devpost to join the conversation.