# Project export: ChemSpec

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: A chemistry app for students and educators, demonstrating the steps of a reaction at both the molecular and observational level.
- Devpost: https://devpost.com/software/chemspec
- GitHub: https://github.com/charles-mills/ChemSpec
- Demo: https://charles-mills.github.io/ChemSpec/
- Video: https://www.youtube.com/embed/XxhLagRU2wY?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — Charles Mills (205 commits), oli-robbins (21 commits), Aryan Saini (15 commits), Patryk (6 commits)

## Devpost submission (written by the team)

### Inspiration

Chemistry education often relies on students memorizing complex chemical equations without ever witnessing the reactions themselves. Due to limited lesson time, curriculum constraints, and shrinking school budgets, teachers are unable to demonstrate many important experiments in the classroom. We wanted to bridge this gap by making chemical reactions more accessible, interactive, and memorable, giving every student the opportunity to see chemistry come to life regardless of their school's resources.

### What it does

ChemSpec is a chemical reaction simulator aimed at teachers and students from sixth grade up to early undergraduate level. ChemSpec allows students to gain an understanding of various chemical reactions at both the molecular and observational level with the molecular simulation and 3D view, respectively. Upon inputting validated reactants, the student can watch a step-by-step molecular simulation of all the changes made to the reactants, with accompanying explanations. After this, the student can then see that same reaction play out like in the classroom - no need for safety goggles! ChemSpec simulates the predicted observations in a realistic 3D viewer and plays them out for the student to observe. The program takes care to also show observations that are normally invisible to the human eye so students can understand every aspect of the reaction. We also employ Codex to go one step deeper in reaction verification and analysis. Where ChemSpec's algorithm is unable to verify the validity of a reaction, users have the option to pass it off to Codex, which confirms or denies the reaction with an accompanying explanation and simulation. Alongside this, once users have finished viewing the 3D simulation, through Codex, they have the option to learn more about various aspects of the reaction. When requested, Codex will describe the conditions required for the reaction to take place, where it occurs in nature and/or in industry, as well as its common uses.

### How we built it

We started with one important constraint: ChemSpec's core features should work without a stable internet connection. ChemSpec is a native Rust application built with Iced and wgpu, making it portable, light-weight, and accessible without an internet connection. We divided the app into three layers for parsing: chemical reasoning, rendering and AI integration. We built ChemSpec from the ground up using GPT 5.6 Sol. We began the project with a team-meeting discussing our intended outcome; once agreed, we handed off to a fresh thread, describing what we wanted to achieve and the components it would require. We requested Sol first ask us everything required to close out any assumptions, after which it was ready to write the implementation plan and specifications. Sol then worked through the stages it had specified. First, ChemSpec checks its brief reviewed reaction catalogue, then runs an algorithmic solver if the reaction is not present in this catalogue. The solver covers common reaction families and activity and solubility rules. If both paths decline, Codex can return a tightly constrained claim containing suggested products, conditions and observations. ChemSpec resolves and balances that claim locally before applying the same validation used for catalogue reactions. Atoms and molecules are represented as typed graphs. Each atom is stored as a node which contains its formal charge, number of unpaired/unbonded electrons, and its membership within a molecule. Reactions are represented as atomic graph transformations. The validation kernel checks that every atom is accounted for, charge and electrons are conserved, each bond or electron operation is legal, and the final molecular graphs match the products. Validated reactions are converted into renderer-independent frames containing the structural change. These frames create both a guided 2D molecular animation and a macroscopic 3D simulation. Playback is calculated from an absolute timeline and stable seed. Asynchronous work has generation IDs which allows ChemSpec to reject late Codex or validation results.

### Challenges we ran into

Our key issue was identifying the proper implementation and architecture for the app's supported reaction families. When we initially allowed Codex to determine this for us, we fell into a time-eating trap of hard-coded, heavily researched, and non-dynamic reaction types. Once we had identified this as a key bottleneck for the project, we simplified the requirements for new reactions, solving large families algorithmically and then deferring all families we do not support to Codex.

### Accomplishments we're proud of

Resolving thousands of reactions without requiring an internet connection or LLM, through an extensive and extendable resolver. Getting our native app working and on the web in its full form, still supporting thousands of reactions, and making it more accessible in the process. Creating a 3D simulation system that enables reactions to be accurately represented according to the state and colour of the reactants.

### What we learned

When we initially allowed Codex to design the reaction architecture without proper review of its output, we ended up in a time-trap of only permitting hard-coded, non-dynamic reaction types. We learned to be explicit about our intended architecture upfront, and ensure we were aligned with the model. Using Codex to make quick UI mockups, such as in HTML and CSS, working incrementally until we were happy with the design, was much faster than incrementing through Iced's compile-and-run cycle, and gave the model a clear approved reference to compare against.

### What's next

Organic structures have support for most reactions studied at high school/A-Level, however we aim to expand the scope of ChemSpec's organic branch to cover polymerisation as well as aromatic and carbonyl chemistry.

## README (from the GitHub repository)

# ChemSpec

ChemSpec is a chemistry exploration app built for the Education category of [OpenAI Build Week 2026](https://openai.devpost.com/). Learners construct a reaction question, follow its structural changes atom by atom, and then see a human-level 3D interpretation of the same outcome.

<img alt="the ChemSpec dashboard" src="https://github.com/user-attachments/assets/ee612b0e-f844-4865-9563-1e38ad9371e4" />

## Running ChemSpec

### Web demo

Open the [ChemSpec web demo](https://charles-mills.github.io/ChemSpec/) in a browser with WebGPU support. The demo excludes Codex integration and may not work on your device.

### Desktop app

Install the latest [release](https://github.com/charles-mills/ChemSpec/releases) for your platform.

### From Source

With [rustup](https://rustup.rs/) available, run the following: 

```sh
git clone https://github.com/charles-mills/ChemSpec.git
cd ChemSpec
cargo run -p chemspec-app
```

Local chemistry does not require an account or network connection. To use the LLM path, install the [Codex CLI](https://github.com/openai/codex), sign in with a ChatGPT account and relaunch ChemSpec.



## Detected evidence (automated analysis)

Indexed codebase: 187 recognized source files, 5145 KB.
- HTML (language) — detected in the code
- Python (language) — detected in the code
- Rust (language) — detected in the code
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (120 of 677)

```
.gitattributes
.github/workflows/ci.yml
.github/workflows/demo.yml
.github/workflows/release.yml
.gitignore
AGENTS.md
assets/README.md
Cargo.lock
Cargo.toml
catalogue/candidates/acid-base-neutralization/candidate.json
catalogue/candidates/acid-base-neutralization/evidence.json
catalogue/candidates/acid-base-neutralization/example.chems
catalogue/candidates/acid-carbonate-gas-evolution/candidate.json
catalogue/candidates/acid-carbonate-gas-evolution/evidence.json
catalogue/candidates/acid-carbonate-gas-evolution/example.chems
catalogue/candidates/alkaline-earth-water/candidate.json
catalogue/candidates/alkaline-earth-water/evidence.json
catalogue/candidates/alkaline-earth-water/example.chems
catalogue/candidates/covalent-combinations/candidate.json
catalogue/candidates/covalent-combinations/evidence.json
catalogue/candidates/covalent-combinations/example.chems
catalogue/candidates/oxygen-reactions/candidate.json
catalogue/candidates/oxygen-reactions/evidence.json
catalogue/candidates/oxygen-reactions/example.chems
catalogue/candidates/periodic-table-and-alkali-water/candidate.json
catalogue/candidates/periodic-table-and-alkali-water/evidence.json
catalogue/candidates/periodic-table-and-alkali-water/example.chems
catalogue/candidates/precipitation-silver-halide/candidate.json
catalogue/candidates/precipitation-silver-halide/evidence.json
catalogue/candidates/precipitation-silver-halide/example.chems
catalogue/candidates/README.md
catalogue/candidates/single-displacement-halogen/candidate.json
catalogue/candidates/single-displacement-halogen/evidence.json
catalogue/candidates/single-displacement-halogen/example.chems
catalogue/experience-registry.json
catalogue/oxygen-screening/oxygen.json
catalogue/reference/core-chemistry/catalogue.json
catalogue/reviews/core-chemistry.review.json
conformance/artifacts/.gitkeep
conformance/artifacts/artifact-boundary-001.input.json
conformance/artifacts/canonical-identity-001.domain.json
conformance/artifacts/canonical-identity-001.input.json
conformance/catalogue/.gitkeep
conformance/catalogue/alkali-metal-water-001.catalogue.digest
conformance/catalogue/alkali-metal-water-001.catalogue.json
conformance/catalogue/alkali-metal-water-001.input.json
conformance/catalogue/lithium-rule-001.catalogue.digest
conformance/catalogue/lithium-rule-001.catalogue.json
conformance/catalogue/lithium-rule-001.review.json
conformance/diagnostics-tooling/.gitkeep
conformance/diagnostics-tooling/stable-diagnostics-001.chems
conformance/encoding-layout/.gitkeep
conformance/encoding-layout/encoding-matrix-001.input.json
conformance/encoding-layout/nested-comments-001.chems
conformance/end-to-end/.gitkeep
conformance/end-to-end/alkali-water-family-001.input.json
conformance/end-to-end/alkali-water-k-001.chems
conformance/end-to-end/alkali-water-li-001.chems
conformance/end-to-end/alkali-water-na-001.chems
conformance/end-to-end/covalent-br-cl-brcl-001.chems
conformance/end-to-end/covalent-br-f-brf-001.chems
conformance/end-to-end/covalent-br-f-brf3-001.chems
conformance/end-to-end/covalent-br-f-brf5-001.chems
conformance/end-to-end/covalent-cl-f-clf-001.chems
conformance/end-to-end/covalent-cl-f-clf3-001.chems
conformance/end-to-end/covalent-cl-f-clf5-001.chems
conformance/end-to-end/covalent-h-br-hbr-001.chems
conformance/end-to-end/covalent-h-cl-hcl-001.chems
conformance/end-to-end/covalent-h-f-hf-001.chems
conformance/end-to-end/covalent-h-i-hi-001.chems
conformance/end-to-end/covalent-h-n-nh3-001.chems
conformance/end-to-end/covalent-h-s-h2s-001.chems
conformance/end-to-end/covalent-i-br-ibr-001.chems
conformance/end-to-end/covalent-i-cl-icl-001.chems
conformance/end-to-end/covalent-i-cl-icl3-001.chems
conformance/end-to-end/covalent-i-f-if-001.chems
conformance/end-to-end/covalent-i-f-if3-001.chems
conformance/end-to-end/covalent-i-f-if5-001.chems
conformance/end-to-end/covalent-i-f-if7-001.chems
conformance/end-to-end/ionpair-al-br-001.chems
conformance/end-to-end/ionpair-al-cl-001.chems
conformance/end-to-end/ionpair-al-f-001.chems
conformance/end-to-end/ionpair-al-i-001.chems
conformance/end-to-end/ionpair-al-n-001.chems
conformance/end-to-end/ionpair-al-p-001.chems
conformance/end-to-end/ionpair-al-s-001.chems
conformance/end-to-end/ionpair-ba-br-001.chems
conformance/end-to-end/ionpair-ba-cl-001.chems
conformance/end-to-end/ionpair-ba-f-001.chems
conformance/end-to-end/ionpair-ba-i-001.chems
conformance/end-to-end/ionpair-ba-n-001.chems
conformance/end-to-end/ionpair-ba-o-001.chems
conformance/end-to-end/ionpair-ba-p-001.chems
conformance/end-to-end/ionpair-ba-s-001.chems
conformance/end-to-end/ionpair-be-br-001.chems
conformance/end-to-end/ionpair-be-cl-001.chems
conformance/end-to-end/ionpair-be-f-001.chems
conformance/end-to-end/ionpair-be-i-001.chems
conformance/end-to-end/ionpair-be-n-001.chems
conformance/end-to-end/ionpair-be-o-001.chems
conformance/end-to-end/ionpair-be-p-001.chems
conformance/end-to-end/ionpair-be-s-001.chems
conformance/end-to-end/ionpair-ca-br-001.chems
conformance/end-to-end/ionpair-ca-cl-001.chems
conformance/end-to-end/ionpair-ca-f-001.chems
conformance/end-to-end/ionpair-ca-i-001.chems
conformance/end-to-end/ionpair-ca-n-001.chems
conformance/end-to-end/ionpair-ca-o-001.chems
conformance/end-to-end/ionpair-ca-p-001.chems
conformance/end-to-end/ionpair-ca-s-001.chems
conformance/end-to-end/ionpair-cs-br-001.chems
conformance/end-to-end/ionpair-cs-cl-001.chems
conformance/end-to-end/ionpair-cs-f-001.chems
conformance/end-to-end/ionpair-cs-i-001.chems
conformance/end-to-end/ionpair-cs-n-001.chems
conformance/end-to-end/ionpair-cs-o-001.chems
conformance/end-to-end/ionpair-cs-p-001.chems
conformance/end-to-end/ionpair-cs-s-001.chems
conformance/end-to-end/ionpair-k-br-001.chems
conformance/end-to-end/ionpair-k-cl-001.chems
[557 more files omitted for size]
```

### Dependencies

- crates/agent/Cargo.toml: chem-catalogue, chem-domain, chem-kernel, chems-lang, num-bigint, serde, serde_json
- crates/chem-catalogue/Cargo.toml: chem-domain, jsonschema, serde, serde_json
- crates/chem-domain/Cargo.toml: num-bigint, num-rational, num-traits, proptest, serde, serde_json, sha2
- crates/chem-kernel/Cargo.toml: chem-catalogue, chem-domain, chems-lang, jsonschema, num-bigint, serde, serde_json
- crates/chem-presentation/Cargo.toml: chem-catalogue, chem-domain, chem-kernel
- crates/chems-cli/Cargo.toml: chem-catalogue, chem-domain, chem-kernel, chems-lang, serde, serde_json
- crates/chems-lang/Cargo.toml: serde, serde_json, sha2
- crates/chemspec-app/Cargo.toml: agent, bytemuck@1.25.1, chem-catalogue, chem-domain, chem-kernel, chem-presentation, chems-lang, directories@6.0, fastrand, glam@0.25.0, iced, serde@1.0, serde_json@1.0, serde_json@1.0, web-time@1

### Recent commits (newest first)

- Fix failing tests
- Merge pull request #31 from charles-mills/finalchanges
- Bump 1.0.0
- added magnesium, other changes
- Fix the Windows gate?
- Merge pull request #30 from charles-mills/ask-codex
- molecules bounce
- Fix suggestion button gesture ordering
- Stream Prof. Codex chat responses
- Merge pull request #29 from charles-mills/ask-codex
- Nitrates show charges
- Add dropdown nav menu for reactions
- Place the info btn in the page header
- Make the chat interface nicer
- Cleanup the viewer
- fix windows failure
- Work on detonation
- Merge pull request #28 from charles-mills/simulationfixes
- molecularsim fixes
- Merge pull request #27 from charles-mills/fix-merged-conflict-markers

## Key source files (fetched from GitHub, selected and truncated for size)

### CONTRIBUTORS.md

```markdown
# Contributors

ChemSpec was built for the 2026 OpenAI Build Week, in a team of 4:

- Aryan Saini <vikram4king@googlemail.com>
- Charles Mills <charlesrjmills@gmail.com>
- Oliver Robbins <oliver.robbins11@gmail.com>
- Patryk Gutowski <patryktv198@gmail.com>

```

### CONTEXT.md

```markdown
# ChemSpec Domain Language

ChemSpec turns reaction requests into validated structural meaning and then
into an explanatory experience. These terms distinguish knowledge provenance
from runtime authority.

## Language

**Reference catalogue**:
Bundled local chemistry records used for identity reuse, factual provenance,
and fast-path derivation. Presence or absence never grants or denies permission
to validate, animate, or display chemistry.
_Avoid_: Trusted catalogue, approved catalogue, allow-list

**Reviewed**:
A factual-provenance label stating that a reference record received the
declared review. It is not a runtime capability or validation result.
_Avoid_: Trusted, approved, authorized

**Provisional**:
Structurally represented chemistry whose factual content is not a reviewed
reference record. It may become renderer-readable after identical deterministic
validation while retaining provisional provenance.
_Avoid_: Untrusted chemistry, review candidate

**Validated**:
A private capability produced by deterministic balance, identity, structure,
mapping, electron, and staleness checks. Only validated meaning may reach the
simulation.
_Avoid_: Trusted

**Unsupported**:
A typed outcome stating that the current deterministic and bounded fallback
paths cannot produce validated meaning. It describes capability, not catalogue
membership.
_Avoid_: Not approved, not allow-listed

```

### Cargo.toml

```
[workspace]
members = [
    "crates/agent",
    "crates/chem-catalogue",
    "crates/chem-domain",
    "crates/chem-kernel",
    "crates/chem-presentation",
    "crates/chems-cli",
    "crates/chems-lang",
    "crates/chemspec-app",
]
resolver = "3"

[workspace.package]
authors = [
    "Aryan Saini <vikram4king@googlemail.com>",
    "Charles Mills <charlesrjmills@gmail.com>",
    "Oliver Robbins <oliver.robbins11@gmail.com>",
    "Patryk <patryktv198@gmail.com>",
]
edition = "2024"
homepage = "https://github.com/charles-mills/ChemSpec"
license = "MIT"
repository = "https://github.com/charles-mills/ChemSpec"
rust-version = "1.96"
version = "1.0.0"

[workspace.dependencies]
fastrand = "2"
jsonschema = { version = "0.40", default-features = false }
iced = { version = "=0.14.0", features = ["canvas", "svg", "tokio"] }
num-bigint = { version = "0.4", features = ["serde"] }
num-rational = "0.4"
num-traits = "0.2"
proptest = "1"
rustix = { version = "1.1.4", features = ["process"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sha2 = "0.10"

[workspace.lints.rust]
missing_debug_implementations = "warn"
unsafe_code = "forbid"

[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }

[profile.dev]
# wgpu and Iced are unusably slow at opt-level 0; keep dependencies optimized.
opt-level = 1

[profile.dev.package."*"]
opt-level = 3

[profile.release]
lto = true
codegen-units = 1
strip = true

```

### crates/chem-presentation/Cargo.toml

```
[package]
name = "chem-presentation"
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
chem-catalogue = { path = "../chem-catalogue" }
chem-domain = { path = "../chem-domain" }
chem-kernel = { path = "../chem-kernel" }

[lints]
workspace = true

```

### crates/chems-lang/Cargo.toml

```
[package]
name = "chems-lang"
authors.workspace = true
description = "Lossless source frontend and formatter for .chems"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[lib]
name = "chems_lang"

[dependencies]
serde.workspace = true
serde_json.workspace = true

[dev-dependencies]
sha2.workspace = true

[lints]
workspace = true

```

### crates/chem-catalogue/Cargo.toml

```
[package]
name = "chem-catalogue"
authors.workspace = true
description = "Immutable reviewed chemistry facts and catalogue validation for ChemSpec"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
chem-domain = { path = "../chem-domain" }
serde.workspace = true
serde_json.workspace = true

[dev-dependencies]
jsonschema.workspace = true

[lints]
workspace = true

```

### crates/chem-domain/Cargo.toml

```
[package]
name = "chem-domain"
authors.workspace = true
description = "Exact values and stable chemistry types for ChemSpec"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
num-bigint.workspace = true
num-rational.workspace = true
num-traits.workspace = true
serde.workspace = true
serde_json.workspace = true
sha2.workspace = true

[dev-dependencies]
proptest.workspace = true

[lints]
workspace = true

```

### crates/chem-kernel/Cargo.toml

```
[package]
name = "chem-kernel"
authors.workspace = true
description = "Trusted typed elaboration and derivation kernel for ChemSpec"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
chem-catalogue = { path = "../chem-catalogue" }
chem-domain = { path = "../chem-domain" }
chems-lang = { path = "../chems-lang" }
num-bigint.workspace = true
serde.workspace = true
serde_json.workspace = true

[dev-dependencies]
jsonschema.workspace = true

[lints]
workspace = true

```

### crates/chems-cli/Cargo.toml

```
[package]
name = "chems-cli"
authors.workspace = true
description = "Command-line source, formatting, and expansion inspection for ChemSpec"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[[bin]]
name = "chems"
path = "src/main.rs"

[dependencies]
chem-catalogue = { path = "../chem-catalogue" }
chem-domain = { path = "../chem-domain" }
chem-kernel = { path = "../chem-kernel" }
chems-lang = { path = "../chems-lang" }
serde.workspace = true
serde_json.workspace = true

[lints]
workspace = true

```

### crates/agent/Cargo.toml

```
[package]
name = "agent"
authors.workspace = true
description = "Provider-neutral dynamic reaction construction for ChemSpec"
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
chem-catalogue = { path = "../chem-catalogue" }
chem-domain = { path = "../chem-domain" }
chem-kernel = { path = "../chem-kernel" }
chems-lang = { path = "../chems-lang" }
num-bigint.workspace = true
serde.workspace = true
serde_json.workspace = true

[target.'cfg(unix)'.dependencies]
rustix.workspace = true

[lints]
workspace = true

```

[136 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]