Examples
Offline static and live examples, plus the in-repo playground.
Two runnable examples ship with Vela™, plus an interactive playground. Both examples use offline OHLCV — no network, no API key — so they run anywhere out of the box.
These snippets import from the npm package
@luxalgo/vela(see Installation).
Orientation snippet
The shape of every example is the same: create a chart over offline data, register a scripting engine, add an indicator. Vela™ ships no engine — these examples use the Pine addon (npm i @luxalgo/vela-pinets pinets; see Scripting engines).
import { Vela } from '@luxalgo/vela';
import { PineEngine } from '@luxalgo/vela-pinets';
const chart = new Vela('#chart', { data: myBars, timeframe: '1h', live: false, theme: 'dark' });
chart.registerEngine('pine', new PineEngine());
chart.addIndicator(`//@version=5
indicator("EMA", overlay=true)
plot(ta.ema(close, input.int(20, "Length")), "EMA", color.orange)`);With offline data, timeframe only drives bar spacing and axis labels; there is no fetch.
A fully-featured setup
Everything in one place — a provider-backed, live chart with a custom theme, the GPU backend, drawing tools, a scripting indicator, runtime tweaks, and events. Swap provider/symbol for data: myBars to run the same thing offline (minus the live feed).
Construct with the full option set:
import { Vela } from '@luxalgo/vela';
import { PineEngine } from '@luxalgo/vela-pinets';
import { BinanceProvider } from '@luxalgo/vela/providers/binance';
// A full custom theme — all seven fields are required.
const theme = {
background: '#0b0e14',
textColor: '#c9d1d9',
gridColor: '#1c2230',
borderColor: '#30363d',
upColor: '#26a69a',
downColor: '#ef5350',
fontFamily: 'Inter, system-ui, sans-serif',
};
const chart = new Vela('#chart', {
// market — provider-backed (use `data: myBars` instead to run offline)
provider: 'binance',
symbol: 'BTCUSDT',
timeframe: '1h',
bars: 1000,
live: true,
// appearance
theme,
upColor: '#26a69a', // candle colors live at the TOP level (the theme's up/down don't reach the candles)
downColor: '#ef5350',
priceStyle: 'candles', // candles | bars | line | area | baseline
currentPriceLine: true,
logScale: false,
glow: 0.4, // WebGL2 only
// backend + motion
nativeBackend: 'webgl2', // auto | canvas2d | webgl2
animations: { zoom: true, pan: false },
// interactive layers
drawings: { toolbar: true, tools: ['trendline', 'hline', 'ray', 'box', 'text'] },
// scripting
defaultLanguage: 'pine',
});Wire up the provider, engine, an indicator, runtime tweaks, and events:
// Neither a provider nor an engine is bundled; registerEngine is chainable.
chart.data.registerProvider('binance', new BinanceProvider());
chart.registerEngine('pine', new PineEngine());
await chart.data.ready(); // provider symbol index settled
await chart.ready(); // chart painted and interactive
// A Pine indicator in its own pane — the handle is usable synchronously.
const rsi = chart.addIndicator(
`//@version=5
indicator("RSI")
plot(ta.rsi(close, input.int(14, "Length")), "RSI", color.purple)`,
{ pane: 'new', title: 'RSI (14)' }, // AddIndicatorOptions: language / inputs / props / overlay / pane / title
);
rsi.on('ready', () => console.log(rsi.title, '→', rsi.inputs.length, 'inputs'));
rsi.on('error', ({ error }) => console.error('RSI failed:', error.message));
// Chart-level events.
chart.on('bar', (bar) => { /* the forming bar updated or a new bar appended */ });
chart.on('indicator:error', ({ id, error }) => console.error(id, error.message));
// Runtime appearance — no rebuild, no indicator re-run.
if (chart.renderer.supports('glow')) chart.renderer.set('glow', 0.6);
chart.renderer.set({ logScale: true, gridlines: true, timezone: 'America/New_York' });
// Frame a preset range, then read the exact window back.
chart.setVisibleRangePreset('3M');
const range = chart.getVisibleRange(); // { from, to } in epoch-ms (non-null after ready)
// Programmatic drawing + JSON round-trip.
if (range && chart.drawings.supported) {
chart.drawings.add('trendline', {
paneId: 'price',
anchors: [{ time: range.from, price: 30000 }, { time: range.to, price: 40000 }],
});
const saved = chart.drawings.toJSON(); // chart.drawings.fromJSON(saved) restores it
}
// Export a PNG snapshot; tear everything down when done.
const png = chart.renderer.screenshot(); // PNG data URL, or null if unsupported
// chart.destroy();Every option above is documented in Options; every method and event in API reference.
The two examples
| Example | What it shows |
|---|---|
| Static | History only: candles plus several indicators (EMA, MACD, RSI, bands with fills/markers/bgcolor) over offline bars. |
| Live | The same setup with a forming candle and indicators recomputing on each (locally synthesized) tick. |
The only meaningful difference between them is the
liveflag. The static example passeslive: false; the live example passeslive: trueand listens onchart.on('bar', …)to count ticks. Same data path, same engine registration, sameaddIndicatorcalls.
Adding drawings from code
The drawing toolbar is interactive by default; you can also place drawings programmatically and round-trip them through JSON:
chart.drawings.add('trendline', {
paneId: 'price',
anchors: [
{ time: myBars[10].time, price: myBars[10].low },
{ time: myBars[40].time, price: myBars[40].high },
],
});
const saved = chart.drawings.toJSON(); // persist this however you like
chart.drawings.fromJSON(saved); // …and restore it laterSee Drawing Tools for the full tool catalogue and toolbar UX.
Playground
The in-repo playground (npm run playground) mounts the full single-chart shell against live Binance data straight from the source (open /widget.html from the index) — edit playground/widget.ts to try options, providers, or your own indicator manifest. Press ? in the shell for the shortcut list.
Next steps
- New to the API? Start at Quickstart.
- Tuning behavior or appearance? See Options.
- Full surface and events? See API reference.