Rust engines
How the invitation design engine and the studio engine are built, shipped and kept honest.
For: Developers
Why Rust
The arithmetic must be identical in a browser, an AI call and a test, and heavy maths should not weigh down the page. Both engines are small Rust crates compiled to WebAssembly and loaded lazily.
| Engine | Crates | Browser package | Artifact |
|---|---|---|---|
| Studio (hall, thermal, catering, risk, checklist) | crates/studio-core, studio-wasm, render-core | @ariya/studio | public/wasm/ariya_studio.wasm |
| Design (invitation editing) | crates/design-core, design-wasm | @ariya/design | public/wasm/ariya_design.wasm |
The pattern
- A pure core crate owns the model and operations (serde with camelCase fields; enum variant fields need
rename_all_fields). - A thin wasm crate exposes a C-ABI:
ariya_design_alloc,ariya_design_freeandariya_design_call. JSON goes in, JSON comes out. - Failures are returned as data (
{ ok: false, code, message }), never a panic across the boundary. - Types are generated from Rust with
ts-rsintopackages/*/src/generated(excluded from Prettier). - A TypeScript package wraps the wasm and falls back to a TypeScript implementation if loading fails, so a failed load never blanks the page.
- The compiled
.wasmis committed and built deterministically with--remap-path-prefixbyapps/web/scripts/build-wasm.mjs.
Design engine operations
Add shape, add layer of a kind, add image, duplicate, stacking order, align and distribute, import a card, remove the card, ensure the entry seal, fast resize (minimum width 5%, height 1%) and rotation snapping.
Keeping it honest
- Rust unit and integration tests, including a fixture design (
tests/fixtures/house.json). - A TypeScript/Rust parity test (
engine.parity.test.ts) runs the same operations on both and compares normalised results. - CI checks that the committed wasm equals a fresh build, and that regenerated types equal the committed ones.
- The studio's parity corpus has 693 cases for geometry.
Rebuilding
cd apps/web && node scripts/build-wasm.mjs # builds both targets
cargo test --workspace # Rust testsNext phases (not started): a picture pipeline, effects, and print-ready export. See Roadmap.