engineering stack

What we ship on.

Every tech below is running in production for at least one of our own products. We don't list things we haven't shipped — this is the working set, not a résumé.

choices we've locked in

Fewest primitives, most leverage.

We could ship on twenty frameworks. We choose to ship on five. Every engineer can move between every project — no silos, no onboarding tax when we pick up a new engagement.

One frontend framework

Next.js 16 App Router across every site and web app. React 19, Tailwind 4, TypeScript. Reason: one team can move between projects with zero framework overhead. Marketing sites, admin dashboards, and web apps all ship on the same primitive.

Tauri v2 for desktop, not Electron

Rust core + system webview. 6–8 MB installers vs Electron's 60 MB+. Signed installers ship with SHA-256 checksums. Auto-update via S3 + CloudFront. License validation is Ed25519 offline-verifiable — the app works without a network round-trip.

Expo + gradle-only APK

Expo Router 4 + React Native 0.79 for mobile. We build APKs locally with gradle — never EAS Build or Expo cloud services. R8 + ProGuard release builds obfuscate anything IP-bearing before shipping to Play Store or self-distribution.

Unity 6 LTS for games

Unity 6.5 LTS + URP + New Input System. ScriptableObject-driven combat data means content ships via table edits, not code changes. R8 obfuscation matches our mobile pipeline. Same engineers can move between mobile-app and game work.

AWS EC2, not managed platforms

Own the box. PM2 + nginx + Let's Encrypt origin certs, deployed via PowerShell scripts. No AWS Lambda / Vercel / Netlify lock-in on serious workloads — we know exactly where every byte lives and how much every month costs.

by layer

Nine layers deep.

Everything below is in production somewhere. Click through to Work to see the products each layer is shipping.

Frontend

Next.js 16React 19TypeScriptTailwind 4ViteAstroThree.jsR3FFramer MotionGSAP

Mobile

Expo SDK 53React Native 0.79React Navigation 7KotlinSwift (planned)expo-glReact Native Reanimated

Desktop

Tauri v2RustNSISMSIDMGDEBAuto-update (S3 + CloudFront)Ed25519 signed

Game

Unity 6.5 LTSURPC#New Input SystemScriptableObjectR8 / ProGuardKenney 3DQuaternius

Backend

Node.jsExpressPostgreSQLRedisBullMQTypeScripttsxCloudflare R2S3

Systems

RustC#JavaSpring BootSQLite (rusqlite)better-sqlite3ONNX RuntimeFFmpeg

AI / ML

ONNX Runtime (Rust ort)Claude API (SSE streaming)PaddleOCRRetinaFace + ArcFaceYOLOv8nCLIPLaMa

Infra & DevOps

AWS EC2nginxPM2Let's Encrypt (certbot)Cloudflare R2PowerShell deploysGitea (self-hosted)R2 nightly backups

Security & QA

ADR-007 tiered obfuscationEd25519 license keysArgon2 PIN hashingAES-256-GCMR8 + ProGuardOWASP compliance

what shipping code looks like

Small primitives, clean boundaries.

armiscan/src-tauri/src/commands.rs
// Tauri v2 command handler — Rust core, TypeScript UI
#[tauri::command]
async fn run_scan(url: String) -> Result<ScanReport, String> {
    let engine = ScannerEngine::new();
    engine.probe(&url).await
        .map_err(|e| e.to_string())
}

// TypeScript UI side — one line to invoke
const report = await invoke<ScanReport>("run_scan", { url });

This is the actual shape of a shipped Tauri v2 command handler — Rust engine, TypeScript UI, one function call between them. No framework glue, no ORM, no serialisation ceremony. The primitives are small enough that engineers hold the whole architecture in their head.

the rule

We ship on the fewest primitives possible. One frontend framework (Next.js). One desktop shell (Tauri v2). One mobile stack (Expo). One game engine (Unity 6). Every engineer works across every product. Nothing is a "different team's problem."