Docs·Charting Library·Introduction

Getting Started

Install kline-orderbook-chart, create your first candle chart, and start the render loop. From npm install to your first live candle in under five minutes.

Five steps from npm install to your first chart. The whole walkthrough takes about five minutes once you have your license key.

Prerequisites: Node.js 18+, a modern browser (Chrome 90+, Firefox 90+, Safari 15.4+, Edge 90+). For mobile: iOS 15+ Safari, Android 9+ Chrome.

1. Install the package

Shell
npm install @mrd/chart-engine

The package ships as a single ES module with the native engine bundled in. No additional loaders, no peer dependencies, no post-install scripts to run.

What you getSize
Full library — JS + engine~380 KB gzipped
Runtime dependencies0
Framework dependencies0

2. Get a license key

A license key is required to run the engine.

  • Free 30-day trial — full feature set, includes a small watermark. No credit card. After 30 days the engine refuses to render the chart body and shows a centred "License expired — click to purchase" CTA. Request a trial key →
  • Production keys — single-domain, multi-domain, and unlimited tiers. See pricing.

Once you have a key, keep it server-side and inject it at request time. Do not commit it to a public repo.

3. Add a canvas to your HTML

The chart renders into a regular <canvas> element. The canvas needs a parent with a known size — the engine reads the parent's getBoundingClientRect() to size its internal framebuffer.

HTML
<div id="chart-container" style="width: 100%; height: 600px;">
  <canvas id="chart" style="width: 100%; height: 100%; display: block;"></canvas>
</div>

Important: display: block on the canvas matters. Without it, the browser leaves a 4 px gap at the bottom for the descender baseline, and the engine will spend its life chasing that wrong dimension across resizes.

4. Initialise the chart

JavaScript
import { createChartBridge, prefetchEngine } from '@mrd/chart-engine'

// Step 1 (optional but recommended): start downloading the engine binary
// in the background as soon as your app boots. Fire-and-forget — no
// await needed. When createChartBridge() runs later, it reuses the
// already-loaded module instead of waiting on the network.
prefetchEngine()

// Step 2: create the chart. This is async — it validates the license,
// loads the engine, reads the canvas size, and returns a fully wired
// chart instance.
const canvas = document.getElementById('chart')

const chart = await createChartBridge(canvas, {
  licenseKey: 'YOUR_LICENSE_KEY',
})

// Step 3: configure display settings (all optional, all have sensible
// defaults if you skip them).
chart.setTheme('dark')          // 'dark' or 'light'
chart.setPrecision(2)           // decimal places on the price axis
chart.setCandleInterval(3600)   // candle interval in seconds (3600 = 1h)

createChartBridge(canvas, options) — options

OptionTypeDescription
licenseKeystringYour license key. Also accepts key as an alias.
appIdstringMobile app identifier for mobile-app license keys. Optional.

The function returns a Promise that resolves to the chart instance — the object you'll call every method on for the rest of this guide. See Chart Instance for the full lifecycle reference.

5. Load candle data and start rendering

The engine expects OHLCV data as six parallel arrays. This shape avoids per-bar object overhead and matches what every crypto exchange API returns. Timestamps must be in Unix seconds (not milliseconds).

JavaScript
// Example: load 1000 hourly candles from your API.
const res = await fetch('/api/klines?symbol=BTCUSDT&interval=1h&limit=1000')
const raw = await res.json()
// raw is shaped like: [[openTime, open, high, low, close, volume, ...], ...]

const timestamps = new Float64Array(raw.length)
const opens      = new Float64Array(raw.length)
const highs      = new Float64Array(raw.length)
const lows       = new Float64Array(raw.length)
const closes     = new Float64Array(raw.length)
const volumes    = new Float64Array(raw.length)

for (let i = 0; i < raw.length; i++) {
  timestamps[i] = raw[i][0] / 1000  // ms → seconds
  opens[i]      = parseFloat(raw[i][1])
  highs[i]      = parseFloat(raw[i][2])
  lows[i]       = parseFloat(raw[i][3])
  closes[i]     = parseFloat(raw[i][4])
  volumes[i]    = parseFloat(raw[i][5])
}

chart.setKlines(timestamps, opens, highs, lows, closes, volumes)
chart.start()

start() boots the internal render loop. The chart now paints on every requestAnimationFrame where there's something new to draw, and stays idle otherwise.

You should see your candles on screen.

What you have so far

A live candle chart with:

  • Mouse pan + scroll-wheel zoom
  • Crosshair with price + time tooltip
  • Auto-scaling Y axis
  • Trackpad pinch zoom
  • Touch pan + pinch on mobile
  • All the UI affordances expected of a trading chart

What to add next

The fun part. Every advanced view layers on the same chart instance you already have.

Framework integration

The chart instance is framework-agnostic — it just needs a <canvas> DOM node and your data. Ready-made integration recipes:

  • React — see Integrating with React.
  • Vue 3 — see Integrating with Vue (same page, second half).
  • Svelte / vanilla — the same createChartBridge(canvas, options) call works without modification. Mount the canvas in your component, call createChartBridge in onMount, and call chart.destroy() when the component unmounts.

Common first-time issues

The canvas is blank and there are no errors. Your canvas's parent has zero height. Check the container's computed style — if height: 0 or unset, the engine has nothing to draw into. Set an explicit height on the container or use flex: 1 inside a flex column.

License error in the console: "license expired". Your trial key is past its 14-day window. Reach out to support for an extension, or upgrade at pricing.

Candles appear shifted from the time axis. Timestamps are in milliseconds, not seconds. Divide by 1000 before handing the array to setKlines().

Chart is sharp but the rest of my page is blurry, or vice versa. DPR mismatch. The engine handles its own internal DPR scaling — you don't need to set canvas.width / canvas.height manually. Remove any DPR scaling code you had on the canvas before init.

  • Chart Instance — every lifecycle method (start, stop, pause, resume, destroy) and the events your component will subscribe to.
  • Data Loading — real-time tick / append / prepend, infinite-scroll, and the typed-array shape.
  • Events & Tooltips — render your own tooltip from the hover payload.
  • Standalone side-panel enginesOrderbook · Depth Profile for single-venue order-flow signals or multi-exchange depth profile, DOM Ladder for a focused single-venue price ladder, Tick Stream for a trade-by-trade tape.
  • Performance & Smoothness — keep the chart at 60 fps even with a chatty tick feed.
  • Common Pitfalls — skim this before you ship; it covers ~80 % of the bugs first-time integrators hit.