npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tabkit/core

v0.1.3

Published

Modern, responsive SVG tablature renderer for any stringed instrument

Downloads

257

Readme

@tabkit/core

Modern, responsive SVG tablature renderer for any stringed instrument. Zero dependencies, ~5KB gzipped.

Install

npm install @tabkit/core

Quick Start

Static SVG (SSR / Node.js)

import { TabRenderer } from '@tabkit/core'

const svg = TabRenderer.svg({
  measures: [
    {
      beats: [
        { string: 6, fret: 0, duration: '4n' },
        { string: 6, fret: 3, duration: '8n' },
        { string: 5, fret: 0, duration: '8n' },
        { string: 5, fret: 2, duration: '4n' },
      ],
      timeSignature: [4, 4],
      tempo: 120,
    },
  ],
  instrument: 'guitar',
  theme: 'dark',
})

Builder API (Browser)

new TabRenderer('#container')
  .measures(measures)
  .instrument('guitar')
  .theme('dark')
  .leftHanded(true)
  .layout('responsive')
  .draw()

// Get SVG string without rendering to DOM
const svgString = new TabRenderer()
  .measures(measures)
  .instrument('guitar')
  .toSvg()

Features

  • Zero dependencies — pure SVG string generation, no DOM needed
  • Responsive reflow — auto-wraps measures to fit any width
  • Accessible — ARIA labels, <title>, <desc>, WCAG 2.1 AA themes
  • Multi-instrument — guitar, bass, ukulele, banjo, or custom tuning
  • SSR ready — Node.js, Deno, edge functions
  • Left-handed mode — full string/note mirroring
  • Technique decorations — hammer-on, pull-off, slide, bend, vibrato, mute, tap, harmonics
  • Themeable — light/dark built-in, fully customizable
  • Export — PNG, SVG data URL, file download

Instruments

Built-in presets: 'guitar', 'bass', 'ukulele', 'banjo'.

TabRenderer.svg({
  measures: [...],
  instrument: { strings: 7, frets: 24, tuning: ['B','E','A','D','G','B','E'] },
})

Themes

TabRenderer.svg({
  measures: [...],
  theme: {
    background: '#0d1117',
    fretNumberColor: '#58a6ff',
    stringColor: '#8b949e',
  },
})

| Property | Description | |---|---| | background | Background color | | stringColor | String line color | | fretNumberColor | Fret number color | | barlineColor | Barline color | | cursorColor | Playback cursor color | | textColor | Label and title color | | accentColor | Highlight color | | techniqueColor | Technique decoration color | | fontFamily | Font family |

Options

| Option | Type | Default | Description | |---|---|---|---| | measures | TabMeasure[] | required | Tablature data | | instrument | string \| InstrumentConfig | 'guitar' | Instrument preset or custom | | theme | string \| Partial<TabTheme> | 'light' | Theme preset or custom | | layout | 'responsive' \| 'fixed' | 'responsive' | Layout mode | | leftHanded | boolean | false | Mirror for left-handed | | width | number | 800 | SVG width in pixels | | showTuning | boolean | true | Show tuning labels | | showTimeSignature | boolean | true | Show time signature | | noteLabels | boolean | false | Show note names (C, D#, …) below fret numbers — works for any instrument | | onNoteClick | (note, measure, beat) => void | — | Callback when a note is clicked | | ariaTitle | string | auto | Custom accessible title | | ariaDescription | string | auto | Custom accessible description |

Chords (Simultaneous Notes)

A beat can be a single TabNote or an array of TabNote[] for chords:

const measures: TabMeasure[] = [
  {
    beats: [
      // Single note
      { string: 6, fret: 0, duration: '4n' },
      // Chord — multiple notes played simultaneously
      [
        { string: 6, fret: 0, duration: '4n' },
        { string: 5, fret: 2, duration: '4n' },
        { string: 4, fret: 2, duration: '4n' },
        { string: 3, fret: 1, duration: '4n' },
        { string: 2, fret: 0, duration: '4n' },
        { string: 1, fret: 0, duration: '4n' },
      ],
    ],
    timeSignature: [4, 4],
  },
]

Repeat Marks

Measures support repeat barlines with an optional repeat count:

const measures: TabMeasure[] = [
  {
    beats: [{ string: 6, fret: 0, duration: '4n' }],
    repeat: { start: true },
  },
  {
    beats: [{ string: 5, fret: 2, duration: '4n' }],
    repeat: { end: true, times: 4 },
  },
]

Responsive Reflow

When layout: 'responsive' (default), the renderer calculates how many measures fit and breaks into multiple lines automatically.

TabRenderer.svg({
  measures: longRiff,
  width: 400,
  layout: 'responsive',
})

For programmatic control, use reflowMeasures() directly:

import { reflowMeasures, resolveInstrument, DEFAULT_LAYOUT } from '@tabkit/core'

const inst = resolveInstrument('guitar')
const result = reflowMeasures(measures, inst, DEFAULT_LAYOUT, 600)

result.lines       // TabLine[] — each line has measures and startMeasureIndex
result.totalHeight // total SVG height in pixels

Techniques

{ string: 3, fret: 5, duration: '8n', technique: 'hammer' }

Supported: 'hammer', 'pull', 'slide', 'bend', 'vibrato', 'mute', 'tap', 'harmonic'.

Harmonics are rendered with angle brackets (e.g. ⟨12⟩) to visually distinguish them from regular notes.

Left-Handed Mode

Use leftHanded: true in options for automatic mirroring, or call mirrorMeasures() directly:

import { mirrorMeasures, resolveInstrument } from '@tabkit/core'

const inst = resolveInstrument('guitar')
const mirrored = mirrorMeasures(measures, inst)
// String numbers are flipped: S1↔S6, S2↔S5, etc.

Accessibility

Auto-generated ARIA labels for screen readers:

import { generateAriaTitle, generateAriaDescription, resolveInstrument } from '@tabkit/core'

const inst = resolveInstrument('guitar')
const title = generateAriaTitle({ measures, instrument: 'guitar' }, inst)
const desc = generateAriaDescription({ measures, instrument: 'guitar' }, inst)

The SVG output automatically includes <title> and <desc> elements. Override with ariaTitle and ariaDescription options.

Export

const dataUrl = TabRenderer.toSVGDataURL(options)
const blob = await TabRenderer.toPNG(options, { scale: 2 })
await TabRenderer.download(options, { filename: 'riff', format: 'png' })

ExportOptions

| Option | Type | Default | Description | |---|---|---|---| | scale | number | 2 | Scale factor for PNG export | | filename | string | 'tablature' | Download filename (without extension) | | format | 'png' \| 'svg' | 'svg' | Download format |

Constants

import {
  GUITAR, BASS, UKULELE, BANJO,  // InstrumentConfig presets
  DEFAULT_LAYOUT,                  // LayoutMetrics defaults
  lightTheme, darkTheme,           // TabTheme objects
} from '@tabkit/core'

GUITAR   // { strings: 6, frets: 24, tuning: ['E','B','G','D','A','E'] }
BASS     // { strings: 4, frets: 24, tuning: ['G','D','A','E'] }
UKULELE  // { strings: 4, frets: 18, tuning: ['A','E','C','G'] }
BANJO    // { strings: 5, frets: 22, tuning: ['D','B','G','D','G'] }

Utility Functions

Resolvers

import { resolveInstrument, resolveTheme } from '@tabkit/core'

const inst = resolveInstrument('guitar')    // full InstrumentConfig
const theme = resolveTheme('dark')          // full TabTheme
const custom = resolveTheme({ background: '#000' }) // merges with light defaults

Duration & Measure Helpers

import { durationToBeats, measureDurationBeats, flattenBeat } from '@tabkit/core'

durationToBeats('4n')            // 1
durationToBeats('8n')            // 0.5
durationToBeats('2n')            // 2

measureDurationBeats(measure)    // total beats in a measure

// Normalize a beat (single note or chord) into an array
flattenBeat({ string: 1, fret: 0, duration: '4n' })  // [TabNote]
flattenBeat([note1, note2])                            // [note1, note2]

Layout Helpers

import { measureWidth, layoutMeasures, DEFAULT_LAYOUT } from '@tabkit/core'

const w = measureWidth(measure, DEFAULT_LAYOUT)  // pixel width of one measure
const positions = layoutMeasures(measures, DEFAULT_LAYOUT, 0)
// [{ measureIndex, x, width }, ...]

Data Types

type Duration = '1n' | '2n' | '4n' | '8n' | '16n' | '32n' | '8t' | '4t'
type Technique = 'hammer' | 'pull' | 'slide' | 'bend' | 'vibrato' | 'mute' | 'tap' | 'harmonic'
type TabBeat = TabNote | TabNote[]

interface TabNote {
  string: number          // 1 = thinnest / highest pitch
  fret: number            // 0 = open string
  duration: Duration
  technique?: Technique
  text?: string           // free-form label on the note
  accent?: boolean
  tie?: boolean           // tie to next note on same string
}

interface TabMeasure {
  beats: TabBeat[]
  timeSignature?: [number, number]
  tempo?: number
  label?: string
  repeat?: RepeatMark
}

interface RepeatMark {
  start?: boolean
  end?: boolean
  times?: number          // repeat count (default: 2)
}

interface InstrumentConfig {
  strings: number
  frets: number
  tuning: string[]
  name?: string
}

interface ExportOptions {
  scale?: number          // PNG scale factor (default: 2)
  filename?: string       // download filename without extension
  format?: 'png' | 'svg'
}

interface TabLine {
  measures: TabMeasure[]
  startMeasureIndex: number
}

interface ReflowResult {
  lines: TabLine[]
  totalHeight: number
}

Ecosystem

| Package | Description | |---------|-------------| | @tabkit/parser | Parse ASCII tabs and MusicXML | | @tabkit/player | Playback with cursor and metronome | | @tabkit/audio | Web Audio API synthesis | | @tabkit/react | React components and hooks | | chordkit | Chord diagram renderer |

License

MIT