[{"data":1,"prerenderedAt":113},["ShallowReactive",2],{"products":3,"post:why-we-built-opendraw":100,"product-by-slug:opendraw":108},[4,23,38,60,73,85],{"title":5,"tagline":6,"description":7,"status":8,"kind":9,"order":10,"art":11,"artAlt":12,"platforms":13,"facts":16,"links":20,"slug":11,"path":22},"Fold","Journaling, but cool.","The journaling app for Gen Z. Photos, voice notes and quick thoughts, captured with a tap, a hold, or a swipe.","waitlist","app",1,"fold","A skeleton reading a book in a field of roses",[14,15],"iOS","Android",[17,18,19],"Free","Coming 2026","No account, no cloud",{"waitlist":21},"https:\u002F\u002Ffold.taohq.org","\u002Fproducts\u002Ffold",{"title":24,"tagline":25,"description":26,"status":27,"kind":9,"order":28,"art":29,"artAlt":30,"platforms":31,"facts":33,"links":35,"slug":29,"path":37},"Bottles","Bookmarks and docs, filed properly.","A quiet place for your links, notes and files. No feed, no noise. One space for what you keep, one for what you write.","live",2,"bottles","A skull resting in still water, surrounded by rings of ripples",[32],"Web",[34],"Live now",{"app":36},"https:\u002F\u002Fbottles.taohq.org","\u002Fproducts\u002Fbottles",{"title":39,"tagline":40,"description":41,"status":42,"kind":43,"order":44,"art":39,"artAlt":45,"platforms":46,"facts":51,"links":54,"install":58,"slug":39,"path":59},"opendraw","Hand-drawn diagrams, as one component.","A free, open-source hand-drawn whiteboard for your app. Draw hand-drawn diagrams with shapes, arrows, text and sticky notes, one component for Vue, Nuxt, React and Svelte.","open-source","library",3,"A hand-drawn diagram: a rectangle, an ellipse, an arrow, a sticky note, a diamond and a spark",[47,48,49,50],"Vue","Nuxt","React","Svelte",[52,53],"MIT license","Autosaves to localStorage",{"app":55,"github":56,"npm":57},"https:\u002F\u002Fopendraw.taohq.org","https:\u002F\u002Fgithub.com\u002FTheAlphaOnes\u002Fopendraw","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@opendrawjs\u002Fnuxt","npm i @opendrawjs\u002Fnuxt","\u002Fproducts\u002Fopendraw",{"title":61,"tagline":62,"description":63,"status":64,"kind":9,"order":65,"art":66,"artAlt":67,"platforms":68,"facts":69,"slug":66,"path":72},"Bubbles.space","Your AI assistant's home.","A personal AI workspace OS built for the way you actually think. Bubbles, your assistant, lives and works alongside you.","in-development",4,"bubbles-space","A small figure sitting under a blossoming tree beneath a full moon",[],[70,71],"Part of the Bubbles family","AI-agent first","\u002Fproducts\u002Fbubbles-space",{"title":74,"tagline":75,"description":76,"status":64,"kind":9,"order":77,"art":78,"artAlt":79,"platforms":80,"facts":82,"slug":78,"path":84},"Bubbles.mail","It reads your inbox so you don't have to.","An intelligent mail client that turns the raw chaos of email into a short report of what matters, what can wait, and what to hand off.",5,"bubbles-mail","A skull crowned with blossoms, pierced by an arrow",[81],"macOS",[70,83],"Native macOS","\u002Fproducts\u002Fbubbles-mail",{"title":86,"tagline":87,"description":88,"status":42,"kind":43,"order":89,"art":86,"artAlt":90,"platforms":91,"facts":93,"links":95,"install":98,"slug":86,"path":99},"web-have-sounds","UI sounds, generated with math.","A zero-dependency JavaScript library for UI sound effects. No audio files, no network requests. Just the Web Audio API.",6,"A crow perched on a skull inside an arched frame",[32,92],"npm",[94],"Zero dependencies",{"github":96,"npm":97},"https:\u002F\u002Fgithub.com\u002FNormVg\u002Fweb-have-sound","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@thenormvg\u002Fweb-have-sounds","npm i @thenormvg\u002Fweb-have-sounds","\u002Fproducts\u002Fweb-have-sounds",{"title":101,"description":102,"date":103,"author":104,"product":39,"slug":105,"path":106,"readingMinutes":44,"html":107},"Why We Built opendraw","Excalidraw is a wonderful app you have to leave your app to use. The case for a hand-drawn whiteboard that ships as a component instead.","2026-10-31","taohq","why-we-built-opendraw","\u002Fwriting\u002Fwhy-we-built-opendraw","\u003Cp>Every builder knows this moment. You&#39;re explaining your product to someone — a teammate, a client, your future self — and at some point words stop being enough. You need a rectangle, an arrow, and a circle with a line through it. So you reach for a whiteboard.\u003C\u002Fp>\n\u003Cp>\u003Ca href=\"https:\u002F\u002Fexcalidraw.com\">Excalidraw\u003C\u002Fa> nailed what that moment should feel like. The sketchy rendering, the arrows that stick to shapes, the keyboard shortcuts — it&#39;s the whiteboard against which all other whiteboards are measured, and we say that as grateful users. opendraw would not exist without it, and we&#39;ve said so \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FTheAlphaOnes\u002Fopendraw\">in the repo\u003C\u002Fa> too.\u003C\u002Fp>\n\u003Ch2>The leaving part\u003C\u002Fh2>\n\u003Cp>Here&#39;s what bothered us. Using any whiteboard app means leaving the app you&#39;re actually building. You visit a site, you draw, you export a PNG, you paste the PNG. The moment the diagram leaves the whiteboard, it dies a little: it can&#39;t be edited, it can&#39;t be listened to, and it sits in your app as a picture of thinking rather than as thinking.\u003C\u002Fp>\n\u003Cp>That&#39;s fine for a one-off sketch. It&#39;s not fine when the whiteboard \u003Cem>is\u003C\u002Fem> a feature. Planning flows inside your project tool. Diagrams attached to your docs. A canvas in your education app. For those, the whiteboard has to live where the work lives, feel like the rest of the product, and save where you decide — not on someone else&#39;s site.\u003C\u002Fp>\n\u003Ch2>The two bad options\u003C\u002Fh2>\n\u003Cp>Until now, embedding a whiteboard meant choosing between two bad options.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Option one: the iframe.\u003C\u002Fstrong> Embed a hosted board in a box. The drawing is technically on your page, but it&#39;s a foreign runtime: its own domain, its own login, its own styling that will never match yours, its own mobile experience inside a box inside your mobile experience. It works, the way a window into someone else&#39;s house works.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Option two: build your own.\u003C\u002Fstrong> A canvas engine with hit testing, gesture handling, undo history, text editing, arrow binding, export... call it a few months. We know, because we did it.\u003C\u002Fp>\n\u003Ch2>The third option\u003C\u002Fh2>\n\u003Cp>We wanted the thing that didn&#39;t exist: a whiteboard as a \u003Cstrong>native component\u003C\u002Fstrong>. No iframe, no foreign runtime. Mounts like any other component, renders in your theme, fires events you can persist anywhere, and — this was the real requirement — can also run \u003Cem>headless\u003C\u002Fem>, as just a canvas you drive yourself, for the times the full editor UI is not what your product needs.\u003C\u002Fp>\n\u003Cp>That requirement forced the architecture: the engine and the interactive editor know nothing about any UI framework, and the Vue, React and Svelte packages are thin adapters over the same core. One engine, four frameworks, no duplication.\u003C\u002Fp>\n\u003Ch2>Honest about lineage\u003C\u002Fh2>\n\u003Cp>opendraw follows Excalidraw&#39;s lead closely on purpose — how tools, selection, arrow binding, undo and shortcuts behave was studied from its source, so people who know Excalidraw feel at home immediately. Some parts are outright ported and adapted, with the MIT notices kept: the elbow-arrow router, the laser pointer&#39;s trail, the two-finger pinch and pan, and Excalifont for the hand-drawn text.\u003C\u002Fp>\n\u003Cp>If you want a complete, collaborative whiteboard app, use excalidraw.com. opendraw is for the other case: putting a whiteboard \u003Cem>inside your own app\u003C\u002Fem>.\u003C\u002Fp>\n\u003Ch2>Why open source\u003C\u002Fh2>\n\u003Cp>A component lives inside other people&#39;s codebases. Nobody should have to take that on faith — the source has to be readable, buildable and forkable, and the license has to let you ship it without calling us. So: MIT, no paid tier, no &quot;cloud sync for teams&quot; upsell hiding behind the component. What you mount is what you run.\u003C\u002Fp>\n\u003Cp>We wrote more this week: \u003Ca href=\"\u002Fwriting\u002Fhow-we-built-opendraw\">how the engine is built\u003C\u002Fa>, \u003Ca href=\"\u002Fwriting\u002Fhow-to-use-opendraw\">a practical guide to using it\u003C\u002Fa>, and \u003Ca href=\"\u002Fwriting\u002Finside-the-opendraw-engine\">a tour inside the engine\u003C\u002Fa>. And you can just go draw: \u003Ca href=\"https:\u002F\u002Fopendraw.taohq.org\">opendraw.taohq.org\u003C\u002Fa>.\u003C\u002Fp>\n",{"title":39,"tagline":40,"description":41,"status":42,"kind":43,"order":44,"art":39,"artAlt":45,"platforms":109,"facts":110,"links":111,"install":58,"slug":39,"path":59,"html":112},[47,48,49,50],[52,53],{"app":55,"github":56,"npm":57},"\u003Cp>\u003Cstrong>opendraw is a free, open-source hand-drawn whiteboard for your app: shapes, arrows, text and sticky notes, rendered sketchy, as one component for Vue, Nuxt, React and Svelte.\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Ch2>What you can draw\u003C\u002Fh2>\n\u003Cp>Rectangles, diamonds and ellipses, arrows that connect, lines, freehand drawing, text, sticky notes and frames. Everything renders sketchy through rough.js, so it looks drawn by hand, because it was. There are tools and shortcuts for everything: every tool has a key, from V for select to K for the laser pointer. Press \u003Ccode>?\u003C\u002Fcode> inside the editor for the full list.\u003C\u002Fp>\n\u003Ch2>One engine, five packages\u003C\u002Fh2>\n\u003Cp>opendraw ships as five packages:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>@opendrawjs\u002Fcore\u003C\u002Fstrong>, the engine: element model, document &amp; history, geometry, hit testing, rendering and export. No framework code.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>@opendrawjs\u002Feditor\u003C\u002Fstrong>, the framework-free editor: tools, gestures, keyboard, the action registry, persistence. Mounts onto any DOM.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>@opendrawjs\u002Fnuxt\u003C\u002Fstrong>, the Vue\u002FNuxt adapter: \u003Ccode>&lt;OpenDraw \u002F&gt;\u003C\u002Fcode>, \u003Ccode>useOpenDraw()\u003C\u002Fcode> and the full editor UI.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>@opendrawjs\u002Freact\u003C\u002Fstrong> and \u003Cstrong>@opendrawjs\u002Fsvelte\u003C\u002Fstrong>, the React and Svelte 5 adapters.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Getting started\u003C\u002Fh2>\n\u003Cp>Install, register the module, and drop the component anywhere. It fills its container, so give the container a height:\u003C\u002Fp>\n\u003Cpre class=\"shiki taohq\" style=\"background-color:#201e25;color:#ece8f3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#ECE8F3\">npm \u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">install\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\"> @opendrawjs\u002Fnuxt\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre class=\"shiki taohq\" style=\"background-color:#201e25;color:#ece8f3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8A8494;font-style:italic\">\u002F\u002F nuxt.config.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B2A0D8\">export\u003C\u002Fspan>\u003Cspan style=\"color:#B2A0D8\"> default\u003C\u002Fspan>\u003Cspan style=\"color:#ECE8F3\"> defineNuxtConfig\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ECE8F3\">  modules\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\"> [\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">'\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">@opendrawjs\u002Fnuxt\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">'\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">})\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre class=\"shiki taohq\" style=\"background-color:#201e25;color:#ece8f3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">template\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">  &#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">div\u003C\u002Fspan>\u003Cspan style=\"color:#B2A0D8\"> style\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">=\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">\"\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">height: 100vh\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">\"\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">    &#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">OpenDraw\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\"> \u002F>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">  &#x3C;\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">div\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#A39DAD\">&#x3C;\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#C4B5E3\">template\u003C\u002Fspan>\u003Cspan style=\"color:#A39DAD\">>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>The module auto-imports the components and composables. Plain Vue 3 without Nuxt works too: \u003Ccode>import { OpenDraw } from &#39;@opendrawjs\u002Fnuxt\u002Fvue&#39;\u003C\u002Fcode>. The scene saves itself to \u003Ccode>localStorage\u003C\u002Fcode> and restores on reload, and a drawings sidebar keeps many drawings, each saved on its own.\u003C\u002Fp>\n\u003Ch2>Where to Find It\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Docs and demo\u003C\u002Fstrong>: \u003Ca href=\"https:\u002F\u002Fopendraw.taohq.org\">opendraw.taohq.org\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>GitHub\u003C\u002Fstrong>: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FTheAlphaOnes\u002Fopendraw\">github.com\u002FTheAlphaOnes\u002Fopendraw\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Cstrong>npm\u003C\u002Fstrong>: \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@opendrawjs\u002Fnuxt\">npmjs.com\u002Fpackage\u002F@opendrawjs\u002Fnuxt\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>MIT licensed. If you draw something with it, we&#39;d genuinely love to see it.\u003C\u002Fp>\n",1793498088113]