Skip to content
Hooney
한국어
Products

Modules

editors

I built editors for comments, articles, documents, and translation, with a Lexical foundation and features that can be added as needed.

4Editing surfaces sharing one core: short input, body, document, and translation

Period
2024.04 ~ Present
Organization
Firstage
Role
Design and implementation (solo)
Runs on
Frontend · Backend
Key features
Comment, article, document, and translation editors are built from only the features each one needs. Several people can edit at once, and content can be rendered on the server.
Work and results
  • 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
  • Lexical
  • Yjs
  • React

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.