DEV Community

Cover image for From Correct to Polished: What Changed in Strokeline
Saif Jlassi
Saif Jlassi

Posted on Edited on

From Correct to Polished: What Changed in Strokeline

In my last post, I described Strokeline as working, but not pro yet.

At that point, I had a clear list of things I wanted to improve: better motion, better rendering, better text placement, more reliable export, and eventually a better authoring experience.

That post was mostly a plan.

This one is about what actually happened.

A lot of the work ended up being less about adding visual effects and more about fixing the fundamentals underneath them: geometry, timing, rendering consistency, and giving both humans and AI a reliable way to write valid Strokeline scripts.

The biggest lesson so far is pretty simple:

Polish is mostly engineering.

The renderer became diagram-aware

One of the biggest changes was making the renderer understand more about what it is actually drawing.

Tables are a good example.

Previously, getting a table on screen was not enough. The text needed to sit comfortably inside the cells, columns needed to give longer content room before wrapping, and the table needed to look like one coherent object.

Tables now have better padding, automatic column widening before wrapping, rounded corners, header styling, soft shadows, and optional divider sections between attributes and operations.

That same idea applies to shapes.

Shapes now support rounded corners and better centered, auto-fitting labels. I also added a DIAMOND shape for flowcharts.

But arrows were probably the more interesting problem.

An arrow shouldn't simply draw a line from coordinate A to coordinate B. It needs to understand the shapes it connects.

The renderer now clips arrows to the actual shape boundary, spreads anchors when multiple arrows connect to the same side, and uses straighter lines with rounded elbows.

That makes a surprisingly large difference.

Then came UML-specific details: hollow triangles, hollow and filled diamonds, open arrowheads, multiplicities, and labels on both ends of relationships.

For example, a relationship can now carry information like:

SOURCELABEL "1"
TARGETLABEL "*"
Enter fullscreen mode Exit fullscreen mode

Those labels also get automatic background plates so they remain readable over the diagram.

Self-message loops are supported too, which matters for sequence diagrams where an object can send a message back to itself.

The important part is that these aren't isolated visual additions.

Arrow geometry depends on knowing the shape boundary. Label placement depends on knowing the arrow geometry. Readability depends on knowing where the label lands. Multiple arrows depend on knowing which side of the shape they share.

Fixing one piece exposed problems in the next.

That's what I mean by the renderer becoming diagram-aware. It isn't just drawing primitives anymore. More of the rendering logic understands the relationships between those primitives.

Preview and export have to agree

Another lesson was that a preview that looks good is not enough.

If the preview and exported video use different rendering paths, eventually they disagree.

Strokeline now renders with a crisp high-resolution 2x canvas, and exports use the same renderer and visual rules as the preview.

Video export is also deterministic rather than depending only on real-time screen capture.

That matters because an animation editor should not effectively say:

"It looked right while you were watching it, hopefully the recording looks the same."

GIF export gave me a particularly good example of this.

I had a bug where exported GIF frames could come out black or empty. The underlying problem wasn't the animation itself. The frames were being handled at the wrong stage of the rendering/downsampling process.

The fix was to render each frame at the logical canvas size first and then downsample it.

That sounds like a small implementation detail.

It wasn't small from the user's perspective.

A perfect-looking preview followed by an empty GIF is simply a broken export.

Sequence-diagram frames and use-case boundaries also received cleanup, while camera motion and easing became smoother and more stable. Tables and arrows now have smoother reveal animations as well.

I'm still treating preview/export consistency as an area that needs testing. In particular, I haven't verified the stronger claim from the previous post that old scripts remain pixel-identical, so that's still an open item rather than something I'm going to pretend is solved.

Narration changed the architecture of timing

In the previous post, I deliberately said I was skipping voice-over and subtitles for the time being.

That didn't last.

Once narration became part of the product, it became obvious that captions, speech, and animation timing can't really be treated as separate systems.

Consider a SAY line.

It has a duration declared by the script, but the text itself also has a natural reading time. If I only use the declared duration, a long sentence can finish visually before there is enough time to read or hear it.

Strokeline now schedules a SAY using whichever is longer: its declared duration or a text-based estimate.

That timing then needs to drive the caption.

And the caption needs to represent the entire spoken text. Long captions now advance through the full text instead of getting stuck showing only the first couple of wrapped lines.

Then there is generated audio.

The audio needs to line up with that same timeline. If the caption says one thing while the generated narration is at another point, the system feels broken even if both pieces work individually.

So generated audio is now synchronized with the actual caption timeline.

Seeking and playback timing were also improved, making audio less likely to skip or end abruptly. Pausing the preview now pauses the narration state as well.

This is still ongoing work. I'm not claiming that every browser audio edge case is solved.

But the architectural lesson is clear:

If two things describe the same moment in the animation, they need to share the same timing model.

AI needs a source of truth

Another part of Strokeline that changed wasn't the renderer at all.

It was how scripts get written.

Because Strokeline is text-based, it's natural to ask an AI to generate a .wbs file.

That also creates a very predictable problem: an AI can confidently invent syntax.

It might produce YAML. Or JSON. Or Mermaid. Or PlantUML. Or some imaginary hybrid that looks reasonable but has nothing to do with the actual Strokeline parser.

That's not useful.

So I built a public Strokeline skill repository:

Strokeline-Skills

The skill contains the actual core instructions, syntax references, diagnostics, layout guidance, quality checks, bad/good examples, patterns, and complete example scripts.

The important part is that the examples are validated against the real parser/compiler/validator.

The workspace's Copy AI Prompt now tells assistants to use this skill before generating or editing Strokeline scripts.

That gives an AI something much better than a vague description of the product: an actual source of truth.

The skill also documents details that are easy for an AI to get subtly wrong.

For example, CANVAS takes width and then height. POSITION represents the center point of an object. Vertical layouts need to respect safe areas.

These details sound obvious once you know them.

They're exactly the kind of details an AI will happily get wrong if nobody gives it authoritative instructions.

The goal isn't to make AI magically understand Strokeline.

The goal is to give it enough real information that the output has a chance of being executable on the first pass.

A small UI cleanup

I also cleaned up the surrounding workspace.

The landing page now has a darker shadcn-style design with stronger hierarchy, refined cards, spacing, and motion.

Inside the workspace, menus such as Scenes now appear above the preview instead of getting clipped behind it.

It's not the main story, but the editor shouldn't get in the way of the thing you're actually building.

What's still unfinished

Strokeline is in a much better place than when I wrote the previous post, but there are still plenty of open problems.

I haven't finished proving compatibility with existing scripts at the pixel level. Audio behavior still needs continued work across different browser conditions. And the renderer still has plenty of room for refinement as more complicated diagrams expose new geometry and timing cases.

I'm also deliberately not calling every item from the original roadmap finished just because related work happened. Some of those ideas still need proper implementation and validation.

Right now, my focus is on making the existing pipeline more reliable and predictable rather than piling on effects.

The pattern I've started to see is that every layer affects the next one.

Better geometry improves animation.

Better timing improves narration.

A shared renderer improves export.

A real syntax reference improves AI-generated scripts.

And when those foundations are right, visual polish becomes much easier to build on top of them.

That's a much more useful definition of "polished" than adding more effects.

What would you want a scriptable diagram animation tool to get right before anything else: rendering, animation, narration, export, or AI authoring?

Strokeline studio: https://strokeline.glassisaif.workers.dev/

Strokeline AI skill repo: https://github.com/laakri/Strokeline-Skills

Top comments (0)