A web app for practising organic molecule drawing and nomenclature. Draw a structure, get its IUPAC name from the Organic-Namer-Engine API, edit the structure, see the name update.
See Alkane-Implementation-Plan.md (one level up, alongside
Web-App-Requirements.md) for the full design and build order.
- React + TypeScript + Vite (scaffolded from the official
react-tstemplate) - Vitest for unit tests
- Custom SVG molecule editor — no diagramming library
- The molecule is a graph (
src/graph); SVG only renders it
npm install
npm run devnpm run dev— start the dev servernpm run build— type-check and build for productionnpm run lint— run ESLintnpm test— run the Vitest suitenpm run preview— preview the production build locally
/ is the React editor. Every other route is hand-written static HTML listed in
build.rollupOptions.input in vite.config.ts — it ships its own content and never
loads the app bundle:
| Route | File |
|---|---|
/ |
index.html (editor + crawlable copy below it) |
/about/ |
about/index.html |
The reason for the split: a Vite SPA ships an empty <div id="root">, and most LLM
crawlers and social scrapers do not run JavaScript at all. Anything that needs to be
read by a crawler therefore lives in the HTML source, not in React. On / that means
the site header, the prose below the editor and the footer are plain markup in
index.html; the editor mounts between them.
Adding a route means adding both an entry in vite.config.ts and a <url> in
public/sitemap.xml.
Shared styling for the static pages is src/site.css (linked directly, so it applies
without JavaScript). src/index.css styles the editor only.
robots.txt— allows everything, including the AI crawlers; points at the sitemap.sitemap.xml— every route, withlastmod. Submit in Google Search Console and Bing Webmaster Tools after a domain change.llms.txt— a plain-prose summary of the tool, its scope and its API, for LLM crawlers._headers/_redirects— Cloudflare Pages caching, security headers, and the www → apex redirect. The canonical host is the apex,https://thealkane.com; every page also declares<link rel="canonical">.- Brand images (
og.png,logo.svg, favicons, touch icons) are generated bytools/generate-images.py— edit that script and re-runpython3 tools/generate-images.pyrather than hand-editing the PNGs.
The point of all of the above is that content survives with JavaScript switched off:
curl -sA "Googlebot" https://thealkane.com/ | grep -c "IUPAC name generator"
curl -sA "GPTBot" https://thealkane.com/about/ | head -40
curl -s https://thealkane.com/sitemap.xmlEach should return real content, not an empty <div id="root">.