
I still remember the first time I looked into RTEs — confident, curious, and completely unaware of the rabbit hole I was about to fall into.
In my head, an RTE was just a fancy textbox with a toolbar. Maybe a text area with bold, italics and the occasional list. Nothing more.
But the moment I actually started working on one, that myth busted really quickly.
It’s a good reminder of something we, as engineers, often forget — we’re always beginners at something new.
I’m writing this blog to summarize my learnings so far. Hopefully, it helps someone looking to work on RTEs to get a gist of what an RTE really is and the challenges that come with it.
Oh, and by the way: RTE stands for Rich Text Editor, which can represent data in HTML, JSON or other formats, depending on how you want to play with your data.

Building an RTE isn’t just a task; it’s a journey.
How is working with an RTE different from an input field?
How is the data managed?
- In a multiline textbox, data is usually just a string.
- But when building a custom RTE, we need to decide how the data will look, be stored and served to the user.
- We need to think about all possible combinations users might create.
- And we need to handle the CSS that might come along with that data — quite possible, right? After all, we’re giving them formatting options.
A simple example:
<h2 style="text-align: center;"><strong>Hi there!</strong></h2>
So right from storing data, preserving spaces, saving CSS, and handling attributes — it’s all on us.
Wondering how the JSON for the above might look? Here it is:
{
"type": "doc",
"uid": "34d5dc2f6a55495d8aebf38a1ea72033",
"attrs": {},
"children": [
{
"type": "h2",
"attrs": {
"style": {
"text-align": "center"
},
"redactor-attributes": {
"style": "text-align: center;"
}
},
"uid": "d81a4b5214fc48f5b3181c00c27fe338",
"children": [
{
"text": "Hi there!",
"attrs": {
"style": {}
},
"bold": true
}
]
}
]
}
The above JSON, is just for one html line of code, can you imagine what it would look like for the actual real world data?🤔
Ohh and yes, this is the same data we might need to look into in case of failure/errors.
Interestingly complex elements
In an RTE, two elements that really make things interesting are images and tables.
They’re total game changers for content writers, making the content look rich, structured and honestly, just better.
But behind all that good-looking stuff is where the real engineering challenge lies — how efficiently you handle their data.
Images
Images aren’t just simple blocks dropped into text.
There’s so much that goes behind the scenes!
You need to keep track of how they’re resized, how they’re aligned, their captions, alt text and even whether they’re inline or block-level.
So every time a user drags that little resize handle or centers the image, your RTE has to capture, update, and store all of it perfectly.
Tables
Tables take things up another notch.
Each cell can have completely different content — a paragraph, an image, a list, maybe even a nested table (because why not?).
And every action inside that table, from merging cells to moving the cursor between them, needs to be handled gracefully without breaking the structure.
It’s these “small” things that really separate a basic RTE from a great one.
HTML standards and protocols
When dealing with RTE data, we also need to ensure that it complies with HTML standards and protocols — invalid markup can easily creep in, and browsers don’t always interpret it the same way.
Consider this example:
<p>
<h4>Hi</h4>
<a href="/link">Link here</a>
<p>Bye</p>
</p>
What do you think? Is the HTML above valid?
Yes? No? Skeptical?
In either case, how would you:
- Store this data?
- Manage invalid inputs?
Keeping your RTE aligned with web standards helps maintain predictable rendering and prevents broken layouts or corrupted content structures.
Complex selection logic

Take the snippet above — it contains multiple paragraphs, an anchor link and text selections spread across elements.
Now, what happens if the user applies another formatting option, like italics, to that selection?
We need to ensure that our JSON structure (in case of a JSON-based RTE) accounts for such scenarios and handles them gracefully.
Custom behaviors for elements
One of the most common examples here is the Tab key.
- In paragraphs → it indents text
- In tables → it moves selection to the next cell
- In lists → it creates a sublist (nesting)
And we need to handle all of these cases — and many more.
Real-world problems
Copy–Paste
Ah yes, the engineer’s favorite —- copy code from Stack Overflow or ChatGPT and paste!
In this case, our RTE should be able to:
- Interpret the source of the copied content
- Detect anomalies in the snippet
- Fix them and display the result correctly
Undo–Redo
How can any RTE not support the most basic operation of all? (And yet, it’s not as simple to implement as you’d think!)
Performance
With all the heavy HTML, frequent formatting and rendering, we must ensure:
- Minimal re-renders
- Quick formatting operations
- No visible lag for the user
Enhancements appreciated
Drag and drop (DnD)
Imagine having loads of data and not being able to drag and drop when needed. What a nightmare!
We must ensure that when the DnD operation completes, the correct JSON/HTML structure is formed — else the entire data could get corrupted.
Floating toolbars
A simple yet powerful enhancement — when a user selects text, show a relevant toolbar with actions they can perform.
It makes a content writer’s life so much easier.
Pro tip 💡
Remember: The data entered in your RTE might not be used immediately. It can also be manipulated downstream by the user or other systems.
So make sure that any changes you make to your code don’t unintentionally break someone’s CSS or structure.
💬 Fun fact:
By now, you might have guessed — this very blog was drafted on an RTE! 😄
Google Docs? Confluence? Custom built?
Final Takeaway
RTEs are deceptively tricky, part text field, part layout engine, part magician. But once you understand their quirks, they become surprisingly fun to work with.
So read the docs, keep a sandbox ready, and learn from other editors. And most importantly, don’t let that innocent-looking toolbar fool you again.😀
Shreya Kamble is a Software Engineer II at Contentstack. Follow her on LinkedIn here.




