Structure Editor Integration (Ketcher)
Relevant source files
The following files were used as context for generating this wiki page:
The Structure Editor Integration provides a graphical interface for drawing and editing chemical structures within the cheMD platform. While the core of cheMD relies on SMILES strings for semantic representation, the integration with Ketcher allows users to perform per-bond manual geometry editing and visual manipulation of molecules.
This system is implemented as a bridge between the React-based web application and the Ketcher editor hosted within an iframe. It enables a bidirectional flow where structures from the document can be loaded into the editor, modified by the user, and then saved back as updated SMILES or Molfile data.
Sources: chemd-v0.1-architecture.md, apps/web/src/app/page.tsx:32-45
Architecture and Components
The integration follows a layered approach, separating the UI dialog, the iframe container, and the communication bridge.
Component Hierarchy
- KetcherDialog: A high-level modal component that wraps the editor. It handles the "Save" and "Cancel" actions and manages the visibility of the editor.
- KetcherFrame: Responsible for embedding the Ketcher application via an
<iframe>. It serves as the physical boundary between the cheMD app and the external editor. - useKetcherBridge: A custom hook that manages the
postMessagecommunication protocol between the host window and the Ketcher iframe.
The following diagram illustrates the relationship between these components and the main application state.
Data Flow and Communication
Communication with Ketcher is asynchronous and relies on a messaging bridge. Since Ketcher runs in a separate document context (iframe), the useKetcherBridge hook facilitates data exchange.
Loading and Saving Sequences
When a user opens the editor, the application passes existing structure data (SMILES or Molfile). Upon saving, the bridge requests the current molecule state from Ketcher in multiple formats to ensure both human-readable SMILES and coordinate-rich Molfiles are preserved.
Implementation Details
| Component/Hook | Key Responsibility | Implementation Note |
|---|---|---|
useKetcherBridge | Iframe synchronization | Uses useImperativeHandle to expose getSmiles and getMolfile methods. |
KetcherDialog | Save orchestration | Performs a POST request to /api/chem/structure/save before updating the source document. |
KetcherFrame | Asset Loading | Loads Ketcher from /ketcher/index.html. |
Sources: apps/web/src/features/structure-editor/hooks/useKetcherBridge.ts:10-40, apps/web/src/features/structure-editor/components/KetcherDialog.tsx:15-30, apps/web/src/app/page.tsx:200-215
Backend Integration and Persistence
When a structure is saved from the Ketcher editor, the web application performs a multi-step update process:
- Server-side Sync: The new structure is sent to a backend API (
/api/chem/structure/save) to be processed and validated. - Draft Store Update: The application saves the structure in a local "Structure Draft Store" to maintain session state and prevent data loss.
- Document Injection: The source Markdown in the editor is updated. If a
:::moleculeblock with the corresponding ID exists, it is updated; otherwise, a new block is inserted.
// Example of the save logic in apps/web/src/app/page.tsx
const response = await fetch("/api/chem/structure/save", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
documentId,
blockId: editingStructure.blockId,
sessionId,
...buildStructureSaveRequest(next)
})
});
Sources: apps/web/src/app/page.tsx:195-210, apps/web/src/app/page.tsx:218-228
Summary
The Ketcher integration enables high-fidelity chemical drawing while maintaining the "plain-text source of truth" philosophy of the cheMD project. By wrapping the editor in a managed bridge, the system ensures that complex manual edits are correctly serialized back into the semantic AST as SMILES and persisted via the structure draft system.
Sources: chemd-v0.1-architecture.md:215-230, apps/web/src/app/page.tsx:170-180