Skip to content
Menu

Look

Language

GitHub — @IchiSieben
Projects

Metal Globe

Live usable

I put 195,679 metal bands on a 3D globe, filterable by country, genre and decade.

195,679 metal bands from 153 countries on a navigable 3D globe: filter by country, genre and decade, with country sheets and a treemap that make an otherwise unreadable catalog legible.

Technology

  • Frontend
  • Data viz
  • Scraping

Sector

  • Music & culture

Problem

Encyclopaedia Metallum has the data — nearly 200,000 bands — but its own site is a flat, unfilterable list. There is no way to see where a scene comes from, how a country's metal output compares to its neighbors, or how genres shift across regions without scrolling through hundreds of paginated tables.

Approach

A custom scraper over Encyclopaedia Metallum, plus a data pipeline and a framework-free visualization built to survive both a slow connection and a demanding 3D scene at once.

Metal Archives has no public API, and as of this build its pages sit behind a Cloudflare Turnstile challenge that blocks requests and headless browsers alike. The working path was Scrapling on top of Camoufox (a stealth Firefox build): a human solves the challenge once, and that same warmed-up browser session then sweeps every country page without being challenged again — a new browser launch gets a new fingerprint and gets blocked again, so the scrape runs as one continuous local session rather than a distributed job.

The scraped bands, genres and city-level metadata feed a Python pipeline that resolves genre taxonomy, geocodes countries, and assembles a single JSON the frontend consumes. The globe itself is hand-written WebGL through three.js: real TopoJSON borders projected onto a sphere, per-city pins, and level-of-detail that swaps in named countries and treemap panels as the camera zooms from planetary to continental to country view — no chart or globe library beyond three.js and ECharts for the side panels.

The original 4,408-line index.html shipped everything — markup, styles and app logic — in one file. It now splits cleanly into index.html, styles.css, data.js and app.js, with flags lazy-loaded per country instead of bundled up front.

Result

bands indexed
195,679

web/data/bands_index.json

countries covered
153

web/data/atlas_data.json

main HTML lines after split
496

web/index.html

Standards

Software quality (ISO/IEC 25010) Not run through a formal ISO/IEC 25010 checklist. Maintainability was addressed directly: the 4,408-line monolith was split into index.html + styles.css + data.js + app.js without changing a pixel.
Web performance (Core Web Vitals) not measured
Accessibility (WCAG 2.2) not measured
Research software (FAIR4RS) n/a — not research software
Security hygiene No secrets in the repo. Browser session state under data/cache/*_state.json is gitignored before the repo goes public.
Reproducibility The scraping pipeline is fully scripted (scraper/*.py), but Cloudflare Turnstile needs one human click per session, so a clean-clone rerun is not push-button end to end.
Benchmark methodology no benchmark claimed
Data / model documentation n/a
Versioning & change log No SemVer or CHANGELOG; plain commit history on GitHub.

What I'd do next

  • Split app.js (2,959 lines) the same way index.html already was, into feature modules.
  • Add the genre × country filter (currently only one-directional) proposed as the next UI iteration.
  • Move the scraping session past its one manual Cloudflare click, or document it as a permanent constraint instead of a TODO.