How Dotlet was built,
what broke, and what changed.
A full account of building a vector creation tool — from the first idea to the final submission. Including the errors, the features that didn't make it, and what was learned along the way.
Try Dotlet liveDotlet is a browser-based vector creation tool. You place dots on a grid, they merge into smooth organic shapes in real time, and you export a clean SVG or PNG. No pen tool. No anchor points. No prior experience needed.
It was built for anyone who has ever had a clear idea for an icon, a logo, or a symbol — and then opened a design tool and immediately felt out of their depth. The gooey filter engine is the heart of it: an SVG feGaussianBlur and feColorMatrix pipeline that turns separate overlapping dots into one continuous organic shape, automatically, in real time.
Most vector design tools were built for people who already know how to design.
The pen tool, bezier curves, anchor points, node editing — these are skills that take weeks to learn before you can make something that looks intentional. That learning curve quietly keeps a lot of people out. Not because they don't have ideas. Because the tool asks for technical knowledge before it lets you be creative.
None of these people are missing creativity. They're missing a tool that meets them where they are. Dotlet was built to be that tool.
Before any spec was written, the Figma design agent was used to explore what this tool could feel like.
Side panel vs floating controls were compared visually. The floating palette direction was chosen — the canvas stays clear, controls appear when needed.
Name, color direction, and visual identity were all explored at this stage using the Figma agent — ahead of any code. The sticker-sheet color theme (blue #4A7FD4, soft sky background) came from extracting a reference image at this point.
Learning: doing this before locking a requirements document meant the FRD was grounded in layout decisions that had already been visually tested — not made in the abstract.
Writing a full Functional Requirements Document before opening Figma Make was the single decision that made everything else go more smoothly.
Most AI-assisted builds start with a vague prompt and iterate until something looks right. The FRD forced the opposite: define what the tool is, what it does, how it behaves, and what it will never do — before writing any code. Every Figma Make prompt that followed was specific because the spec was specific. The tool built what was actually meant, not what was accidentally implied.
The FRD began as an adaptation of an existing reference project — "Gooey Icon Builder." The project was renamed twice (Dottles, then Dotlet), and almost every concept in the original spec was reconsidered before being rewritten or replaced.
The scope was widened deliberately: from "icon tool" to "icons, logos, custom shapes, symbols, and decorative marks — anything that would otherwise require a path editor." The grid expanded from 3 presets to 5. The shape palette doubled from 4 types to 8. The entire vocabulary was replaced so that every term in the spec, the UI labels, and the code matched — no ambiguity between what the FRD said and what Figma Make built.
Most specs list what to build. This one also listed what not to build — and crucially, why. Every exclusion was written with a reason tied to the product's core premise. That reasoning became the test for every new feature idea that came up during the build.
Freeform path / bezier editing
Reintroduces the exact precision barrier the product exists to remove. If users need a pen tool, they already have a pen tool.
AI-generated shape input
Conflicts with a hands-on, skill-free creation model. The tool should respond to what the user places, not generate for them.
Raster image import
Outside the defined vector-first workflow. Dotlet creates from scratch — it doesn't convert or embed.
Animation / motion export
Dotlet is a static vector tool. Motion would require a second rendering pipeline with no connection to the gooey filter engine.
Governing principle — the product must not reintroduce a technical skill requirement at any stage of the workflow. This rule was written in the FRD before any code was written. It was used again when the Font Builder was evaluated — and it's why the Font Builder was eventually cut.
The FRD needed to become prompts that Figma Make could act on precisely. This step had its own learning curve.
First mistake — vague prompts produced inconsistent output
▾"Use less credits" appeared repeatedly throughout the build. Short, targeted prompts for isolated changes became the working habit — one feature at a time, not one giant request.
A reverse-engineered Figma Make output was used to match the expected prompt structure exactly. The FRD was translated into directives specifying exact values — corner radius ratios, exponential curve formulas, SVG namespace declarations — not descriptions of feel.
Features were built incrementally — each as its own scoped prompt rather than one large request. Click any stage to expand it.
The export pipeline was the most error-prone part of the build. Each problem was different — click to see the cause and fix.
Cross-cutting pattern: every export error was code that worked correctly in the live canvas context making different assumptions in the export context. The fix was always: stop duplicating logic, make export reuse the same source of truth as the canvas.
Exports now always capture exactly what is on the canvas — current Spread, Crispness, and Outline settings. If sliders are at zero, export is naturally crisp. One code path, one source of truth.
Figma's SVG importer ignores filter elements — a known Figma limitation. Workaround: render to PNG via the same canvas pipeline, encode as base64, embed in an SVG wrapper. The file has a .svg extension but the artwork is raster — Figma imports it and sees the correct gooey shape.
Two features were implemented and then cut — deliberately, and for different reasons.
A marching-squares + Catmull-Rom bezier tracing pipeline was built to convert the rendered gooey shape into real editable vector paths. A Font Builder mode was designed on top — draw each letter on the dot grid, export as a working .ttf font via opentype.js. The tracing worked in principle. The Font Builder did not reach a working state in the available time.
A full account system was designed and partially built — email OTP sign-in, canvas save and load, a file manager with per-file thumbnails. During implementation, real configuration problems appeared.
Figma Weave was used to generate the visual assets for the submission — keeping the creative workflow inside one platform.
Thumbnail — first attempt failed
The model hallucinated a fake design tool UI with nonsense text. Lesson: never ask an image model to render text or UI. Fix: described pure abstract visuals only ("organic blue blobs, no text, no UI") and added all text manually in Figma Design afterward.
Pixel art sun character
Generated with Google Imagen 4. Then animated with Kling 3 — subtle sun ray rotation, flowers swaying, clouds drifting. Iterated motion prompts to add a pixel art dinosaur running through the field as the primary motion subject.
Halftone dot art icon set
16 icons in a 4×4 grid, Ben-Day dot style on mint green. Generated with Ideogram V2. Animated with Kling 3 using a breathing/pulse motion — each icon gently expanding and contracting in staggered timing.
1-bit Mac OS bitmap portrait style
Explored as a visual direction — black and white only, checkerboard dithering, early Macintosh aesthetic.
Submission video assets
All promotional video elements assembled from the Weave workflow output — keeping Make (build), Weave (assets), and the design agent (ideation) as three distinct Figma tools in one submission.
Every stage that went well had one thing in common: the intent was made specific before the AI was asked to act on it. The FRD, the scope decisions, the precise build prompts — each of these worked because they removed interpretation before it could happen.
Every stage that hit problems had the opposite in common: something left vague, something assumed, something that worked in one context (the live canvas) and was copied rather than shared into another context (the export pipeline).
The two features that were removed — the Font Builder and the account system — both reflect the same instinct that shaped the product itself. It is better to do one thing well and honestly than to do more and deliver less of it.
Dotlet does one thing: it lets anyone make a vector graphic without needing to know what a bezier curve is. That part works. Everything else can come later.