Render 2D chemical structures from SMILES, molfile, SDF, or reaction(rxn) in your notes, powered by RDKit.js.
Turn plain-text chemistry into pictures, right inside your notes. Write a SMILES string (or a molfile, SDF, or reaction) in a code block and Molren draws the 2D structure inline — powered by RDKit.js, running entirely on your machine.
Website: molren.amberlogica.com · Support: ☕ Buy me a coffee
Molren is for anyone who keeps chemistry in Obsidian — students, chemists, researchers, teachers — and wants their notes to show the molecules, not just spell them out. Your structures stay as searchable, version-controllable text; the drawing is generated on the fly, offline, with nothing uploaded.
In Obsidian: Settings → Community plugins → Browse, search Molren, then Install and Enable.
quiachonj/molren in the BRAT plugin.main.js, manifest.json, and styles.css from a release into <your-vault>/.obsidian/plugins/molren/, then reload Obsidian.[!IMPORTANT] Molren is desktop-only and requires Obsidian 1.4.0 or later.
Molren reads fenced code blocks and draws what's inside. The fence's language tag tells Molren what kind of input it is.
In any note, add a code block tagged smiles with one structure:
```smiles
CCO
```
Switch to Reading or Live Preview — Molren draws ethanol inline.
Edit the SMILES and the picture updates. That's the whole idea; everything below is more of it.
Put one SMILES per line for a responsive grid, and add a caption after the first space:
```smiles
CCO Ethanol
CC(=O)O Acetic acid
c1ccccc1 Benzene
```
Lines starting with # are comments, so you can annotate a block:
```smiles
# Common solvents
CCO Ethanol
CC(C)=O Acetone
```
Stereo bonds and R/S / E/Z labels are drawn automatically (toggle in Settings):
```smiles
C[C@H](N)C(=O)O L-alanine
```
Use a mol block for a single molfile — Molren keeps its authored coordinates. Use an sdf block for multi-record SDF — each record becomes a card, using its title line as the caption:
```mol
(paste the full molblock here, ending in "M END")
```
```sdf
(paste SDF records separated by $$$$)
```
Use a rxn block for reaction SMILES (reactants>>products, optionally reactants>agents>products). Reactions render as wide, full-width rows:
```rxn
CC(=O)O>[H+]>CC(=O)OCC Fischer esterification
```
chemA chem block auto-detects whether its contents are SMILES, a molfile, SDF, or a reaction — handy when pasting mixed content.
| Use this fence | When your input is… | You get… |
|---|---|---|
smiles |
one or more SMILES (one per line) | a single card or a grid |
mol |
a single molfile / molblock | one card, coordinates kept |
sdf |
an SDF file (records split by $$$$) |
a grid, one card per record |
rxn |
reaction SMILES (with >>) |
full-width reaction rows |
chem |
any of the above — auto-detected | the right result for the input |
[!NOTE] In
smilesandrxnblocks, text after the first space becomes a caption,#lines are comments, and a trailing CXSMILES|…|extension is kept as part of the structure. If a line can't be read, that block shows a small inline error (e.g.⚠ Molren: invalid SMILES: …) — one bad line won't stop the others.
New to SMILES? Copy the "Canonical SMILES" from a compound's PubChem or Wikipedia page, or draw a structure in a free editor (e.g. Ketcher) and export SMILES.
Settings → Community plugins → Molren:
| Setting | What it does | Default |
|---|---|---|
| Image width | Width each structure is drawn at (also the grid column width) | 350 |
| Image height | Height each structure is drawn at | 300 |
| Stereo annotations | Show or hide R/S and E/Z labels | On |
chem fence.fence (smiles│mol│sdf│rxn│chem)
│
▼
parse.ts → detect format, split into structure specs (+ captions)
│
▼
svg.ts → RDKit → SVG (molecules + reactions), theme recolor
│
▼
renderer.ts → layout (single│grid│reaction stack), cache, mount
| File | Responsibility |
|---|---|
src/main.ts |
Plugin entry — registers the smiles/mol/sdf/rxn/chem fences. |
src/parse.ts |
Format detection and parsing block text into structure specs. |
src/svg.ts |
Pure RDKit → SVG conversion (molecules + reactions) and theming. |
src/renderer.ts |
Obsidian/DOM bridge: layout, caching, and mounting. |
src/rdkit.ts |
Lazy, one-time RDKit wasm init from the inlined (base64) wasm bytes. |
src/settings.ts |
Settings tab (dimensions, stereo annotations). |
npm install # installs deps and pulls in the RDKit wasm
npm run dev # esbuild watch → main.js (wasm inlined)
npm test # vitest
npm run lint # eslint (incl. Obsidian plugin rules)
npm run format # prettier --write
npm run build # type-check + production bundle
npm run check # format:check + lint + test + build (what CI runs)
To develop against a real vault, symlink molren/ into a test vault's
.obsidian/plugins/, then reload Obsidian (Ctrl+R) after each build.
[!IMPORTANT] Molren is desktop-only (
isDesktopOnly: true) and targetsminAppVersion1.4.0, so it uses the classic settings-tab API rather than the declarative one from 1.13.
.wasm (~7 MB) is inlined into main.js as base64 (esbuild base64 loader), decoded with atob at load, and passed to initRDKitModule({ wasmBinary }). This is required because community-store and BRAT installs only download main.js/manifest.json/styles.css — extra release assets aren't fetched, so the wasm can't ship as a separate file.has_coords(), not by fence.#191919, annotations) plus O/N as CSS variables, so one cached SVG adapts to light/dark live.DOMParser + importNode (not innerHTML) per Obsidian's guidelines.@rdkit/rdkit types omit the reaction API and the CJS default export, so both are declared locally in src/rdkit.ts.MIT. RDKit.js is distributed under the BSD-3-Clause license.