[{"data":1,"prerenderedAt":267},["ShallowReactive",2],{"project-urcharts-en":3,"mdc--gc2wav-key":31},{"id":4,"title":5,"content":6,"description":7,"endDate":8,"extension":9,"image":8,"meta":10,"poster":27,"startDate":26,"stem":28,"style":19,"tags":29,"url":18,"__hash__":30},"projects_en/en/projects/urcharts.yml","UrCharts — GPU-Accelerated Financial Charting","> Part of **UrStack**, my open-source organization for TypeScript libraries.\nSiblings: [UrColor](/projects/urcolor), [UrVis](/projects/urvis), [UrDock](/projects/urdock).\n\n## Overview\n\nUrCharts renders charts on the GPU. Marks (lines, areas, splines, bars, candles,\nOHLC) go through WebGL2 via luma.gl. Text that has to stay crisp and selectable,\nmeaning axes, labels, legends and tooltips, renders as SVG and HTML on top.\n\nThe core is a minimal kernel and everything else is a plugin. Chart types, scales\nand interactions all attach through the same extension surface, so a build only\ncarries what it uses.\n\n---\n\n## Why I built it\n\nCharting libraries tend to fall apart at exactly the point financial workloads\nbegin: tens of thousands of candles, updating live. DOM-based renderers stall,\nand the canvas-based ones that survive usually hard-code their chart types.\n\nUrCharts pairs GPU rendering with D3's mathematics. Scales, ticks and formatting\nare solved problems worth reusing, so the part left open is the chart vocabulary\nitself.\n\n---\n\n## Key features\n\n- GPU rendering on WebGL2 through luma.gl, structured so WebGPU is a backend\n  swap rather than a rewrite\n- Financial marks: lines, areas, splines, bars, candles, OHLC\n- A minimal kernel, with chart types and interactions attaching as plugins\n- Streaming through a delta protocol and a RingBuffer, so live data flows\n  without reallocating history\n- D3 mathematics (`d3-scale`, `d3-array`, `d3-time`, `d3-format`) for scales,\n  ticks and formatting\n- Axes, labels, legends and tooltips rendered as SVG and HTML, so text stays\n  crisp\n- A Web Component core with React, Vue and Svelte adapters\n- MIT licensed\n\n---\n\n## Tech stack\n\n::tech-carousel{:tech='[\"typescript\", \"webgl\", \"d3\", \"vue\", \"react\", \"svelte\", \"vitepress\"]'}\n::\n\n- **Rendering**: WebGL2, luma.gl\n- **Math**: D3 (d3-scale, d3-array, d3-time, d3-format)\n- **Core**: TypeScript, Web Components\n- **Adapters**: React, Vue, Svelte\n- **Docs**: VitePress\n","Framework-agnostic TypeScript charting for financial and big-data workloads, rendering through WebGL2 with a plugin-first kernel and streaming support.",null,"yml",{"path":11,"body":12},"/en/projects/urcharts",{"title":5,"description":7,"poster":13,"url":18,"style":19,"tags":20,"startDate":26,"content":6},{"pattern":14,"gradient":15,"color":16,"bg":17},"square","linear","#ff653f","#1e104e","https://urcharts.vercel.app/","projects/urcharts-styles.css",[21,22,23,24,25],"UrStack","TypeScript","WebGL","D3","Charts","2026",{"pattern":14,"gradient":15,"color":16,"bg":17},"en/projects/urcharts",[21,22,23,24,25],"FvCybvj03pmUIxzTjf_q68swnPpyrl8mTGLPodKcErc",{"data":32,"body":33},{},{"type":34,"children":35},"root",[36,79,86,91,96,100,106,111,116,119,125,200,203,209,214],{"type":37,"tag":38,"props":39,"children":40},"element","blockquote",{},[41],{"type":37,"tag":42,"props":43,"children":44},"p",{},[45,48,53,55,62,64,70,71,77],{"type":46,"value":47},"text","Part of ",{"type":37,"tag":49,"props":50,"children":51},"strong",{},[52],{"type":46,"value":21},{"type":46,"value":54},", my open-source organization for TypeScript libraries.\nSiblings: ",{"type":37,"tag":56,"props":57,"children":59},"a",{"href":58},"/projects/urcolor",[60],{"type":46,"value":61},"UrColor",{"type":46,"value":63},", ",{"type":37,"tag":56,"props":65,"children":67},{"href":66},"/projects/urvis",[68],{"type":46,"value":69},"UrVis",{"type":46,"value":63},{"type":37,"tag":56,"props":72,"children":74},{"href":73},"/projects/urdock",[75],{"type":46,"value":76},"UrDock",{"type":46,"value":78},".",{"type":37,"tag":80,"props":81,"children":83},"h2",{"id":82},"overview",[84],{"type":46,"value":85},"Overview",{"type":37,"tag":42,"props":87,"children":88},{},[89],{"type":46,"value":90},"UrCharts renders charts on the GPU. Marks (lines, areas, splines, bars, candles,\nOHLC) go through WebGL2 via luma.gl. Text that has to stay crisp and selectable,\nmeaning axes, labels, legends and tooltips, renders as SVG and HTML on top.",{"type":37,"tag":42,"props":92,"children":93},{},[94],{"type":46,"value":95},"The core is a minimal kernel and everything else is a plugin. Chart types, scales\nand interactions all attach through the same extension surface, so a build only\ncarries what it uses.",{"type":37,"tag":97,"props":98,"children":99},"hr",{},[],{"type":37,"tag":80,"props":101,"children":103},{"id":102},"why-i-built-it",[104],{"type":46,"value":105},"Why I built it",{"type":37,"tag":42,"props":107,"children":108},{},[109],{"type":46,"value":110},"Charting libraries tend to fall apart at exactly the point financial workloads\nbegin: tens of thousands of candles, updating live. DOM-based renderers stall,\nand the canvas-based ones that survive usually hard-code their chart types.",{"type":37,"tag":42,"props":112,"children":113},{},[114],{"type":46,"value":115},"UrCharts pairs GPU rendering with D3's mathematics. Scales, ticks and formatting\nare solved problems worth reusing, so the part left open is the chart vocabulary\nitself.",{"type":37,"tag":97,"props":117,"children":118},{},[],{"type":37,"tag":80,"props":120,"children":122},{"id":121},"key-features",[123],{"type":46,"value":124},"Key features",{"type":37,"tag":126,"props":127,"children":128},"ul",{},[129,135,140,145,150,185,190,195],{"type":37,"tag":130,"props":131,"children":132},"li",{},[133],{"type":46,"value":134},"GPU rendering on WebGL2 through luma.gl, structured so WebGPU is a backend\nswap rather than a rewrite",{"type":37,"tag":130,"props":136,"children":137},{},[138],{"type":46,"value":139},"Financial marks: lines, areas, splines, bars, candles, OHLC",{"type":37,"tag":130,"props":141,"children":142},{},[143],{"type":46,"value":144},"A minimal kernel, with chart types and interactions attaching as plugins",{"type":37,"tag":130,"props":146,"children":147},{},[148],{"type":46,"value":149},"Streaming through a delta protocol and a RingBuffer, so live data flows\nwithout reallocating history",{"type":37,"tag":130,"props":151,"children":152},{},[153,155,162,163,169,170,176,177,183],{"type":46,"value":154},"D3 mathematics (",{"type":37,"tag":156,"props":157,"children":159},"code",{"className":158},[],[160],{"type":46,"value":161},"d3-scale",{"type":46,"value":63},{"type":37,"tag":156,"props":164,"children":166},{"className":165},[],[167],{"type":46,"value":168},"d3-array",{"type":46,"value":63},{"type":37,"tag":156,"props":171,"children":173},{"className":172},[],[174],{"type":46,"value":175},"d3-time",{"type":46,"value":63},{"type":37,"tag":156,"props":178,"children":180},{"className":179},[],[181],{"type":46,"value":182},"d3-format",{"type":46,"value":184},") for scales,\nticks and formatting",{"type":37,"tag":130,"props":186,"children":187},{},[188],{"type":46,"value":189},"Axes, labels, legends and tooltips rendered as SVG and HTML, so text stays\ncrisp",{"type":37,"tag":130,"props":191,"children":192},{},[193],{"type":46,"value":194},"A Web Component core with React, Vue and Svelte adapters",{"type":37,"tag":130,"props":196,"children":197},{},[198],{"type":46,"value":199},"MIT licensed",{"type":37,"tag":97,"props":201,"children":202},{},[],{"type":37,"tag":80,"props":204,"children":206},{"id":205},"tech-stack",[207],{"type":46,"value":208},"Tech stack",{"type":37,"tag":210,"props":211,"children":213},"tech-carousel",{":tech":212},"[\"typescript\", \"webgl\", \"d3\", \"vue\", \"react\", \"svelte\", \"vitepress\"]",[],{"type":37,"tag":126,"props":215,"children":216},{},[217,227,237,247,257],{"type":37,"tag":130,"props":218,"children":219},{},[220,225],{"type":37,"tag":49,"props":221,"children":222},{},[223],{"type":46,"value":224},"Rendering",{"type":46,"value":226},": WebGL2, luma.gl",{"type":37,"tag":130,"props":228,"children":229},{},[230,235],{"type":37,"tag":49,"props":231,"children":232},{},[233],{"type":46,"value":234},"Math",{"type":46,"value":236},": D3 (d3-scale, d3-array, d3-time, d3-format)",{"type":37,"tag":130,"props":238,"children":239},{},[240,245],{"type":37,"tag":49,"props":241,"children":242},{},[243],{"type":46,"value":244},"Core",{"type":46,"value":246},": TypeScript, Web Components",{"type":37,"tag":130,"props":248,"children":249},{},[250,255],{"type":37,"tag":49,"props":251,"children":252},{},[253],{"type":46,"value":254},"Adapters",{"type":46,"value":256},": React, Vue, Svelte",{"type":37,"tag":130,"props":258,"children":259},{},[260,265],{"type":37,"tag":49,"props":261,"children":262},{},[263],{"type":46,"value":264},"Docs",{"type":46,"value":266},": VitePress",1785819619070]