editors
A family of four editing surfaces, from short comments to translation, that share one editing core (built on Lexical) and pluggable features.
4Editing surfaces sharing one core: short input, body, document, and translation
- 2024.04 ~ Present
- Firstage
- Design and implementation (solo)

Core value
New writing screens and other products don't build an editor of their own; they pick the features they need on the shared core.
Outcomes
- Powers photo comments, journals, and record bodies in Journey
- ROUND reuses IntlEditor as is to edit event guides in several languages
- The chat composer and the web page builder run on the same core
- Real-time co-editing (Yjs) and server rendering were added without changing the core
Tech stack
Context
Firstage’s Journey app has writing surfaces of very different kinds, from short photo comments to diaries and record bodies. Separate editors for each screen would give each its own storage format and editing behavior, so I built an editor family that adds only the features each surface needs on a shared editing foundation. The package started in April 2024 in the same repository.
Decisions and implementation
- I first built a Markdown editor with Remirror, which is based on ProseMirror, tried Slate as well, and then chose Lexical. A small core with features moved into plugins suited keeping several editing surfaces working together.
- Four surfaces, short input (Plaintext), body text (Richtext), documents (Root), and translation (Intl), share a React-free core and plugin layer. Dependencies run one way, surfaces on plugins and plugins on the core, and a plugin never imports a surface.
- Yjs collaborative editing and DOM-free server rendering attach without changes to the core. The server imports only the headless entry points to render stored documents as HTML.
- Features that need outside data, such as mentions, image upload, and link previews, run on functions the host injects. Without a function, the related action is turned off and nothing pretends to save, and the host is responsible for authorization, storage, audience scope, and the save status it shows.
Current state
Photo comments, diaries, and record bodies in the Journey app use these packages. ROUND, a sports event service in the same monorepo, reuses IntlEditor as is to edit event guides in several languages, and the chats composer and the web page builder (cms) run on the same core. Moving the existing Root editor’s plain-text and rich-text paths onto the new shared base (EditorRoot) and verifying compatibility is still open.
