ยท Sasha Zverev
From Quill to PlateJS: How AI Agents Supercharged Our Editor Migration and Saved My Sanity
Switching editors can be a headache, but our move from Quill to PlateJS revealed unexpected challenges. Learn how coding agents revolutionized our workflow, from converting stubborn Tailwind styles to wrestling with Rust bindings, proving their worth for repetitive tasks and complex refactors.

From Quill to PlateJS: How AI Agents Supercharged Our Editor Migration and Saved My Sanity
At Yaranga, we embarked on a mission to upgrade our text editor, transitioning from Quill to PlateJS. Our goal was clear: a more powerful editor with unparalleled flexibility for feature extensions. What seemed straightforward on the surface quickly revealed its complexities, touching three core areas:
- ๐ผ๏ธ UI and the Editor Itself: PlateJS offers a rich set of pre-built components, but they all demanded custom styling to align with our brand.
- ๐พ Data Storage Format: Our product integrates with numerous platforms, necessitating robust converters between HTML, Markdown, and our internal editor format. We also needed to parse editor text to extract crucial data like dates and tasks.
- ๐ Data Synchronization: We rely on Yjs a CRDT (Conflict-free Replicated Data Type) library, to seamlessly synchronize content between our client and server.
The Easiest Win: Migrating Styles with Coding Agents
PlateJS components come pre-styled with TailwindCSS. The problem? We don't use Tailwind in our project, and importing it caused havoc with our existing layouts. This was a perfect job for a coding agent!
Here's how I tackled it:
- Tailwind to SCSS Migration Guide: I prompted an agent to generate a Tailwind to SCSS migration guide based on our existing codebase. It analyzed our styles and accurately mapped SCSS equivalents for most variables.
- Component-by-Component Conversion: I then began migrating components individually, using a prompt like: "Review new added files in UI and convert from Tailwind, follow instructions from frontend/src/styles folder."
While there were a few minor hiccups, this process saved an incredible amount of time. It was during this phase that I truly grasped a critical insight: not all coding agents are created equal.
At their core, most agents are sophisticated prompts for reasoning models. But their real power lies in their integrations. I used JetBrains Junie, and its seamless integration with Git was a game-changer. When I mentioned "new files," it understood exactly what I meant. This out-of-the-box functionality was crucial for my workflow. (While Gemini might offer similar capabilities, I found Junie's immediate usability a significant advantage).
Next Hurdle: Tackling the Yjs Synchronization Layer
Yjs is a JavaScript library, but our backend is in Kotlin. Luckily, a Rust port of Yjs, called y-crdt, exists. The less fortunate news? No robust Kotlin bindings. So, I took matters into my own hands and wrote planerist/ykt.
My initial version of ykt was a patchwork of copied code from ywasm (part of y-crdt project) โ a "fingers crossed" approach that surprisingly kinda worked.
If you're looking for Kotlin or other uniffi-supported language bindings fro y-crtd, please consider contributing to ykt!
During the migration, we hit a peculiar snag: y-crdt was serializing attributes as strings. PlateJS, however, is strict about data types. For example, "true" (a string) caused issues; it needed to be true (a boolean).
Patching y-crdt was a daunting prospect. The codebase is dense, and idiomatic Rust can be tough to parse. I just couldn't bring myself to start... until I remembered my secret weapon: coding agents.
I decided to try one, and the results were nothing short of amazing.
How Junie Saved Me (and the Rust Community ๐ )
I gave Junie this task:
update Xml insert_attribute & other methods to accept not only string but Any, see text.rs for example
Here's what it did:
- Made the necessary code changes โ almost on the first try.
- Proposed and added tests.
- Compiled the project and fixed the errors (!!).
- Did it all inside my IDE โ seamlessly integrating with my familiar workflow.
99% of the resulting Pull Request was written by Junie. It was a true lifesaver.
Converters: Manual, But With Intelligent Assistance
While I wrote most of the converter logic manually, there were times when I simply gave up and asked the agent to fix an error. This led to a key insight: sometimes we overcomplicate things. There were moments when I assumed a problem would require a massive refactor, only for the agent to offer a simple, brute-force solution.
Was it perfect? No. But:
- โ It worked.
- โ The tests passed.
Yes, I'll refactor it someday. But for now, "good enough" was exactly what we needed. And that's precisely the kind of pragmatic output agents can provide.
When Coding Agents Truly Shine: My Takeaways
Coding agents are most effective when:
- You have a lot of repetitive, detail-oriented work.
- The changes are small and localized.
- You need a kickstart to writing something โ even if it's imperfect, seeing something on the screen can spark your own creativity.
Why I Believe Junie Stands Out
I also experimented with Gemini, but Junie ultimately won me over:
Feature | JetBrains Junie | Gemini |
---|---|---|
Execution & Testing | โ Runs compilation & tests | ๐ซ No test execution (or unclear how) |
Git Integration | โ Understands Git structure | ๐ซ Weak Git integration |
IDE Integration | โ Works inside IDE | ๐ซ Needs setup & separate UI |
Project Context | โ Aware of project context | ๐ซ No understanding of your codebase |
Perhaps Gemini can do all of these things, but as a user, the out-of-the-box experience and seamless integration of Junie were unparalleled.
In Summary
Our PlateJS migration was tougher than anticipated. However, thanks to the invaluable assistance of coding agents, I was able to:
- Write Rust bindings.
- Fix y-crdt.
- Migrate styles from Tailwind.
- And, most importantly, stay sane ๐ .
If you're facing migrations, refactors, or any other tedious, repetitive tasks, give Junie a try โ especially if you're already using JetBrains IDEs.
What are your experiences with coding agents? Have they saved you from any coding headaches?