Open Source Libraries We Evaluated for GuitarTechHub — and Why We Built Our Own Instead

fretboard.js, VexTab, chord-symbol, and Tonal.js looked like obvious fits for our music-theory tools — here's what we found, and why we built our own instead.

  • open-source
  • music-theory
  • astro
  • decisions

GuitarTechHub’s calculators and backing-track player lean on a fair amount of music theory — chord parsing, scale suggestions, fretboard position diagrams. Before writing any of that by hand, we went looking for existing open source libraries to lean on instead. This is what we actually found, and why most of it didn’t make the cut.

fretboard.js and chord-symbol: unmaintained, and heavier than the gap

When we built the chord-tone highlighting on the scale-suggestion fretboard diagram (the small dot overlay that shows where to land a phrase while a backing track plays), fretboard.js and the chord-symbol npm package both looked like natural fits — a fretboard renderer and a chord-symbol parser are exactly the two pieces that feature needed.

Checking the actual repositories changed our minds. Both had gone quiet: fretboard.js’s last push was March 2023, chord-symbol’s was December 2023. Neither is necessarily broken, but neither is a bet we wanted to make for a feature we intended to keep extending. And the dependency cost was real, not hypothetical — fretboard.js pulls in d3-selection; chord-symbol pulls in four separate @tonaljs packages plus lodash. That’s a lot of transitive weight for capability our own zero-dependency fretboard.ts and ScaleDiagram.tsx already covered.

So we extended what we had instead: voicing.ts grew a chordToneIntervals() function, fretboardPositionsForScale() took an options object instead of four positional parameters and started returning an isChordTone flag per fretboard position, and ScaleDiagram.tsx renders a three-tier hierarchy — root (biggest dot) > chord tone (a safe note to land a phrase on) > plain scale tone (a passing tone) — with a small legend. No new dependencies, and we verified live that all three dot tiers render correctly during playback.

VexTab/VexFlow: a real, maintained library — solving a different problem

VexFlow is the one library here that’s genuinely well-maintained, and we still didn’t use it. It renders staff notation and tab, which is a different data model entirely from the position diagrams GuitarTechHub actually needs. Pulling it in would have meant learning and wiring up a notation-rendering engine to solve a “where do I put my finger” problem that a hand-built SVG fretboard already solves. The lesson here wasn’t “avoid maintained libraries” — it was “check that the library’s actual data model matches the problem before reaching for it,” which is easy to skip when a library’s name sounds like an exact match.

Tonal.js: deliberately not adopted, even though it’s a solid library

Tonal.js is a legitimate, well-regarded music theory library, and we considered it as the theory engine underneath scale-suggestion.ts. We didn’t adopt it, and the reason is specific to how that file is written, not a knock on Tonal.js itself.

scale-suggestion.ts maps each supported chord quality to a scale via an exhaustive switch statement with no default case — which means if a new ChordQuality is ever added to the type without updating the scale mapping, the build fails to compile. That’s a deliberate safety net, not an oversight. Swapping in an external theory library would mean giving up that compile-time guarantee across a wide, already-tested surface of code, for a capability upgrade — a bigger chord-quality vocabulary — that GuitarTechHub doesn’t currently need. If the site’s supported chord qualities ever genuinely need to grow past the current set, Tonal.js is still the first thing we’d reach for. Until then, adding it would be trading a real safety guarantee for flexibility nothing is asking for yet.

The pattern across all four

None of these were rejected because they’re bad libraries. Two were unmaintained relative to how much we’d be depending on them; one solves an adjacent but different problem; one would have quietly removed a safety net that’s actively catching bugs today. Checking an open source library seriously — real maintenance status, real dependency weight, real fit against the existing code’s actual guarantees — usually takes less time than integrating it would have, and it’s the difference between a considered decision and just reaching for the first search result.