<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom</title>
    <description>The latest articles on DEV Community by Tom (@katomek).</description>
    <link>https://dev.to/katomek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3991939%2F4018cd64-da64-4e92-9f8e-f640cd23b4de.jpg</url>
      <title>DEV Community: Tom</title>
      <link>https://dev.to/katomek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katomek"/>
    <language>en</language>
    <item>
      <title>I open-sourced the financial charting library we use in production</title>
      <dc:creator>Tom</dc:creator>
      <pubDate>Fri, 19 Jun 2026 06:23:40 +0000</pubDate>
      <link>https://dev.to/katomek/i-open-sourced-the-financial-charting-library-we-use-in-production-1hh9</link>
      <guid>https://dev.to/katomek/i-open-sourced-the-financial-charting-library-we-use-in-production-1hh9</guid>
      <description>&lt;p&gt;If you've ever tried to build a trading dashboard, a crypto portfolio tracker, or any financial app, you probably ran into the "charting problem" pretty quickly.&lt;br&gt;
The standard industry approach goes something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Embed a heavy &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; from a 3rd party provider.&lt;/li&gt;
&lt;li&gt;Realize it doesn't quite match your app's UI/theme.&lt;/li&gt;
&lt;li&gt;Struggle with limited postMessage APIs to push real-time data.&lt;/li&gt;
&lt;li&gt;Watch the UI lag when you try to render multiple charts on the same page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I got tired of fighting with iframe embeds and DOM-based SVG charts that couldn't handle thousands of real-time ticks. I needed something native, fast, and entirely under my control.&lt;br&gt;
So, I built one. And today, I'm fully open-sourcing the core engine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Meet Exeria Charts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/efixdata/exeria-charts" rel="noopener noreferrer"&gt;Exeria Charts&lt;/a&gt; is a source-available, high-performance financial charting library designed for self-hosted web applications.&lt;br&gt;
Instead of embedding external widgets, Exeria renders directly inside your application using a highly optimized Canvas architecture.&lt;br&gt;
Here’s a quick look at what it can do: &lt;a href="https://exeria.dev" rel="noopener noreferrer"&gt;https://exeria.dev&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Tech Constraints (Why build another charting lib?)
&lt;/h2&gt;

&lt;p&gt;Building a financial chart isn't just about drawing boxes and lines. It’s about performance under pressure.&lt;br&gt;
When designing the architecture, we had a few strict requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero iframes:&lt;/strong&gt; It had to be a native JavaScript/React module that lives in the main DOM tree, styled perfectly to match the host application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-frequency updates:&lt;/strong&gt; Crypto and forex markets move fast. The library needed to handle sub-millisecond tick updates without dropping frames or blocking the main UI thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified runtime:&lt;/strong&gt; I didn't want a separate library for line charts, another for candlesticks, and another for volume histograms. We needed one engine that could switch views instantly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;We designed the API to be as straightforward as possible. Here is what a vanilla JS implementation looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createChart&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@efixdata/exeria-chart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Grab your container&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chart-root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 2. Initialize the chart&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createChart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// 3. Feed it some data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1715472000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;101.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;103.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;100.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;102.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1715475600000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;102.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;104.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;102.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;103.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2950&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMainSeriesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;milis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If you use React, we also built an open-source wrapper @efixdata/exeria-chart-ui-react that gives you out-of-the-box toolbars and menus).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Sourcing the Core&lt;/strong&gt;&lt;br&gt;
The core charting engine is available on GitHub under the AGPL-3.0 license.&lt;/p&gt;

&lt;p&gt;We've also open-sourced (MIT) a bunch of data connectors so you can plug straight into Binance, Kraken, Coinbase, etc., without writing websocket boilerplate.&lt;/p&gt;

&lt;p&gt;I’d love to get feedback from the Dev.to community.&lt;/p&gt;

&lt;p&gt;If you are building fintech apps, crypto trackers, or just like messing around with Canvas performance:&lt;/p&gt;

&lt;p&gt;What charting libraries are you currently using?&lt;br&gt;
What is the biggest pain point you have with displaying real-time data?&lt;br&gt;
Check out the Live Playground or drop a star on the Repo if you find it useful. Happy to answer any questions about Canvas rendering or handling high-frequency financial data in JS!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
