Unified JSON datasets and TypeScript libraries for drawing tablets, pens, drivers, and their relationships.
| Entity | Files |
|---|---|
| Brands | data/brands/brands.json |
| Tablets | data/tablets/<BRAND>-tablets.json |
| Pens | data/pens/<BRAND>-pens.json |
| Pen Families / Tablet Families | data/pen-families/, data/tablet-families/ |
| Pen Compatibility | data/pen-compat/<BRAND>-pen-compat.json |
| Drivers | data/drivers/<BRAND>-drivers.json |
| Pressure Response / Pressure Range | data/pressure-response/, data/pressure-range/ |
| Inventory | data/inventory/<user>-{pens,tablets}.json |
Record counts are deliberately not listed here — a hand-maintained table
went stale by ~90 tablets. For current counts, see the DrawTabData
Explorer's About page
(generated at each deploy by buildVersionInfo() in lib/version-info.ts),
or run npm run version-info.
Pin a specific version of the data in your project:
git submodule add https://github.com/TheSevenPens/DrawTabData.git data-repogit clone https://github.com/TheSevenPens/DrawTabData.git data-repoDownload and copy the data/ and lib/ folders directly into your project.
No local files needed — load data at runtime:
// From GitHub Pages
const ds = await loadAllFromURL("https://thesevenpens.github.io/DrawTabData/data");
// From raw.githubusercontent
const ds = await loadAllFromURL("https://raw.githubusercontent.com/TheSevenPens/DrawTabData/master/data");The package ships its TypeScript sources (like its query engine,
@thesevenpens/queriton), so
consume it from a TypeScript-aware runtime or bundler — tsx, Vite,
SvelteKit. @thesevenpens/queriton is a peer dependency.
import { createDiskDataSet } from "drawtabdata/dataset-node";
const ds = createDiskDataSet({ dataDir: "node_modules/drawtabdata/data" });
console.log(await ds.Pens.filter("Brand", "==", "WACOM").count());Entry points: dataset, dataset-node, loader, loader-node,
all, all-node, compat, reference, units,
entities/<tablet|pen|driver|pen-family|tablet-family|pen-compat>, and
data/* for the JSON files.
import { loadAllFromDisk } from "./data-repo/lib/drawtab-all-node.js";
const ds = loadAllFromDisk("./data-repo/data");
console.log(`${ds.tablets.length} tablets`);
console.log(`${ds.pens.length} pens`);
console.log(`${ds.penCompat.length} compatibility pairs`);import { loadAllFromURL } from "./data-repo/lib/drawtab-all.js";
const ds = await loadAllFromURL("https://your-server.com/data");The ds object contains:
ds.tablets,ds.pens,ds.penCompat,ds.penFamilies,ds.tabletFamilies,ds.drivers— all entity arraysds.tabletToPens— Map: tablet ModelId to compatible Pen[]ds.penToTablets— Map: pen PenId to compatible Tablet[]ds.includedPenMap— Map: pen PenId to Tablet[] that include it
Every record has an EntityId that uniquely identifies it: BRAND.ENTITYTYPE.ID
WACOM.TABLET.PTK870WACOM.PEN.KP501EWACOM.DRIVER.6.3.45-2_WINDOWSWACOM.PENFAMILY.WacomKPGEN3WACOM.TABLETFAMILY.WacomIntuosProGen8
Fields on one entity reference IDs on another:
| Field | On entity | References |
|---|---|---|
ModelIncludedPen |
Tablet | Array of PenIds on Pen |
ModelFamily |
Tablet | FamilyId on TabletFamily |
PenFamily |
Pen | FamilyId on PenFamily |
TabletId |
PenCompat | ModelId on Tablet |
PenId |
PenCompat | PenId on Pen |
import { filterByBrand, filterByType } from "./data-repo/lib/drawtab-loader-node.js";
const wacomDisplays = filterByType(filterByBrand(ds.tablets, "WACOM"), "PENDISPLAY");const pens = ds.tabletToPens.get("PTK-870") ?? [];
for (const pen of pens) {
console.log(`${pen.PenName} (${pen.PenId})`);
}const tablets = ds.penToTablets.get("KP-501E") ?? [];
for (const tablet of tablets) {
console.log(`${tablet.ModelName} (${tablet.ModelId})`);
}import { containsText } from "./data-repo/lib/drawtab-loader-node.js";
const matches = ds.tablets.filter(t =>
containsText(t.ModelName, "16") && containsText(t.ModelName, "pro")
);import { getDiagonal, formatDimensions } from "./data-repo/lib/drawtab-loader-node.js";
import { formatValue } from "./data-repo/lib/units.js";
const largest = ds.tablets
.map(t => ({ tablet: t, diag: getDiagonal(t.DigitizerDimensions) }))
.filter(({ diag }) => diag !== null)
.sort((a, b) => b.diag! - a.diag!)
.slice(0, 10);
for (const { tablet, diag } of largest) {
const mm = diag!.toFixed(1);
const inches = formatValue(mm, "mm", "imperial");
console.log(`${tablet.ModelName} - ${formatDimensions(tablet.DigitizerDimensions)} mm (${mm} mm / ${inches} in diagonal)`);
}import { formatValue, getFieldLabel } from "./data-repo/lib/units.js";
formatValue("345.5", "mm", "imperial"); // "13.60"
formatValue("1145", "g", "imperial"); // "40.38"
getFieldLabel("Diagonal (mm)", "mm", "imperial"); // "Diagonal (in)"Supported: mm to in, g to oz, LPmm to LPI, px/mm to PPI.
| Function | Module | Description |
|---|---|---|
loadAllFromDisk(dataDir) |
drawtab-all-node |
Load everything from disk (sync) |
loadAllFromURL(baseUrl) |
drawtab-all |
Load everything from URL (async) |
filterByBrand(items, brand) |
drawtab-loader |
Case-insensitive brand filter (generic) |
filterByType(tablets, type) |
drawtab-loader |
Case-insensitive type filter |
containsText(value, search) |
drawtab-loader |
Case-insensitive substring match |
equalsText(value, search) |
drawtab-loader |
Case-insensitive equality |
getDiagonal(dimensions) |
drawtab-loader |
Compute diagonal from Width/Height |
formatDimensions(dimensions) |
drawtab-loader |
Format as "W x H" or "W x H x D" string |
formatValue(value, unit, pref) |
units |
Convert metric/imperial |
getFieldLabel(label, unit, pref) |
units |
Update label with active unit |
buildTabletToPenCompatMap(compat, pens) |
compat-helpers |
Map: tabletId to Pen[] |
buildPenToTabletCompatMap(compat, tablets) |
compat-helpers |
Map: penId to Tablet[] |
buildIncludedPenMap(tablets) |
compat-helpers |
Map: penId to Tablet[] (included) |
A live explorer UI is available at thesevenpens.github.io/DrawTabDataExplorer.
Source: github.com/TheSevenPens/DrawTabDataExplorer
data/
tablets/ HUION, WACOM, XENCELABS, XPPEN
pens/ WACOM
pen-families/ WACOM
tablet-families/ WACOM
pen-compat/ WACOM (pen -> tablet[] grouped format)
drivers/ WACOM
Files are partitioned by brand: BRAND-entitytype.json (e.g. WACOM-tablets.json).
Contributors: tablets, pens and pressure-response sessions are authored one
record per file under source/<collection>/<brand>/<EntityId>.json.
The data/tablets/*, data/pens/* and data/pressure-response/* bundles are generated from them
(npx tsx scripts/generate.ts --write) — edit the source file, never the bundle.
See docs/DATALAYOUT.txt.
- User Manual — detailed guide with all examples
- Architecture — project structure and library design
- Fields — tablet field definitions with formats and units
- Data Layout — JSON file organization
- Decisions — design decision log
- Futures — roadmap
ISC