Scientific Editor

The Zemna.AI Scientific Editor is a Tiptap-based rich text editor built for academic writing. It includes LaTeX equation support, automatic saving, version history, and publication persistence via the Ring Platform database layer.

Status: Phase 2 (Sprints 2.1–2.3) complete. Figure/table support and export are planned for Sprints 2.4–2.5.


Overview

FeatureDescription
Rich textHeadings (H1–H6), bold, italic, underline, lists, block quotes, code blocks, tables, links, images
LaTeXInline and display math via KaTeX; equation modal with live preview and templates
Auto-save30-second debounced save; first save creates a publication, then updates via PUT
Version historySnapshot and restore versions; list versions with timestamps and optional summaries
PublicationsContent stored as Tiptap JSON; load by URL ?id=... or create new

Editor Features

Rich Text (Tiptap)

The editor uses Tiptap with StarterKit and extensions for scientific writing:

  • Formatting: Bold, italic, underline, strikethrough, superscript, subscript, highlight
  • Structure: Headings H1–H6, ordered/unordered lists, block quotes
  • Blocks: Code blocks (syntax highlighting via lowlight), tables (rows, columns, header)
  • Inline: Links, images (placeholder support)
  • Typography: Smart quotes and typography improvements

Content is stored as Tiptap JSON in the publication content field; the editor accepts initial content as either HTML string or JSON for loading saved publications.

LaTeX Equations

  • Block math: Insert display-mode equations via the toolbar (Calculator icon) or equation modal.
  • Rendering: KaTeX renders equations in the editor; click to edit opens the equation modal.
  • Modal: LaTeX textarea, display/inline toggle, live preview, template buttons (fraction, sum, integral, matrix), Insert/Cancel.

Equations are stored as custom Tiptap nodes (mathBlock) with latex and display attributes.

Auto-Save & Publications

  • New document: No ?id= in URL; first Save or first auto-save creates a publication via POST /api/publications and sets the publication id for subsequent saves.
  • Existing document: Open with ?id=<publicationId>; the page loads the publication and sets title and content (JSON). Auto-save and manual Save use PUT /api/publications/:id.
  • Debounce: Changes to title or content trigger a 30-second debounced save; manual Save triggers an immediate save.
  • Save indicator: Toolbar shows "Saved" with timestamp when the last save completed successfully.

Version History

  • Panel: Version History button in the toolbar opens a dialog listing versions (version number, date, optional summary).
  • Snapshot: "Save snapshot" creates a new version with the current content (optional change summary).
  • Restore: "Restore" on a version updates the publication content to that version and refetches the editor; the panel closes and the editor shows the restored content.

Architecture

Publication schema

Publications and versions use the Ring Platform database abstraction (PostgreSQL with JSONB):

  • publications: id, data (JSONB), created_at, updated_at.
    data holds: user_id, title, content (Tiptap JSON), status, template_id.
  • publication_versions: id, data (JSONB), created_at, updated_at.
    data holds: publication_id, version_number, content, change_summary, created_by.

Schema is defined in data/schema.sql; the PostgreSQL adapter has fieldMappings for both collections.

Save flow

sequenceDiagram
  participant User
  participant Editor
  participant useAutoSave
  participant API
  participant DB

  User->>Editor: Edit content / title
  Editor->>useAutoSave: touch(publicationId, payload)
  useAutoSave->>useAutoSave: Debounce 30s
  Note over useAutoSave: Timer fires
  useAutoSave->>API: POST /api/publications (new) or PUT /api/publications/:id
  API->>DB: create() or update()
  DB-->>API: publication
  API-->>useAutoSave: 200 + publication
  useAutoSave->>Editor: onFirstSave(id) if new
  useAutoSave->>Editor: lastSaved updated

Version history flow

sequenceDiagram
  participant User
  participant Panel
  participant API
  participant DB

  User->>Panel: Open Version History
  Panel->>API: GET /api/publications/:id/versions
  API->>DB: findByField(publication_versions, publication_id, id)
  DB-->>API: versions[]
  API-->>Panel: versions

  User->>Panel: Restore version V
  Panel->>API: POST /api/publications/:id/versions { action: 'restore', versionId: V }
  API->>DB: updatePublication(id, content from V)
  DB-->>API: publication
  API-->>Panel: 200
  Panel->>User: onRestore() → refetch publication, set editor content

API routes

MethodPathDescription
GET/api/publicationsList current user's publications
POST/api/publicationsCreate publication (body: title, content, status, template_id)
GET/api/publications/[id]Get publication (ownership checked)
PUT/api/publications/[id]Update publication (ownership checked)
DELETE/api/publications/[id]Delete publication (ownership checked)
GET/api/publications/[id]/versionsList versions for publication
POST/api/publications/[id]/versionsSnapshot (action: snapshot) or restore (action: restore, versionId)

All routes require authentication; ownership is enforced for get/update/delete and versions.


Key files

AreaPath
Editor pageapp/(authenticated)/[locale]/editor/page.tsx
Scientific editorcomponents/editor/scientific-editor.tsx
Toolbarcomponents/editor/editor-toolbar.tsx
LaTeX extensioncomponents/editor/extensions/latex-extension.tsx
Equation modalcomponents/editor/equation-editor.tsx
Version history panelcomponents/editor/version-history-panel.tsx
Auto-save hookhooks/use-auto-save.ts
Publication typesfeatures/publications/types/index.ts
Publication servicefeatures/publications/services/publication-service.ts
API routesapp/(public)/api/publications/
Schemadata/schema.sql

Usage

Opening the editor

  • New publication: Go to /editor (or /[locale]/editor). The editor loads with the default scientific template; publication id is set on first save.
  • Existing publication: Go to /editor?id=<publicationId>. The page fetches the publication and sets the title and content (Tiptap JSON) in the editor.

Saving

  • Manual: Click Save in the toolbar. For a new document this creates a publication and sets the id; for an existing document it updates via PUT.
  • Auto-save: After 30 seconds without further changes, the current title and content are saved automatically (POST for new, PUT for existing).

Version history

  1. Click Version History (History icon) in the toolbar.
  2. Use Save snapshot to create a new version with the current content.
  3. Use Restore on a version to set the publication content to that version and reload the editor.
Tip

Restore does not delete versions; it updates the publication content and leaves the version history intact.


Roadmap (Phase 2 remaining)

  • Sprint 2.4: Figure upload component, table editor enhancements, cross-reference extension, FileService integration for images.
  • Sprint 2.5: Export (PDF, Word, Markdown) services, export dialog, export button and shortcut.

See Phase 2: Scientific Editor Enhancement for the full sprint breakdown.