Skip to main content

Get started

Step 1 — Install the package​

npm install @iccandle/reactjs-widget
# or
pnpm add @iccandle/reactjs-widget

Ensure react and react-dom are installed and meet the peer version range (React 18+).

Step 2 — Host the Charting Library​

Copy the TradingView Charting Library build into a path your app can serve as static files (e.g. public/charting_library/ in Vite or Create React App).

Import the library constructor from that path in your bundler setup (see TradingView’s integration docs for your framework). The library is not bundled inside @iccandle/reactjs-widget; it loads at runtime via library_path on the widget options.

Step 3 — Bootstrap TradingView with replay helpers​

Wrap your datafeed with withPlayChart and register custom indicators via getCustomIndicators so the embed can inject predicted / replay bars:

import { useEffect, useRef, useState } from "react";
import type {
ChartingLibraryWidgetOptions,
IChartingLibraryWidget,
ResolutionString,
} from "charting_library/charting_library";
import { widget } from "charting_library/charting_library";
import { withPlayChart, getCustomIndicators } from "@iccandle/reactjs-widget";

const LIBRARY_PATH = "/charting_library/";

const containerRef = useRef<HTMLDivElement>(null);
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
null,
);

useEffect(() => {
const el = containerRef.current;
if (!el) return;

const options: ChartingLibraryWidgetOptions = {
container: el,
library_path: LIBRARY_PATH,
symbol: "EURUSD",
interval: "60" as ResolutionString,
datafeed: withPlayChart(yourDatafeed),
locale: "en",
autosize: true,
drawings_access: {
type: "black",
tools: [{ name: "Date Range" }],
},
custom_indicators_getter: () => getCustomIndicators("light"),
};

const tv = new widget(options);
setChartWidget(tv);

return () => {
try {
tv.remove();
} catch {
/* no-op */
}
setChartWidget(null);
};
}, []);

You must supply a valid datafeed, symbol, interval, locale, and any other options required by your TradingView license and app. Import paths for widget and types differ by setup — follow TradingView’s docs for your bundler.

If your integration only exposes the instance after onChartReady, call setChartWidget inside that callback instead of immediately after new widget(...).

Step 4 — Wrap the chart with WidgetIccandle​

WidgetIccandle wraps your chart and renders the scanner overlay plus the results iframe. Pass the live widget instance (or null while mounting):

import { WidgetIccandle } from "@iccandle/reactjs-widget";

<WidgetIccandle chartWidget={chartWidget} theme="light" language="en">
<div ref={containerRef} style={{ height: "100%", minHeight: 400 }} />
</WidgetIccandle>

Render prop for chart refs​

Use a render-prop children when you need chartRefs for generated-candle studies (replay / predict):

<WidgetIccandle chartWidget={chartWidget} theme="dark" language="en">
{(chartRefs) => (
<ChartHost containerRef={containerRef} chartRefs={chartRefs} onReady={setChartWidget} />
)}
</WidgetIccandle>

A plain React node also works if you do not need those refs.

Step 5 — Enable Date Range drawing​

The scanner selects a bar window with TradingView’s Date Range tool. Enable it in drawings_access:

drawings_access: {
type: "black",
tools: [{ name: "Date Range" }],
},

Default window size is 25 bars.

Auth​

Users sign in through the embedded results app. On success, the embed posts sign-in-success and the parent stores iccandle_token in localStorage. Scan cache and pattern tracker APIs use that token as a Bearer credential.

You do not pass an API key prop to WidgetIccandle — auth is handled via the iframe login flow.

Theme and language​

  • theme="light" / theme="dark" — forces that palette for scanner chrome and the iframe.
  • theme="system" — follows prefers-color-scheme.
  • language — one of en, zh, vi, th, ko, ja, mn, ru (defaults to en). Applied to scanner UI and the results iframe locale.

Full working example​

import { useEffect, useRef, useState } from "react";
import type {
ChartingLibraryWidgetOptions,
IChartingLibraryWidget,
ResolutionString,
} from "charting_library/charting_library";
import { widget } from "charting_library/charting_library";
import {
WidgetIccandle,
withPlayChart,
getCustomIndicators,
} from "@iccandle/reactjs-widget";

const LIBRARY_PATH = "/charting_library/";

export function ChartWithIccandle() {
const containerRef = useRef<HTMLDivElement>(null);
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
null,
);

return (
<div style={{ height: "100vh", width: "100%" }}>
<WidgetIccandle
chartWidget={chartWidget}
theme="light"
language="en"
onCloseResult={() => {
/* optional: react when the embed posts close-result */
}}
>
{(chartRefs) => (
<ChartHost
containerRef={containerRef}
chartRefs={chartRefs}
onReady={setChartWidget}
/>
)}
</WidgetIccandle>
</div>
);
}

function ChartHost({
containerRef,
chartRefs,
onReady,
}: {
containerRef: React.RefObject<HTMLDivElement | null>;
chartRefs: import("@iccandle/reactjs-widget").WidgetIccandleChartRefs;
onReady: (w: IChartingLibraryWidget | null) => void;
}) {
useEffect(() => {
const el = containerRef.current;
if (!el) return;

const options: ChartingLibraryWidgetOptions = {
container: el,
library_path: LIBRARY_PATH,
symbol: "EURUSD",
interval: "60" as ResolutionString,
datafeed: withPlayChart(yourDatafeed),
locale: "en",
autosize: true,
drawings_access: {
type: "black",
tools: [{ name: "Date Range" }],
},
custom_indicators_getter: () => getCustomIndicators("light"),
};

const tv = new widget(options);
onReady(tv);

return () => {
try {
tv.remove();
} catch {
/* no-op */
}
onReady(null);
};
}, [containerRef, chartRefs, onReady]);

return <div ref={containerRef} style={{ height: "100%", width: "100%" }} />;
}

Replace yourDatafeed and widget options with your real datafeed and TradingView settings.

Features overview​

Pattern scanner​

  • Subscribes to chart readiness, symbol, resolution, and drawing events.
  • Manages a date_range multipoint drawing for the bar window.
  • On scan: posts candles to the cache service, then navigates the results iframe with search parameters.
  • Optional advanced filters (symbols, top-k, lookback period, probability window) stored in localStorage under search-filter.

Results iframe​

  • Loads https://embed-iccandle-app.iccandle.ai/{language}?theme=... by default.
  • After scan / news navigation, the src updates with search or similar-events paths.
  • On iframe load, the parent posts { type: "parent-origin", origin } so Stripe checkout can return to the host domain.

Pattern tracker​

From the scanner popup, users can open a subscription modal to track a custom pattern (name + timeframes + symbols). Requires a valid iccandle_token.

News / economic events​

  • Clicking a timescale mark can open an event info modal (currency calendar events; skips holidays / early / sentiment-only marks).
  • “Go to detail” loads similar events in the iframe and draws a vertical line on the chart.
  • Marks can be driven from localStorage keys tv:selected-news-events and tv:clicked-news-event if your datafeed implements getTimescaleMarks — see Optional: timescale marks.

Common patterns​

PatternApproach
Full-page chart + resultsParent with height: 100vh; WidgetIccandle fills the viewport and lays out chart + iframe.
Theme syncPass theme from your app shell (light / dark / system).
Locale syncPass language to match your app locale.
Gate scans until iframe readyPass iframeLoaded={true} once the results iframe has loaded (or omit the prop if you do not gate).
News marks on the time axisImplement getTimescaleMarks and sync with localStorage — see Configuration.