chemistry is a high-performance chemical structure rendering service within the Ф architecture. It generates on-demand SVG diagrams from SMILES strings, powered by RDKit. These diagrams are optimized for embedding in Markdown, HTML, and research platforms (social media, forums, and academic environments).
| Molecule | SMILES | Structure |
|---|---|---|
| Ethanol | CCO |
|
| Aspirin | CC(=O)OC1=CC=CC=C1C(=O)O |
|
| Caffeine | CN1C=NC2=C1C(=O)N(C(=O)N2C)C |
The chemistry API supports two primary integration scenarios.
You can use direct URLs with the config parameter to customize colors. This is ideal for PDFs, GitHub, Notion, or forums where you do not have control over the underlying code.
FFM provides native support for SMILES rendering. Simply use the smiles code block. You can test it at the Playground. For multiple images, list one SMILES string per line:
```smiles
CCO
CC(=O)OC1=CC=CC=C1C(=O)O
```
Use standard Markdown image syntax to embed structures:
OC1=CC=CC=C1C(=O)O>)Embed directly using the <img> tag:
<img
width="300"
alt="Aspirin"
src="https://chemistry.fuyeor.net/v1/depict?smiles=CC(=O)OC1=CC=CC=C1C(=O)O"
/>If you have full control over your website's source code, you can integrate chemical structure diagrams directly into the page using JavaScript. This approach enables dynamic rendering and lets you customize visual styles through CSS custom properties.
The following example fetches the SVG from the depict endpoint and inserts it into the DOM:
// Render SMILES chemical structure into DOM container
async function renderMolecule(smiles, containerId) {
const url = `https://chemistry.fuyeor.net/v1/depict?smiles=${window.encodeURIComponent(smiles)}`;
const res = await window.fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const svg = await res.text();
const container = window.document.getElementById(containerId);
if (container) container.innerHTML = svg;
}
renderMolecule("CCO", "molecule-container").catch(window.console.error);Once the SVG is injected, you can override the default atom and bond colors by targeting CSS variables. The variable names follow the pattern --smiles-{atom}, where {atom} is the lowercase element symbol (for example, c for carbon, n for nitrogen).
:root {
--smiles-c: #666;
--smiles-n: #29f;
}Security considerations
The SVG returned by the official Chemistry service is safe to use. If you have stricter security requirements, consider one of these alternatives:
● Render the structure as an
<img>element, which completely isolates the SVG content:const img = document.createElement("img"); img.src = `https://chemistry.fuyeor.net/v1/depict?smiles=${encodeURIComponent(smiles)}`;● Sanitize the SVG string before inserting it into the DOM. You can use the browser's built-in Sanitizer API or a library like DOMPurify.
Renders a chemical structure from a SMILES string or a common name.
Requirement: You must provide either
smilesorname, but not both.
| Parameter | Type | Required | Description |
|---|---|---|---|
smiles |
string | Conditional | A valid SMILES or Reaction SMILES string. |
name |
string | Conditional | A case-insensitive common name (e.g., "aspirin", "ethanol"). |
config |
JSON | Optional | Customization for background or atom/line colors. |
For detailed information, please refer to the API Documentation.
This project is licensed under the MIT License.
It utilizes RDKit, an open-source cheminformatics library licensed under the BSD 3-Clause License.
This repository has two independent publication paths. A normal push to main builds and pushes the backend image to the public GitHub Container Registry. The stable deployment image is ghcr.io/fuyeor/chemistry:latest; every build also receives an immutable commit tag such as ghcr.io/fuyeor/chemistry:sha-<commit> for rollback.
RDKit is released separately because its prebuilt toolchain changes much less frequently than the backend. Pushing a tag named rdkit-vX.Y.Z builds the RDKit C++ prebuild once, publishes the corresponding public OCI image ghcr.io/fuyeor/chemistry-rdkit:X.Y.Z, and creates a GitHub Release with the archive, manifest, and SHA-256 checksum. The RDKit release tag is intentionally separate from backend application versions.
docker pull ghcr.io/fuyeor/chemistry:latest
docker run --rm -p 30001:30001 ghcr.io/fuyeor/chemistry:latestFor a reproducible deployment, replace latest with the sha-<commit> tag printed by the GitHub Actions run. The backend Dockerfile pins the RDKit OCI image by version and digest. Updating RDKit is therefore a deliberate main-branch change after the corresponding rdkit-vX.Y.Z release has passed its archive and image checks.
For example, the Ubuntu 22.04 x86_64 prebuild for RDKit 2026.03.5 is downloaded from the chemistry Release asset below:
curl --fail --location --remote-name \
https://github.com/Fuyeor/chemistry/releases/download/rdkit-v2026.03.5/rdkit_2026_03_5_ubuntu_22_04_amd64.tar.gz
curl --fail --location --remote-name \
https://github.com/Fuyeor/chemistry/releases/download/rdkit-v2026.03.5/rdkit_2026_03_5_sha256.txt
sha256sum --check rdkit_2026_03_5_sha256.txt
mkdir -p "$HOME/rdkit"
tar -xzf rdkit_2026_03_5_ubuntu_22_04_amd64.tar.gz \
--strip-components=1 -C "$HOME/rdkit"The extracted tree keeps the Code/ and build/lib/ layout expected by build.rs and run.sh. Local builds can then use RDKIT_DIR="$HOME/rdkit" and LD_LIBRARY_PATH="$HOME/rdkit/build/lib".
Build and publish a new RDKit version only after the upstream release is available and the local build has been verified. The tag must use the exact form rdkit-vX.Y.Z, for example:
git tag -a rdkit-v2026.03.5 -m "chore: Release RDKit 2026.03.5 prebuild"
git push origin rdkit-v2026.03.5The tag workflow refuses to replace an existing Release. This keeps the archive, checksum, OCI image tag, and source commit immutable in practice. After the workflow succeeds, update the RDKit version and digest in Dockerfile.backend in a normal main commit, then let the backend workflow publish a new chemistry image.