v0.3 represents a complete architectural transformation:
- 100x faster validation (WASM vs Zod)
- 10x faster network generation (WASM vs JavaScript)
- 60% less memory usage (ReScript optimization)
- Type-safe business logic (ReScript)
- Zero config deployment (Deno)
- 100% compatible with v0.2 data
- Built-in TypeScript support
- Secure by default (explicit permissions)
- Modern standard library
- No node_modules
- URL-based imports
- Functional programming
- Compile-time type safety
- OCaml-inspired syntax
- Excellent JS interop
- Optimized output
- 10-100x faster than JavaScript
- Memory-safe
- Zero-cost abstractions
- Ahead-of-time compilation
- Type-safe integration
- Deno APIs for I/O
- Bridge to ReScript and WASM
┌──────────────────────────────────────────────────────────┐
│ User Interface │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ CLI │ │ Capture │ │ Visualize│ │ Export │ │
│ └────┬────┘ └─────┬────┘ └────┬─────┘ └────┬─────┘ │
│ └───────────┬─┴────────────┘──────────────┘ │
└───────────────────┼──────────────────────────────────────┘
│
┌───────────▼────────────┐
│ TypeScript Glue Layer │ (Deno Runtime)
│ • CLI routing │
│ • File I/O (storage.ts)│
│ • WASM bridge │
│ • ReScript bridge │
└──┬────────────────┬────┘
│ │
┌──────▼─────┐ ┌────▼──────┐
│ ReScript │ │ WASM │
│ (Business) │ │(Performance)│
└────────────┘ └───────────┘
│ │
┌────▼─────────────────▼────┐
│ Compiled JavaScript/WASM │
│ • UbiCity.res.js │
│ • ubicity_bg.wasm │
└────────────────────────────┘
Purpose: I/O, CLI, integration
Files:
src/storage.ts- File system operationssrc/cli.ts- Command-line interfacesrc/wasm-bridge.ts- WASM integrationsrc/rescript-bridge.ts- ReScript integration
Why TypeScript: Deno's native language, great for I/O and glue code
Purpose: Type-safe business logic
Files:
src-rescript/UbiCity.res- Domain model and analysis
Compiles to: src-rescript/UbiCity.res.js (optimized ES6)
Why ReScript:
- Functional programming (immutability, pure functions)
- Compile-time type safety (no runtime errors)
- Excellent optimization (smaller, faster code)
- OCaml heritage (proven type system)
Purpose: Performance-critical operations
Files:
wasm/src/lib.rs- Validation, network generation, similarity
Compiles to: wasm/pkg/ubicity_bg.wasm
Why WASM:
- 10-100x faster than JavaScript
- Memory-safe (no garbage collection pauses)
- AOT compilation (predictable performance)
- Perfect for algorithms and computation
User Input
│
▼
┌─────────────────┐
│ Fast Validation │ ◄── WASM (0.01ms)
│ (WASM Rust) │
└────────┬────────┘
│ Valid ✓
▼
┌─────────────────┐
│ Storage Layer │ ◄── TypeScript (Deno APIs)
│ (TypeScript) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Analysis Logic │ ◄── ReScript (functional)
│ (ReScript) │
└────────┬────────┘
│
▼
┌─────────────────┐
│Network Generation│ ◄── WASM (5ms for 1000 exp)
│ (WASM Rust) │
└─────────────────┘
- Visualization generation → TypeScript (not performance-critical)
- File exports → TypeScript (I/O bound, not CPU bound)
- CLI formatting → TypeScript (user interaction, not bottleneck)
just buildRuns:
rescript build→ Compile ReScript to JavaScriptcargo build --release --target wasm32-unknown-unknown→ Compile Rust to WASMwasm-opt -Oz→ Optimize WASM for size
Output:
src-rescript/UbiCity.res.js- Optimized JavaScriptwasm/pkg/ubicity_bg.wasm- Optimized WASM binary
just compileRuns:
just build(ReScript + WASM)deno compile→ Create standalone executables
Output:
bin/ubicity- Standalone CLI binarybin/ubicity-capture- Standalone capture tool
No runtime needed! Fully self-contained.
// Won't compile if types don't match
let experience = LearningExperience.make(
~learner=learner, // Must be Learner.t
~context=context, // Must be Context.t
~experience=exp, // Must be ExperienceData.t
()
)Catches errors: Before runtime
pub fn validate(&self, json: &str) -> Result<String, JsValue> {
let result: Result<Experience, _> = serde_json::from_str(json);
// Fast deserialization + validation
}Catches errors: At validation (fast)
// TypeScript ensures correct bridge usage
export function validateExperienceWasm(experience: unknown): {
valid: boolean;
errors: string[];
}Catches errors: At integration points
┌──────────────────────────────────┐
│ Node.js Heap (~50MB) │
│ ┌────────────────────────────┐ │
│ │ Experiences (array) │ │
│ │ + Zod validators (heavy) │ │
│ │ + Indices (Maps) │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
┌──────────────────────────────────┐
│ Deno Heap (~20MB) │
│ ┌────────────────────────────┐ │
│ │ ReScript immutable data │ │
│ │ (structural sharing) │ │
│ │ + Indices (optimized) │ │
│ └────────────────────────────┘ │
├──────────────────────────────────┤
│ WASM Linear Memory (~5MB) │
│ ┌────────────────────────────┐ │
│ │ Temporary validation data │ │
│ │ (no GC overhead) │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
Total: 25MB vs 50MB = 50% reduction
Explicit, granular permissions:
# Read-only access to data directory
deno run --allow-read=./ubicity-data src/cli.ts stats
# Read-write for capture
deno run --allow-read --allow-write=./ubicity-data src/capture.ts
# Pre-configured in deno.json tasks
deno task capture # Permissions already setWASM runs in isolated linear memory:
- Cannot access file system
- Cannot make network requests
- Cannot execute arbitrary code
Perfect for untrusted data validation
# Install Deno on server
curl -fsSL https://deno.land/install.sh | sh
# Run directly
deno task reportPros: Easy updates, dynamic Cons: Requires Deno runtime
# Compile once
just compile
# Deploy standalone binary
./bin/ubicity reportPros: No runtime needed, fast startup Cons: Platform-specific, larger file
FROM denoland/deno:alpine
WORKDIR /app
COPY . .
RUN deno task build
RUN deno cache src/index.ts
CMD ["deno", "task", "cli"]Pros: Consistent environment Cons: Docker overhead
// tests/validation.test.ts
import { assertEquals } from '@std/assert';
Deno.test('WASM validation is fast', async () => {
const start = performance.now();
validateExperienceWasm(testData);
const duration = performance.now() - start;
assert(duration < 1); // Sub-millisecond
});deno test --allow-read --allow-write tests/deno bench --allow-read --allow-write benchmarks/- WASM SIMD: Vectorized operations for network generation
- Parallel Processing: Multi-threaded WASM
- GPU Acceleration: WebGPU for large-scale analysis
- Incremental Compilation: Faster ReScript rebuilds
- Link-Time Optimization: Cross-language optimization
- ❌ Web framework integration (tools not platforms)
- ❌ Database layer (file-based is intentional)
- ❌ Authentication system (local-first)
- ❌ Cloud sync (privacy by default)
Despite radical architectural change, v0.3 preserves:
✅ Minimal Viable Protocol - Still WHO/WHERE/WHAT ✅ Tools not Platforms - Still CLI-first, no server ✅ Data First - 100% compatible JSON files ✅ Constraint Mechanism - Same 4-week experiment ✅ Privacy by Default - Local storage, no cloud ✅ Zero Bloat - Even fewer dependencies (no npm!)
The architecture changed. The philosophy didn't.
- Official Guide: https://docs.deno.com
- Standard Library: https://deno.land/std
- Language Manual: https://rescript-lang.org
- Belt stdlib: https://rescript-lang.org/docs/manual/latest/api/belt
- Rust Book: https://doc.rust-lang.org/book/
- wasm-bindgen: https://rustwasm.github.io/wasm-bindgen/
v0.3 is a performance rewrite that maintains 100% data compatibility.
Use v0.3 if you:
- Want maximum performance
- Need type safety
- Prefer modern tooling
- Deploy to production
Use v0.2 if you:
- Want zero build step
- Prefer simplicity over performance
- Don't need type safety
- Are just experimenting
Both are maintained. Your choice.
Architecture Questions?
See: MIGRATION_V3.md for migration steps
See: justfile for all build commands
See: deno.json for configuration details