Build an Evidence-Friendly Bitcoin Timeline with Static HTML and TimelineJS
A timeline can make a long technical history easier to explore, but a visual slider alone is not enough. If the events are hidden inside a third-party feed or rendered only after JavaScript runs, readers, search engines, and assistive tools have less context to work with.
This tutorial shows how to build a small static timeline from the open-source The History of Bitcoin repository. The project stores its event data in the repository, keeps a chronological HTML index in the page, and adds metadata for crawlers and answer engines. The result is an interactive timeline without a backend or database.
The project is educational. It is not investment advice, and historical price references are snapshots rather than predictions.
TL;DR
You will:
- Clone the
gh-pagesbranch. - Serve the files with Python's built-in HTTP server.
- Inspect the local event data in
assets/js/timeline-data.js. - Render it with TimelineJS.
- Verify the page, metadata, and source links locally.
The repository is MIT licensed and currently documents 37 curated events from 2007 through June 30, 2026.
Prerequisites
You need:
- Git.
- Python 3.8 or newer with the
pylauncher on Windows, orpython3on macOS and Linux. - A browser.
- Basic HTML and JavaScript familiarity.
The published project uses the gh-pages branch directly. It is a static site, not a package with a versioned release. That means you should treat the branch contents you clone as the source snapshot you are reviewing.
1. Run the existing timeline
Clone the branch and start a local server:
git clone --branch gh-pages --depth 1 https://github.com/paladini/bitcoin-history.git cd bitcoin-history python -m http.server 8058 On Windows PowerShell, the equivalent command is:
py -3 -m http.server 8058 Open http://127.0.0.1:8058/. The expected result is a page titled “The History of Bitcoin: Interactive Timeline (2007-2026)†with a TimelineJS navigation area, a chronological event index, and an educational disclaimer.
The repository's README documents the same local server path. In a smoke test of the current branch, the page returned HTTP 200 and served the expected HTML.
2. Understand the data boundary
The important design choice is that the timeline data lives in the repository instead of a live spreadsheet. Open assets/js/timeline-data.js. It assigns a TimelineJS-compatible object to window.bitcoinHistoryTimelineData.
A simplified event has this shape:
{ "start_date": { "year": "2008", "month": "10", "day": "31" }, "text": { "headline": "The Bitcoin white paper is published", "text": "Satoshi Nakamoto publishes the original peer-to-peer electronic cash proposal." } } The actual repository keeps the dates and text as strings because that is the structure expected by TimelineJS. It also stores the title and the complete event array in the same file, so a reviewer can inspect the source without opening a database or calling an application API.
To add an event, append another object to the events array. Keep the date explicit, use a factual headline, and include a source link in the visible HTML index when the claim depends on a primary document.
3. Connect the data to TimelineJS
The end of index.html loads TimelineJS and then passes the local object to the constructor:
<script src="https://cdn.knightlab.com/libs/timeline3/latest/js/timeline.js"></script> <script src="assets/js/timeline-data.js"></script> <script> new TL.Timeline("timeline-embed", window.bitcoinHistoryTimelineData, { hash_bookmark: true, language: "en", timenav_position: "bottom" }); </script> The order matters. The data file must load before the constructor runs. The timeline-embed element must also exist in the document:
<section id="history" aria-label="Interactive Bitcoin timeline"> <div id="timeline-embed"></div> </section> The hash_bookmark option lets the selected event be represented in the URL. That makes a particular point in the timeline easier to share and revisit.
The project currently loads TimelineJS from Knight Lab's CDN. The event data is local, but the page is not fully self-contained offline because the library and stylesheet are external dependencies. If you need an offline archive, download and serve those assets locally, then verify their licenses and update the HTML references.
4. Keep a crawlable fallback
The interactive component is useful for exploration, but the page does not depend on it for all meaning. The current HTML also contains:
- A visible summary of the covered period.
- An ordered list of chronological milestones.
-
timeelements with machine-readable dates. - Source links for selected historical and regulatory claims.
- A disclaimer that separates education from investment advice.
This fallback is valuable when JavaScript fails, when a crawler reads the raw HTML, or when a reader wants to scan the chronology without operating a visual control.
A simple event entry looks like this:
<li> <time datetime="2024-01-10">January 10, 2024</time> - The SEC approves spot Bitcoin exchange-traded products. <a href="https://www.sec.gov/newsroom/speeches-statements/gensler-statement-spot-bitcoin-011023"> Source </a> </li> The visible list should stay synchronized with the JavaScript data. A practical workflow is to update the data object first, then add the same event to the HTML index, then run a local review.
5. Add metadata without hiding the content
The current page uses ordinary HTML metadata rather than relying only on the interactive widget. It includes a canonical URL, a description, Open Graph fields, a Twitter card, Dublin Core fields, and JSON-LD.
The JSON-LD describes the page as a web page, article, image, breadcrumb, and item list. The repository also publishes robots.txt, sitemap.xml, and llms.txt.
These files do not replace good content. They make the page's identity, language, date range, license, and update date easier for different consumers to interpret. Use descriptive titles and headings, keep the canonical URL stable, and ensure that metadata matches the visible page.
6. Verify changes reproducibly
After editing an event, repeat the same checks:
python -m http.server 8058 Then verify:
- The page returns HTTP 200.
- The browser shows the timeline and the chronological index.
- The selected event updates the URL hash.
- The event appears in both
timeline-data.jsand the HTML list. - Source links open the intended primary pages.
- The disclaimer remains visible.
- No API key, wallet credential, or private data was added.
For a command-line smoke test, request the local page:
curl -I http://127.0.0.1:8058/ A successful response should include HTTP/1.0 200 OK or an equivalent HTTP 200 status from the local Python server.
Why this structure works
The repository separates three concerns:
-
timeline-data.jsis the structured event source for the visualization. -
index.htmlprovides the readable fallback and metadata. -
robots.txt,sitemap.xml, andllms.txtdescribe how the published page can be discovered.
That separation is small enough to review in a pull request. It also avoids making the interactive library responsible for facts, source attribution, or the page's entire information architecture.
Failure modes and limitations
If the timeline is blank, check that the external TimelineJS script loaded, that timeline-data.js appears before the constructor, and that the timeline-embed element exists.
If the page works locally but not on a host, check the base path, case-sensitive asset names, and HTTPS mixed-content rules. GitHub Pages serves the project under /bitcoin-history/, so relative asset paths are safer than root-relative paths.
The project is a curated historical view, not a complete ledger of every Bitcoin event. Some entries include price snapshots, which can become stale. Regulatory and institutional claims can also require updates as official sources change. The MIT license permits reuse, but reused copies should preserve attribution and should not imply that the original author endorses financial decisions.
FAQ
Does this need a database?
No. The current project keeps the event data in a JavaScript file and publishes static HTML.
Is it fully offline?
Not as published. The event data is local, but TimelineJS is loaded from a CDN. Self-host the library and stylesheet if offline operation is a requirement.
Is this an investment tool?
No. It is an educational chronology. It does not predict prices, recommend assets, or manage wallets.
Can I add my own milestones?
Yes. Add a dated object to the event array and mirror it in the HTML index. Cite a primary source for claims that readers may want to verify.
Takeaway
A useful historical visualization does not have to begin with a database. A local event file, a readable HTML fallback, explicit sources, and a small client-side renderer are enough to build something interactive and reviewable.
AI assistance disclosure: AI assistance was used to organize this tutorial and improve its wording. The repository behavior, file names, current branch, license, and smoke-test results were checked against the linked primary sources.
What would you add first: more historical events, local self-hosted TimelineJS assets, or automated checks that compare the HTML index with the JavaScript event data?