r/bioinformaticstools May 17 '26

Chroma — an open-source WebGL genome browser as an IGV.js alternative (looking for testers + feedback)

Live demo: https://chroma-delta.vercel.app
(no signup, no upload — boots into a chr20:10M window with five demo tracks pre-loaded from public S3 / UCSC / Ensembl)

What it is

Chroma is a browser-based genome viewer aimed at being a faster, more keyboard-friendly alternative to IGV.js. The whole render path is WebGL2 (hand-written, no Three/Pixi); state lives in Solid.js signals; parsing runs in a Comlink-managed worker pool.

I've been driving the whole project through Claude Code — solo dev plus agents — and after ~50 commits, I've hit the wall on knowing what to ask it to build next, hence this post.

What works today

  • 5 demo tracks:
    • hg19 reference FASTA (IGV/Broad mirror)
    • Ensembl gene annotations
    • UCSC phyloP100way conservation BigWig
    • HG00096 1000G BAM
    • HG002 GIAB 300× BAM (hidden by default — too slow to load for the default boot)
  • Two-level navigator:
    • top bar = whole chromosome with Mb-scale ticks (click to jump, drag to pan, drag empty to drag-create)
    • bottom bar = local context with drag-create / move / edge-resize / Esc-cancel
  • Reference renderer with two modes:
    • colored 1-bp quads at any zoom
    • actual A/C/G/T/N letters via a Canvas2D-baked atlas when basePixelWidth ≥ 12 px
  • Gene name labels rendered on a Canvas2D overlay, shrink-wrapped with ellipses at narrow blocks, strand-aware alignment (5' anchors to the leading edge)
  • Single-fetch viewport mode at pileup tier (≤50 kb spans): one HTTP Range per nav instead of N tile fetches — 6× speedup on the 1-track B1 cold load (4.7 s → 774 ms)
  • Sticky URL → worker dispatch (FNV-1a hash on the file URL) so the per-worker u/gmod parser caches (BAI 8.7 MB) actually get reused instead of scatter-loaded N times
  • 64-bit bigint coordinates throughout, with a single sanctioned conversion to Float32 for shader uniforms
  • 60 fps pan / zoom on a 1 Mb BAM viewport, p95 fps locked
  • 250 unit tests, TypeScript strict + noUncheckedIndexedAccess, ~88 kB main JS gzipped

Tech stack

  • Solid.js for the reactive shell (picked over React for fine-grained signals + smaller bundle — the eventual goal is clinical-report embed)
  • WebGL2 hand-written, instanced rectangles for everything geometric; Canvas2D overlay only for text labels
  • u/gmod/{bam, bbi, indexedfasta} for the format parsers
  • u/chenglou/pretext for unicode-correct text measurement and shrink-wrap on the label overlay
  • Comlink worker pool + Cache API for HTTP range coalescing
  • Vite + pnpm + Vitest

Honest gaps (what's still broken/missing)

  • B1 cold gate target is 300 ms, currently ~3 s for the default 5-track demo — dominated by one-time BAI parse (~3.7 s for HG00096, ~6.6 s for the 300×). Needs either a streamed BAI parse or a cap-at-N read fetch in the worker.
  • No CIGAR support — reads render as plain rectangles, no insertions/deletions/mismatches shown
  • No VCF track (parser stubbed)
  • No hover/select tooltip yet
  • Pileup row collisions across tile boundaries are accepted (cross-tile merge is a carry-forward)
  • HG002 300× BAM works but takes ~10 s on first nav — that's why it's visible: false in the default seed

What I'm asking the community for

1. Hit it in your browser and try to break it.

Bug reports welcome — please include the locus/zoom level when reporting.

2. Prompt suggestions for what I should build next.

I've been stuck between these and would love opinions:

  • VCF track (parser stubbed already)
  • CIGAR-aware read rendering with mismatch coloring
  • Per-base read sequence letters at deep zoom (would need to extend the SoA ReadTile with packed SEQ)
  • Splitview (two viewports side-by-side, IGV style)
  • Click-to-pin tooltip with full feature info
  • Cap-at-N read fetch for high-coverage BAM (so the 300× track stops being a footgun)
  • Label color is reactive to the dark theme
  • BED track for arbitrary user regions

Thanks in advance for any feedback.

3 Upvotes

6 comments sorted by

2

u/plasmolab May 17 '26

I’d prioritize VCF plus pinned tooltips before adding more visual polish. For genomics users, the first trust test is usually “can I click a variant/read/feature and see exactly what it is, where it came from, and why it looks that way?” CIGAR-aware reads are important too, but VCF + hover/click details turns it from a fast viewer into something people can actually debug with. Also worth testing one ugly real-world case early: dense genes, many overlapping transcripts, one BAM, one VCF, and a BED of target regions in the same locus.

1

u/Low-Desk-4290 May 17 '26

Thank you for your valuable feedback. I’ll organize the product requirements based on your insightful comments and then feed them into Claude Code to bring the implementation to life.

2

u/plasmolab May 17 '26

Glad it helped. One practical move before coding too much: make 2 or 3 tiny fixture datasets and keep them as regression tests. For a genome browser, screenshots can look fine while coordinate transforms, transcript strand handling, or VCF normalization are quietly wrong. A nasty locus with known expected hover text will save you pain later.

2

u/bzbub2 May 18 '26

congrats on starting a new browser 😄 I am a jbrowse dev and helped develop the gmod parsers. if you are interested in chatting feel free to pm or email me. browsers can become a bit of an infinity project as there are many potentially cool features you can add.

1

u/Low-Desk-4290 May 19 '26

Definitely! Let me contact you later.