diff --git a/package-lock.json b/package-lock.json index 8677ff8..87ecc00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "astro": "^5.0.0", - "traverse-embedder-web": "^0.9.0" + "traverse-embedder-web": "0.9.0" }, "devDependencies": { "@playwright/test": "^1.63.0" diff --git a/src/components/DocsSidebar.astro b/src/components/DocsSidebar.astro index d124f35..b557d5f 100644 --- a/src/components/DocsSidebar.astro +++ b/src/components/DocsSidebar.astro @@ -21,6 +21,7 @@ const sections = [ title: 'Guides', links: [ { href: '/docs/guides.html', label: 'All Guides' }, + { href: '/docs/guides/cross-os-capability.html', label: 'Cross-OS Capability' }, { href: '/docs/guides/mcp-setup.html', label: 'MCP Setup' }, { href: '/docs/guides/react-integration.html', label: 'React Integration' }, ], diff --git a/src/pages/blog/cross-platform-rarely-means-what-it-sounds-like.astro b/src/pages/blog/cross-platform-rarely-means-what-it-sounds-like.astro new file mode 100644 index 0000000..e60c2a8 --- /dev/null +++ b/src/pages/blog/cross-platform-rarely-means-what-it-sounds-like.astro @@ -0,0 +1,129 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+
+ + + Industry + Portability +
+

Why "cross-platform" rarely means what it sounds like

+ +
+
+ +
+
+ +
+ +

"Cross-platform" is one of those words that sounds precise and isn't. Every framework that uses it means something slightly different by it, and the gap between what it implies and what it delivers is usually where a project's second rewrite comes from. Worth being specific about what each one actually promises, because "cross-platform" alone tells you almost nothing.

+ +

Flutter: cross-platform UI, single language

+

Flutter's promise is real and well-delivered: one Dart codebase, native-feeling widgets on desktop, mobile, and web. What it doesn't promise is that your business logic is usable outside a Flutter app. That logic is Dart. If your backend needs the same rule, you're porting it — by hand, into a different language, hoping the port stays faithful as the rule changes.

+ +

Electron and Tauri: cross-platform desktop, browser-based

+

Electron and Tauri both mean "cross-platform desktop," specifically — neither targets mobile. Electron bundles its own Chromium per app, which is why an Electron app's install size raises eyebrows; Tauri uses the OS's system web view instead, which is lighter but means your app's rendering can vary slightly by OS, since it's not the same engine everywhere. Both are honest about being desktop-only. The logic-reuse gap is the same as Flutter's: your JS or Rust lives inside that app.

+ +

React Native: cross-platform mobile, with real per-platform seams

+

React Native's "learn once, write anywhere" tagline is more careful than most, and for good reason — the framework itself acknowledges that native modules, platform-specific styling quirks, and OS-level API differences mean a nontrivial React Native app usually has real iOS-specific and Android-specific code somewhere. It's a meaningfully smaller rewrite than fully native, not a zero rewrite.

+ +

Progressive Web Apps: cross-platform with an asterisk that keeps growing

+

PWAs promise "any device with a browser," which is the broadest-sounding claim of the group — and also the one with the most fine print. Background processing, push notifications, and deep OS integration vary by platform and browser vendor, and iOS Safari has historically lagged in exactly the capabilities that make a PWA feel native. "Works everywhere" quietly becomes "works everywhere, to varying degrees of well."

+ +

The pattern underneath all of them

+

Every one of these tools is honest about the layer it actually controls — Flutter controls rendering, Electron controls the desktop shell, React Native controls the mobile bridge, PWAs control browser delivery — and every one of them is quieter about what it doesn't control, which is almost always the business logic living inside that layer. That's not a knock on any of them individually. It's what happens when "cross-platform" gets used as a single word for a UI-layer promise, without a separate word for the logic-layer question underneath it.

+ +
The honest framing isn't "which of these is the real cross-platform tool." It's "which layer are you actually asking about" — the UI, or the logic underneath it. They're different problems with different honest answers.
+ +

Where this leaves Traverse

+

Traverse doesn't compete on the UI-layer question at all — it has no UI. What it answers is the logic-layer question specifically: is this one rule identical, governed, and auditable everywhere it's invoked, independent of which UI framework called it. Native — Windows, macOS, Linux — is shipped and mature. The browser is shipped, with a stated scope. Mobile embedders are real, working, unreleased code on Android and .NET, and honestly blocked on iOS pending the WASM engine ecosystem. That's a narrower claim than "cross-platform" usually implies, on purpose, because the narrower claim is the one that's actually true today. The full platform-by-platform status, evidence-linked, is on Platforms, and the deeper comparison against the UI-layer frameworks named here is on the Traverse vs. cross-platform app frameworks page.

+ +
+ + + +
+
+ +
+
+

Keep your UI framework. Govern the logic underneath it.

+

See where Traverse fits next to the tool you're already using.

+
+ Read the comparison → + Quickstart +
+
+
+`; +--- + + + + diff --git a/src/pages/blog/does-traverse-run-on-any-os-honest-answer.astro b/src/pages/blog/does-traverse-run-on-any-os-honest-answer.astro new file mode 100644 index 0000000..f7cc90d --- /dev/null +++ b/src/pages/blog/does-traverse-run-on-any-os-honest-answer.astro @@ -0,0 +1,128 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+
+ + + Honesty + Platforms +
+

"Does this work on any OS?" — the question I get the most, answered without the marketing gloss

+ +
+
+ +
+
+ +
+ +

Some version of "does Traverse work on any OS" comes up in almost every conversation I have about this project — GitHub issues, Discord, people I meet who ask what I've been building. It's a fair question, and it deserves a real answer instead of a slide with a checkmark next to five platform logos. So here's the one I actually give.

+ +

The short answer

+ +

For native desktop — Windows, macOS, Linux — yes, unreservedly. Write a capability once, compile it to WASM, and traverse-runtime's Wasmtime-backed executor runs the identical binary on all three. That's the most mature, most heavily used path through the project, and I'll say "yes" to that one without an asterisk.

+ +

For the browser, also yes, with a real but honest scope: the Web embedder SDK loads a bundle, verifies it, and executes it directly in the browser's native WASM host. As of the last release there's a governed path for running a single verified capability and getting a trace receipt back. What it doesn't do yet is arbitrary conditional or event-driven workflow execution in-browser — linear, directly-triggered pipelines only, for now.

+ +

For mobile, the honest answer is "not yet, and here's exactly why." That's the part most cross-platform marketing skips, so let me not skip it.

+ +

Why mobile gets a different answer

+ +

Android has a real, working runtime bridge — built on Chicory, with bundle validation and lifecycle handling in place. What's missing is the reference-app integration and a public release, both tracked as open work, not vaporware.

+ +

iOS is the one that actually stops me from saying "any OS" cleanly. We went through a formal screen of the available WASM engines — WasmKit, WAMR, Wasmtime, Wasmer — looking for one that exposes the resource-control APIs a certified native embedder needs to pass App Store review. None of them currently do, for a mix of reasons: missing resource-control surface, no supported iOS profile, or JIT and entitlement conflicts with App Store distribution rules. That's not "we haven't gotten to it." That's genuinely blocked on something outside this project.

+ +

We didn't just stop there and shrug. A feasibility spike embedded the wasmi interpreter directly through a Rust static library and a narrow C bridge, with the host enforcing memory and fuel limits by hand, and it ran clean on a physical iPhone. That's a real, verified result — I wrote up the full technical account separately — but it's a foundation for a future path, not something you can add to an Xcode project today.

+ +

Why I keep answering it this way instead of rounding up

+ +

It would be easier, in a pitch, to say "runs on any OS" and let the listener assume mobile is covered. Most people wouldn't check until they'd already started building. I've been on the other end of that kind of claim from other tools — the finding-out-later part is what actually costs you time and trust, not the narrower truth up front.

+ +

So the answer stays specific: full support for Windows, macOS, and Linux, shipped. Real support for the browser, shipped with a stated scope. Real, working, unreleased code for Android and .NET/WinUI. A blocked, evidence-backed status for iOS, with a documented workaround that isn't a product yet. Anyone can go check every one of those claims against the actual crates and issues on the Platforms page — it's the same page I link when someone asks me this in person.

+ +
+ + + +
+
+ +
+
+

Check the claims yourself.

+

Every platform, scored against a real crate, package, or blocking issue in the repo.

+
+ Platform status → + Quickstart +
+
+
+`; +--- + + + + diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 94d3f62..960d3b8 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -2,6 +2,11 @@ import SubpageLayout from '@layouts/SubpageLayout.astro'; const posts = [ + { href: '/blog/the-v1-gates-why-we-wont-call-this-done.html', title: "The v1.0 gates: why we won't call this done until it's actually done", desc: "Ten explicit, checkable requirements, not a date or a feeling. None are met as a complete set yet, and the roadmap says exactly which ones aren't." }, + { href: '/blog/what-a-governed-capability-buys-you.html', title: "What a governed capability buys you that a shared library doesn't", desc: 'A shared crate gets Rust callers code reuse with no ceremony. It breaks down the moment a non-Rust caller, or an audit requirement, shows up.' }, + { href: '/blog/does-traverse-run-on-any-os-honest-answer.html', title: '"Does this work on any OS?" — the question I get the most, answered without the marketing gloss', desc: 'Full native support on Windows, macOS, and Linux, a real but scoped answer for the browser, and exactly why mobile is a different story.' }, + { href: '/blog/same-binary-three-operating-systems.html', title: 'Same binary, three operating systems: what "write once" actually means', desc: 'What actually happens when a capability runs identically on Windows, macOS, and Linux — and what that claim honestly does not cover yet.' }, + { href: '/blog/cross-platform-rarely-means-what-it-sounds-like.html', title: 'Why "cross-platform" rarely means what it sounds like', desc: 'Flutter, Electron, Tauri, React Native, and PWAs each mean something different by the word, and all of them are quieter about the logic layer underneath the UI.' }, { href: '/blog/traverse-0-10-governed-composition.html', title: 'Traverse v0.10: governed composition, and what it means for AI-built software', desc: 'The runtime can now plan, schedule, run, and promote multi-capability workflows over MCP, and persist a durable, tamper-evident trace of what ran. An honest status report.' }, { href: '/blog/native-ios-runtime-foundation.html', title: 'Native iOS without a JIT: a hands-on feasibility proof', desc: 'A Swift app called a Rust wasmi interpreter, enforced host-owned memory and fuel limits, and ran clean on a physical iPhone — no JIT required.' }, { href: '/blog/ai-agents-need-contracts.html', title: 'AI agents need contracts, not just function definitions', desc: 'Function calling tells an agent what a tool does. It says nothing about what has to be true before or after it runs.' }, diff --git a/src/pages/blog/same-binary-three-operating-systems.astro b/src/pages/blog/same-binary-three-operating-systems.astro new file mode 100644 index 0000000..caba001 --- /dev/null +++ b/src/pages/blog/same-binary-three-operating-systems.astro @@ -0,0 +1,131 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+
+ + + Portability + Native +
+

Same binary, three operating systems: what "write once" actually means

+ +
+
+ +
+
+ +
+ +

A teammate asked me last week whether Traverse "runs on any OS." I gave the honest answer, which took about four sentences and included the word "blocked" once. They looked a little disappointed. I get it — "yes, any OS" is a much better sentence than what I actually said. It's also not true for most tools that say it, and I'd rather be the tool that says the true thing.

+ +

So here's the actual mechanics of what happens when the same capability runs on Windows, macOS, and Linux, and why that part of the claim is one I'll make without hedging.

+ +

What actually runs

+ +

You write a capability once, in Rust. You compile it to WebAssembly. That produces a single .wasm file — a binary instruction format, not machine code for any particular CPU or OS. traverse-runtime loads that file into a Wasmtime-backed WasmExecutor, validates the request against the capability's contract, runs it in a sandbox, checks the output against the contract's postconditions, and writes a trace.

+ +

Every step of that is identical on Windows, macOS, and Linux, because none of it touches the host OS directly. The WASM sandbox doesn't see a filesystem, a network socket, or a thread unless the contract explicitly grants it and the host wires up the import. There's no "Windows build" of your capability and no #[cfg(target_os = "linux")] branch hiding somewhere. It's the same file, byte for byte, on all three.

+ +
This is also, not coincidentally, why the sandbox exists in the first place. The moment a capability starts making raw system calls, it stops being portable — the whole reason OS-independence holds is that the boundary between "my logic" and "the host" is explicit and narrow.
+ +

Why this isn't a Traverse trick

+ +

I want to be clear this part isn't clever engineering on our side. It's what WebAssembly is for. Any conformant WASM runtime executes a given binary the same way, by design, regardless of the host it's embedded in. Traverse's job on top of that is the governance layer — the contract, the registry, the validation, the trace — not the portability itself. If you stripped Traverse away entirely and just ran raw wasmtime run capability.wasm on all three operating systems, you'd already get the same execution behavior. We're not reinventing that; we're making it safe to build a real system on top of.

+ +

What I won't claim next to this

+ +

Here's the part that made my teammate less excited. "Runs on any OS" quietly implies "runs on your phone too," and that's not true yet. Android has a working Kotlin runtime bridge with no public release. iOS is blocked — not behind, not deprioritized, actually blocked — because no WASM engine we've evaluated currently exposes the resource-control APIs a certified native embedder needs to pass App Store review. We found a workaround that runs on a physical iPhone using a different engine entirely, and that's a real result, but it's a research spike, not something you can ship today.

+ +

I could stop mentioning that and let "any OS" imply more than it delivers. Plenty of tools do exactly that, and most people won't check until they've already built on the assumption. I'd rather lose the cleaner sentence and keep the trust.

+ +

The claim I'll actually make

+ +

Write the capability once. It runs, unmodified, on Windows, macOS, and Linux, natively, today — and in the browser, through the Web embedder SDK, with its own honestly-scoped limits. That's real, it's shipped, and I'll say it plainly. Mobile is coming, at different speeds, for reasons outside our control on one of the two platforms. The full, evidence-linked status of every target — not a rounded-up version of it — lives on the Platforms page, and I'd rather you read that before you build on top of any of this than find out later.

+ +
+ + + +
+
+ +
+
+

See it run on your own machine.

+

The quickstart builds the same binary the CLI runs on Linux, macOS, and Windows alike.

+
+ Quickstart → + View on GitHub +
+
+
+`; +--- + + + + diff --git a/src/pages/blog/the-v1-gates-why-we-wont-call-this-done.astro b/src/pages/blog/the-v1-gates-why-we-wont-call-this-done.astro new file mode 100644 index 0000000..18a8d33 --- /dev/null +++ b/src/pages/blog/the-v1-gates-why-we-wont-call-this-done.astro @@ -0,0 +1,122 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+
+ + + Roadmap + Honesty +
+

The v1.0 gates: why we won't call this done until it's actually done

+ +
+
+ +
+
+ +
+ +

It would be easy to slap a "v1.0" tag on this project right now. The core runtime works. 133 governing specs are approved. Three crates are coverage-gated in CI. People are building real things with it. By a lot of projects' standards, that's already a 1.0.

+ +

I'd rather not do that, and I want to explain why, because it connects directly to everything else on this site about not overselling platform support.

+ +

Ten gates, not a vibe

+ +

The v1.0 milestone for this project isn't a date or a feeling — it's ten explicit, named requirements, published on the roadmap, that all have to be true at the same time. A few of them: every crate actually published on crates.io, not just buildable from source. A five-platform CI stress matrix that actually exercises the cross-platform claim instead of assuming the architecture guarantees it. An MCP library surface, not just the stdio subprocess most people are using today. 100% coverage on every governed path, not just the three core crates that are gated now. Zero open P0/P1 bugs.

+ +

None of those are met as a complete set right now. Some are close. Some — the full CI matrix, specifically — are real, tracked gaps, not rounding errors.

+ +

Why I don't round up

+ +

The tempting move is obvious: call it 1.0 anyway, because "1.0" signals stability and stability is what gets adoption. I've watched other projects do exactly that, and I've been burned by exactly that as a user — building against a "1.0" that turned out to mean "we felt ready," not "we verified the specific things a 1.0 label is supposed to promise."

+ +
A version number is a claim, same as "runs on any OS" is a claim. If I'm going to hold myself to evidence for one, I have to hold myself to it for the other.
+ +

So instead, the roadmap lists exactly which gates are met and which aren't, with the actual milestone document linked, not summarized into a vaguer "coming soon." If cross-platform CI coverage is the thing you're relying on before you trust this in production, you can go check whether it's actually there yet, instead of trusting a badge.

+ +

What this means if you're evaluating Traverse today

+ +

It means v0.10.1 is real, useful, and — for its shipped scope — solid: native execution, the CLI, the MCP server, the browser adapter, all functional and used in the examples on this site. It also means you should read "shipped" as "shipped for what it claims" and not assume everything you'd expect from a 1.0 project is already in place. The roadmap is written to make that distinction checkable, not to be skimmed past.

+ +
+ + + +
+
+ +
+
+

Check the gates yourself.

+

Ten explicit requirements, tracked in the open, not rounded up.

+
+ Roadmap → + Security audit +
+
+
+`; +--- + + + + diff --git a/src/pages/blog/what-a-governed-capability-buys-you.astro b/src/pages/blog/what-a-governed-capability-buys-you.astro new file mode 100644 index 0000000..ff2c0f2 --- /dev/null +++ b/src/pages/blog/what-a-governed-capability-buys-you.astro @@ -0,0 +1,124 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+
+ + + Contracts + Architecture +
+

What a governed capability buys you that a shared library doesn't

+ +
+
+ +
+
+ +
+ +

The most common pushback I get on Traverse, from Rust teams specifically, is some version of: "couldn't I just put this in a shared crate?" It's a good question, and the honest answer is usually yes — right up until it isn't. Here's where the line actually sits.

+ +

The case for just using a crate

+ +

If your whole system is Rust, a shared crate gets you real code reuse with none of the ceremony: no contract to write, no WASM compilation step, no sandbox overhead. Every service imports the crate, calls the function, done. For a team that's fully Rust and has no reason to expect that to change, I will tell you honestly: don't reach for Traverse. You don't need it yet.

+ +

Where it breaks down

+ +

The crate approach starts to strain the moment a caller outside your Rust ecosystem needs the same logic. Your frontend is JavaScript. Someone wants to call the rule from Python for a data pipeline. An AI agent needs to invoke it as a tool. None of them can just use your crate. Each one now needs its own binding: an FFI layer, a WASM build of the crate compiled separately for that purpose, or a network service wrapping it — and you're maintaining integration surface per caller, which is exactly the duplication problem you were trying to avoid in the first place, just moved one level up.

+ +

There's a second, quieter problem even within an all-Rust system: a crate's public function signature is a type contract, not a behavioral one. Nothing stops a caller from passing a technically well-typed but semantically invalid input. Nothing records, later, what was actually passed and returned when something goes wrong in production. You get compile-time safety and approximately nothing at runtime.

+ +

What a governed capability changes

+ +

A Traverse capability compiles to WASM instead of a native crate, which sounds like a downgrade in a Rust-only world and is actually the thing that makes it callable from everywhere else — any WASM-hosting environment loads it through the same interface, with no per-language binding to maintain. The contract attached to it isn't just types; it's declared preconditions and postconditions the runtime actually checks on every call, and a trace artifact that records what happened, every time, without anyone remembering to add a log line.

+ +
A shared crate answers "can multiple Rust services call this function." A governed capability answers "can I prove, after the fact, exactly what ran, with what inputs, and whether it was valid" — for any caller, in any language.
+ +

The real tradeoff, stated plainly

+ +

Writing a contract is more upfront work than writing a function signature. WASM sandboxing has real, measurable overhead compared to an in-process native call. Neither of those costs disappears because the benefits sound good. Pay them for the logic where drift, misuse, or an unexplained failure would actually cost you — pricing, eligibility, compliance, anything an AI agent might call unsupervised. Don't pay them for logic that's genuinely internal to one Rust service with no other callers in sight. Most systems have both kinds of logic in them; the skill is telling which is which before you've built four divergent copies of the wrong one.

+ +
+ + + +
+
+ +
+
+

See a real contract, end to end.

+

The quickstart inspects a real, governed bundle in under 15 minutes.

+
+ Quickstart → + GitHub +
+
+
+`; +--- + + + + diff --git a/src/pages/compare/index.astro b/src/pages/compare/index.astro index 1f0d1fb..4ca5d5e 100644 --- a/src/pages/compare/index.astro +++ b/src/pages/compare/index.astro @@ -5,6 +5,8 @@ const pages = [ { href: '/compare/vs-function-calling.html', title: 'Traverse vs AI Function Calling', desc: 'Function definitions describe a shape. Contracts govern behavior, before and after execution.' }, { href: '/compare/vs-microservices.html', title: 'Traverse vs Microservices', desc: 'Microservices split logic by team boundary. Traverse splits it by capability, running as one portable binary.' }, { href: '/compare/vs-serverless.html', title: 'Traverse vs Serverless Functions', desc: 'Serverless solves deployment and scaling. Traverse solves contract governance and portability. Different problems.' }, + { href: '/compare/vs-cross-platform-frameworks.html', title: 'Traverse vs Cross-Platform App Frameworks', desc: "Flutter, Electron, Tauri, and .NET MAUI solve UI portability. Traverse solves business-logic portability underneath them." }, + { href: '/compare/vs-wasm-runtimes.html', title: 'Traverse vs Raw WASM Runtimes', desc: 'Wasmtime, WasmEdge, and Wasmer execute WASM fast and portably. Traverse is a governance layer built on top of Wasmtime, not a competing runtime.' }, ]; --- +
+ +

Traverse vs. Cross-Platform App Frameworks

+

Flutter, Electron, Tauri, React Native, and .NET MAUI solve UI portability: one codebase, one native-feeling app across operating systems. Traverse solves a layer underneath that — one governed business-logic binary that behaves identically no matter which UI framework, backend, or AI agent is calling it. They're not really competing, and you can use them together.

+
+ + +
+ + +
+

What cross-platform UI frameworks solve

+

Flutter, Electron, Tauri, React Native, and .NET MAUI all attack the same problem from different angles: write your UI once, ship a native-feeling app on Windows, macOS, Linux, iOS, and Android without hand-building five separate front ends. Flutter and React Native compile or interpret down to native widgets. Electron and Tauri wrap a web view (Electron ships its own Chromium; Tauri uses the OS's own web renderer, which is why its binaries are smaller). .NET MAUI shares one XAML-based UI layer across desktop and mobile.

+

All of them are genuinely good at this. It's a hard, well-understood problem, and each one has years of tooling, hot-reload workflows, and platform-specific escape hatches built up around it.

+

What none of them do is govern what happens once your button's onPressed handler fires. The business logic behind that tap — the pricing rule, the eligibility check, the discount calculation — is just more Dart, JavaScript, or C#, living inside that one app. If your backend, your web dashboard, and your AI agent need the exact same rule, you're re-implementing it in each of their languages and hoping the copies don't drift.

+
+ +
+

What Traverse solves

+

Traverse doesn't compete for the UI layer at all — it has none. What it governs is the rule itself. You write a capability once in Rust, compile it to WebAssembly, and attach a contract that declares its inputs, outputs, preconditions, and postconditions. The runtime validates all of that before and after execution, and produces a structured trace artifact every time the capability runs.

+

That WASM binary is device-independent: it executes locally by default, on whatever client loaded it, and the client can heuristically delegate part of the work to a server when its own context calls for it — not because someone chose "server" as a fixed deployment target ahead of time. The two shipped hosts for that binary today are native (Windows, macOS, Linux, through traverse-runtime's Wasmtime-backed executor) and the browser (through the public Web embedder SDK). Android and .NET/WinUI embedders are real, working code without a public release yet; iOS is blocked on the WASM-engine ecosystem lacking a certifiable resource-control API — see Platforms for the evidence.

+
The distinction: a UI framework decides how your app looks and behaves on each OS. Traverse decides whether a specific rule inside that app is consistent, governed, and auditable everywhere it's called from — including places that have no UI at all, like a batch job or an MCP-connected AI agent.
+
+ +
+

Key differences

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DimensionFlutter / Electron / Tauri / MAUITraverse
Primary unitA widget tree or DOM — the thing the user sees and touchesA governed WASM capability — the rule the app calls into, with no UI of its own
OS reach, shipped todayWindows, macOS, Linux, iOS, and Android are all shipped and mature for every framework in this groupWindows, macOS, Linux (native) and browser are shipped. Android and .NET/WinUI embedders are in progress, unreleased. iOS is blocked on the WASM engine ecosystem — see Platforms.
Contract enforcementNone built in — your logic runs as written, with whatever validation you hand-codePreconditions and postconditions are declared in a machine-readable contract and enforced by the runtime, not by convention
Execution recordWhatever logging you add yourselfA structured trace artifact on every execution — capability, version, inputs validated, outputs validated, timing
Reuse outside the appThe logic is Dart, JS, or C# inside that app; using it from a backend or AI pipeline means porting it to another languageThe same WASM binary and contract are callable from the CLI, an MCP-connected AI agent, or another app, unmodified
Primary useShip one native-feeling UI across operating systems and devicesKeep one business rule byte-for-byte identical everywhere it's invoked, UI or not
+
+ +
+

When to use which

+
+
+

Use a cross-platform UI framework when

+
    +
  • Users need a real native or native-feeling app on desktop and mobile
  • +
  • You want one team shipping UI once instead of five native codebases
  • +
  • The business logic behind the UI is simple enough to live in one place, in one language
  • +
  • You don't need that logic callable from outside this one app
  • +
+
+
+

Use Traverse when

+
    +
  • A rule has to produce the same result in the app, the backend, and an AI pipeline
  • +
  • Compliance requires a reproducible, auditable record of what ran and why
  • +
  • Logic drift between rewritten copies is already causing production bugs
  • +
  • You want contracts enforced before execution, not hoped for in code review
  • +
+
+
+
+ +
+

Running Traverse inside a Tauri app

+

Tauri is the most natural pairing here, because its backend is Rust — the same language Traverse capabilities compile from. The UI stays exactly what Tauri already gives you (a native window rendering your web frontend); a Tauri command just calls into the same governed capability your web dashboard and your AI agent call, through the public traverse-embedder crate.

+
+
src-tauri/src/commands.rs
+
use traverse_embedder::{BundleEmbedder, EmbedderConfig, TraverseEmbedderApi}; +use tauri::State; + +// Initialized once at app startup, shared across every window +pub struct AppState { + pub embedder: BundleEmbedder, +} + +#[tauri::command] +async fn check_discount_eligibility( + state: State<'_, AppState>, + customer_id: String, + cart_total: f64, +) -> Result<serde_json::Value, String> { + let input = serde_json::json!({ + "customer_id": customer_id, + "cart_total": cart_total, + }); + + // Same bundle the web dashboard and the backend call — one contract, one result + state.embedder + .submit_and_await("promotions.check-eligibility", &input) + .await + .map_err(|e| e.to_string()) +}
+
+

Tauri's frontend calls check_discount_eligibility like any other Tauri command — it has no idea the answer came from a governed WASM capability instead of hand-written Rust. The window renders whatever Tauri already renders. The rule underneath it is the exact same binary running in your web app and your CI pipeline.

+
+ +
+

The verdict

+

These aren't competitors, because they're not solving the same problem. A UI framework decides how your app looks and feels on five different operating systems. Traverse decides whether one specific rule inside that app is trustworthy, auditable, and identical everywhere it runs — including the places that never had a UI to begin with.

+

If your app's logic is simple, lives in one place, and never needs to run outside that app, you probably don't need Traverse — the UI framework you already picked is enough. If a rule inside that app is load-bearing enough that drift between copies would actually hurt (pricing, eligibility, compliance, anything an AI agent also needs to call), that's the rule worth pulling into a governed capability, while the framework you already chose keeps doing what it's good at.

+
+ + +
+ +
+
+
+
+
Keep your UI framework. Govern the logic underneath it.
+
See the exact platform matrix, or start with the quickstart.
+
+
+ Platform status → + Quickstart +
+
+
+`; +--- + + + + diff --git a/src/pages/compare/vs-wasm-runtimes.astro b/src/pages/compare/vs-wasm-runtimes.astro new file mode 100644 index 0000000..1e7a5e5 --- /dev/null +++ b/src/pages/compare/vs-wasm-runtimes.astro @@ -0,0 +1,167 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; + +const _body = ` +
+
+ +

Traverse vs. Raw WASM Runtimes (Wasmtime, WasmEdge, Wasmer)

+

Wasmtime, WasmEdge, and Wasmer execute WASM binaries fast and portably across operating systems. Traverse isn't a competitor to them — it's built on top of Wasmtime specifically, adding the contract, registry, and trace layer a raw runtime deliberately doesn't provide.

+
+
+ +
+ + +
+

What a WASM runtime solves

+

Wasmtime, WasmEdge, and Wasmer all solve the same core problem: take a .wasm binary and execute it, fast, safely, and identically regardless of the host OS. They differ in focus — Wasmtime is the Bytecode Alliance's reference-grade, standards-first implementation; WasmEdge targets edge and cloud-native workloads with extensions for AI inference; Wasmer emphasizes broad language embedding and its own package registry. All three are genuinely excellent at running a WASM binary correctly and quickly.

+

None of them, by design, know or care what the binary they're running is supposed to do, what inputs are valid, or what should be true when it finishes. That's out of scope for a runtime — it's an execution engine, not a governance layer.

+
+ +
+

What Traverse adds on top

+

Traverse doesn't replace a WASM runtime — traverse-runtime's native executor is built on Wasmtime specifically. What Traverse adds sits above that execution layer: a machine-readable contract describing a capability's inputs, outputs, preconditions, and postconditions; a registry that makes capabilities discoverable by contract rather than by hardcoded import; and a trace artifact recording what happened on every single execution — what ran, what was validated, what the result was.

+

Where Wasmtime answers "run this binary correctly," Traverse answers "was this specific execution allowed, valid, and auditable." Different layer, same underlying binary.

+
The distinction: a raw runtime is infrastructure. Traverse is what you'd build on top of that infrastructure if you needed enforced correctness and an audit trail — which most direct wasmtime run use cases don't need, and most governed business-logic systems do.
+
+ +
+

Key differences

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DimensionRaw WASM runtimeTraverse
What it isAn execution engine for WASM binariesA governance layer built on top of a WASM execution engine (Wasmtime)
Input/output validationNone — the runtime executes whatever the binary's exported functions acceptEnforced against a declared JSON Schema contract before and after execution
DiscoveryYou call a known module by file path or handleCapabilities are discoverable through a queryable registry by contract, not hardcoded reference
Execution recordNone built in — whatever your own code logsA structured trace artifact per execution: capability, version, validation results, timing
Cross-OS behaviorIdentical, by the WASM spec itselfIdentical, inherited from the underlying runtime, plus contract enforcement identical everywhere too
Primary useEmbed WASM execution into any application, with full control over the surrounding logicGovern business logic that needs enforced correctness and an audit trail across multiple callers
+
+ +
+

When to use which

+
+
+

Use a raw WASM runtime directly when

+
    +
  • You're building your own governance or plugin system from scratch
  • +
  • You need fine-grained control over host imports and resource limits that a higher-level layer would abstract away
  • +
  • The workload doesn't need a contract, a registry, or a trace — just fast, sandboxed execution
  • +
+
+
+

Use Traverse when

+
    +
  • You want contract enforcement and traces without building that layer yourself on top of Wasmtime
  • +
  • Multiple callers (an app, a backend, an AI agent) need to discover and invoke the same governed capability
  • +
  • A rule needs to be auditable — what ran, with what inputs, under which contract version
  • +
+
+
+
+ +
+

The verdict

+

This isn't really a choice between alternatives — it's a choice about which layer of the stack you're working at. If you're building infrastructure and want direct control over WASM execution, use Wasmtime, WasmEdge, or Wasmer directly; they're excellent at exactly that. If you're building a business system and want contracts, discovery, and audit trails without reimplementing that layer yourself, Traverse gives you that on top of Wasmtime rather than instead of it.

+
+ + +
+ +
+
+
+
+
See the governance layer in action.
+
Build and inspect a governed bundle in the quickstart.
+
+
+ Quickstart + GitHub +
+
+
+`; +--- + + + + diff --git a/src/pages/docs/guides/cross-os-capability.astro b/src/pages/docs/guides/cross-os-capability.astro new file mode 100644 index 0000000..c5b5d46 --- /dev/null +++ b/src/pages/docs/guides/cross-os-capability.astro @@ -0,0 +1,162 @@ +--- +import SubpageLayout from '@layouts/SubpageLayout.astro'; +import DocsSidebar from '@components/DocsSidebar.astro'; + +const _docsBefore = `
`; +const _docsAfter = ` +
+
+ +

Write one capability, run it on Windows, macOS, Linux, and the browser

+

A hands-on walkthrough of the actual mechanism behind "any OS": one contract, one WASM binary, no per-platform branch. You'll inspect the shipped example bundle, understand why the same commands work on every native OS, and see the same capability load in a browser.

+
+ v0.10.1 + ~15 minutes + Rust 1.94+ +
+
+ +
+
+
01
+ Build once +
+

Build the runtime and the example bundle

+

These are the exact same three commands regardless of whether you're on Windows, macOS, or Linux. Nothing here branches on OS — there's no separate quickstart per platform, because there's nothing platform-specific to instruct.

+
+
any OS — same three commands
+
+
$ git clone https://github.com/traverse-framework/traverse.git
+
$ cd traverse
+
$ cargo build
+
+
Compiling traverse-contracts v0.10.1
+
Compiling traverse-registry v0.10.1
+
Compiling traverse-runtime v0.10.1
+
Finished dev profile
+
+
+

Cargo and rustc are cross-platform build tooling by design — this is the same reason your Rust host binary doesn't need a Windows-specific or Linux-specific variant. The interesting part isn't this step; it's what happens next.

+
+ +
+
+
02
+ Inspect the bundle +
+

Inspect the shipped capability bundle

+

The expedition example ships as a registry bundle: a manifest, contracts, and WASM modules. Inspecting it shows you exactly what the runtime will load — the same output on every OS, because it's reading the same files.

+
+
any OS — identical output
+
+
$ cargo run -p traverse-cli-rs -- bundle inspect examples/expedition/registry-bundle/manifest.json
+
+
Bundle: expedition-planning
+
capabilities: 6
+
events: 5
+
workflows: 1
+
plan-expedition v1.0.0 ... valid
+
+
+
Nothing here is OS-conditional. The manifest, the contracts, and the compiled WASM modules are plain files with no embedded platform assumptions — that's what makes step 3 unremarkable instead of requiring a rewrite.
+
+ +
+
+
03
+ Run natively +
+

Run it through the native executor

+

The native executor is Wasmtime-backed, and Wasmtime compiles the WASM module to native machine code for whichever host it's running on — a step that happens transparently, with no action required from you regardless of which OS you're on.

+
+
Your terminal (Windows, macOS, or Linux)
+
+
traverse-runtime · NativeExecutor · WasmExecutor (Wasmtime)
+
+
plan-expedition.wasm — same binary on every host
+
+

Follow the maintained repository quickstart for the exact run command for your setup — the point to notice is that the command itself doesn't fork by OS. If you have access to more than one operating system, running the identical command against the identical bundle is the fastest way to see this claim verified rather than asserted.

+
+ +
+
+
04
+ Run in the browser +
+

Load the same bundle in a browser

+

The Web embedder SDK loads the same bundle — not a rebuilt or re-exported version of it — and executes the WASM module directly in the browser's own WebAssembly host. This is the same digest-verified artifact the native executor ran in step 3.

+
+
load-in-browser.js (conceptual)
+
import { TraverseEmbedder } from 'traverse-embedder-web'; + +// Same bundle path as the CLI inspected in step 2 +const embedder = await TraverseEmbedder.init('./bundles/expedition'); +const result = await embedder.submit('plan-expedition', { destination: 'kilimanjaro' });
+
+
Scope note: this in-browser path handles linear, directly-triggered pipelines — conditional and event-driven workflow edges aren't executed in-browser yet. See the React integration guide for the fuller, request/response pattern via the local browser adapter, which has no such scope limit.
+
+ +
+
+
05
+ Confirm identical behavior +
+

Confirm it with the trace, not by eye

+

Don't take "identical behavior" on faith — the trace artifact from each run tells you exactly what executed. Compare the capability, version, and output fields from a native run against a browser run with the same input; they should match exactly, because it's the same binary either way.

+
+
trace artifact (either host)
+
{ + "capability": "expedition.planning.plan-expedition", + "version": "1.0.0", + "contract_validated": true, + "preconditions_met": true, + "postconditions_met": true +}
+
+
+ +
+

Next steps

+
+ +
Pair with a desktop UI
+
Call this same capability from a Tauri command.
+
+ +
Platform status
+
The full, evidence-linked matrix beyond this guide's two targets.
+
+ +
MCP Setup
+
Expose the same capability to an AI agent as a governed tool.
+
+
+
+
+
+`; +--- + + + + + + diff --git a/src/pages/docs/guides/index.astro b/src/pages/docs/guides/index.astro index 51c3afe..d5d6fa9 100644 --- a/src/pages/docs/guides/index.astro +++ b/src/pages/docs/guides/index.astro @@ -3,6 +3,7 @@ import SubpageLayout from '@layouts/SubpageLayout.astro'; import DocsSidebar from '@components/DocsSidebar.astro'; const guides = [ + { href: '/docs/guides/cross-os-capability.html', title: 'Write once, run on Windows, macOS, Linux, and the browser', desc: 'Inspect a real bundle, run it natively, load it in a browser, and confirm the match from the trace.' }, { href: '/docs/guides/mcp-setup.html', title: 'MCP Server Setup', desc: 'Expose your capability registry to Claude and other MCP-compatible agents.' }, { href: '/docs/guides/react-integration.html', title: 'React Integration', desc: 'Call Traverse capabilities from a React app.' }, ]; diff --git a/src/pages/questions/can-ai-agents-call-the-same-capability-regardless-of-os.astro b/src/pages/questions/can-ai-agents-call-the-same-capability-regardless-of-os.astro new file mode 100644 index 0000000..aa44d64 --- /dev/null +++ b/src/pages/questions/can-ai-agents-call-the-same-capability-regardless-of-os.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can an AI agent call the same capability my app uses, regardless of OS?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Yes. An MCP-connected agent discovers and invokes a capability through traverse-mcp against the registry, which is the same capability and contract your native or browser-hosted app calls directly. The agent gets the identical enforced behavior and trace as any other caller, independent of which OS is hosting the runtime the agent is talking to.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-does-the-mcp-server-work.html', label: 'How does the Traverse MCP server work?' }, + { href: '/questions/how-do-ai-agents-discover-capabilities.html', label: 'How do AI agents discover capabilities?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/docs/guides/mcp-setup.html', label: 'MCP Server Setup' }, +]; +--- + +

Yes, and this is one of the more concrete payoffs of the whole "one binary, one contract" model. traverse-mcp exposes capabilities from your registry as tools over the Model Context Protocol. When an AI agent — Claude or another MCP-compatible client — discovers and calls a capability, it's invoking the identical contract-governed WASM binary your web app, your native backend, or your CLI would call. Not a reimplementation exposed as a tool description; the same execution path, producing the same trace.

+ +

Because that binary is device-independent to begin with, the OS hosting the MCP server itself is beside the point — the agent's call goes through the registry and the runtime, and the underlying execution behaves the same way whether that host happens to be Windows, macOS, or Linux.

+ +

Why that matters more for agents than for a typical app

+

An AI agent calling a capability is exactly the situation where "the agent got a slightly different answer than the human-facing app because they're calling two different implementations" is a genuinely bad failure mode — invisible until it causes a wrong decision. Because the agent and the app are calling the same binary under the same contract, that specific failure mode is structurally ruled out rather than something you have to test for. See the MCP setup guide to wire this up directly.

+
diff --git a/src/pages/questions/can-i-migrate-existing-business-logic-to-traverse.astro b/src/pages/questions/can-i-migrate-existing-business-logic-to-traverse.astro new file mode 100644 index 0000000..c85edb4 --- /dev/null +++ b/src/pages/questions/can-i-migrate-existing-business-logic-to-traverse.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I migrate existing business logic into Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes, in the sense that you re-express the logic as a Rust capability compiled to WASM with a contract — Traverse doesn't ingest existing code from another language automatically. The practical path is picking one duplicated, drifting, or hard-to-audit rule, rewriting just that rule as a governed capability, and pointing your existing callers at it, rather than migrating an entire codebase at once.", + }, + }], +}); + +const relatedLinks = [ + { href: '/blog/logic-duplication.html', label: 'Why I stopped writing the same business logic four times' }, + { href: '/questions/how-do-i-write-a-capability-contract.html', label: 'How do I write a capability contract?' }, + { href: '/questions/do-i-need-rust.html', label: 'Do I need to know Rust to use Traverse?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

There's no automatic converter that takes your existing JavaScript, Python, or C# business rule and produces a Traverse capability — you re-implement the rule in Rust, compile it to WASM, and write the contract that describes it. That's real, deliberate work, not a checkbox migration, and it's worth being upfront about that instead of implying otherwise.

+ +

Where it pays off is when you're not migrating "the codebase" but one specific rule that's currently duplicated, drifting, or hard to audit — a pricing calculation reimplemented in three services, an eligibility check nobody's fully sure is consistent across the app and the backend. You rewrite that one rule as a governed capability, define its contract precisely (including the edge cases the old scattered copies probably handled inconsistently), and update your existing callers to invoke the capability instead of their own local implementation.

+ +

A reasonable order of operations

+

Start with the rule that's causing the most actual pain from drift, not the most complex one. Write its contract first — inputs, outputs, preconditions, postconditions — since that step alone often surfaces inconsistencies between the existing copies that nobody had written down before. Then implement it once in Rust, compile it, and swap one caller over at a time, verifying the trace output matches what you expect before removing the old implementation it replaced.

+ +

You don't need to know Rust deeply to consume a capability once it exists — see do I need to know Rust to use Traverse — but writing the capability itself does require it, since that's the language capabilities compile from today.

+
diff --git a/src/pages/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.astro b/src/pages/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.astro new file mode 100644 index 0000000..5ae9235 --- /dev/null +++ b/src/pages/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I run the same business logic in a browser app and a native app?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Yes — this is the combination with the most complete, shipped Traverse support today. The same WASM capability and contract are loaded by the native executor (Windows, macOS, Linux) and by the Web embedder SDK in the browser, with no separate implementation or build for either.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/what-is-the-browser-adapter.html', label: 'What is the browser adapter?' }, + { href: '/docs/guides/react-integration.html', label: 'React Integration guide' }, + { href: '/questions/how-do-i-share-business-logic-between-web-and-desktop.html', label: 'How do I share business logic between a web app and a desktop app?' }, +]; +--- + +

Yes, and out of every platform combination people ask about, this is the one with the most mature, complete support today — more so even than native-to-native across different desktop OSes, because it's the pairing the project has spent the most shipped effort on. Native execution (Windows, macOS, Linux) through traverse-runtime's Wasmtime-backed executor and browser execution through the Web embedder SDK both load the identical WASM binary and contract. Nothing about the capability changes between the two.

+ +

What differs is only the transport getting a request to the capability. A native host calls it in-process through an embedder. A browser page either talks to a local browser adapter over HTTP (the pattern the React integration guide walks through) or, as of the more recent releases, executes a single verified capability directly in the browser's own WASM host and gets back a signed trace receipt. Either way, the capability itself — and critically, its result for a given input — is unchanged.

+ +

Where this is genuinely useful

+

The common case: a validation or pricing rule needs to run instantly in a web form for UX (no round trip to a server) and also needs to run identically in your native backend or CLI tooling for the authoritative check. With a shared capability, both are guaranteed to agree, because they're executing the same binary — there's no "the frontend's copy of the rule is slightly out of date" failure mode to debug, because there's no second copy.

+
diff --git a/src/pages/questions/can-i-run-traverse-capabilities-in-a-docker-container.astro b/src/pages/questions/can-i-run-traverse-capabilities-in-a-docker-container.astro new file mode 100644 index 0000000..3873d64 --- /dev/null +++ b/src/pages/questions/can-i-run-traverse-capabilities-in-a-docker-container.astro @@ -0,0 +1,37 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I run Traverse capabilities inside a Docker container?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes. A Traverse capability's WASM binary runs on the native Linux executor, so packaging that host process in a container is unremarkable — it's the same native target running inside a Linux container as running directly on a Linux host, just with the usual containerization benefits layered on top for deployment and orchestration.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-is-traverse-different-from-docker.html', label: 'How is Traverse different from Docker?' }, + { href: '/compare/vs-serverless.html', label: 'Traverse vs Serverless Functions' }, + { href: '/questions/does-traverse-support-windows-macos-and-linux.html', label: 'Does Traverse support Windows, macOS, and Linux?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

Yes, and there's nothing special about it. A Traverse capability's WASM binary runs through the native executor, which is a Rust process using Wasmtime under the hood — the same kind of process you'd containerize for any other Rust service. Build your host application (the one embedding traverse-runtime or traverse-embedder and loading your registry bundle), put it in a minimal base image, and run it the way you'd run any containerized Rust binary.

+ +

This is, in fact, exactly the pattern shown in the Traverse vs. Serverless Functions comparison: the same traverse-embedder-based host that runs on your desktop or in a container also runs inside an AWS Lambda function, because none of those hosts require anything Traverse-specific to accommodate it. WASM execution, contract validation, and trace generation all happen the same way regardless of whether the process is bare-metal, containerized, or serverless — the container just answers "how does this process get deployed," which is orthogonal to what's running inside it.

+ +

One thing containerizing doesn't change: the capability's own sandbox permissions (network, filesystem, host calls) are still governed by its contract, not by whatever the container's own permissions happen to allow. A container with broad filesystem access doesn't loosen what a capability inside it is allowed to touch — the WASM sandbox boundary is enforced independently of the container boundary around it.

+
diff --git a/src/pages/questions/can-i-share-logic-between-ios-and-android-apps.astro b/src/pages/questions/can-i-share-logic-between-ios-and-android-apps.astro new file mode 100644 index 0000000..81c9854 --- /dev/null +++ b/src/pages/questions/can-i-share-logic-between-ios-and-android-apps.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I share business logic between an iOS app and an Android app with Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Not through a shipped Traverse SDK on both sides today. Android has a working, unreleased Kotlin runtime bridge. iOS is blocked on the WASM engine ecosystem lacking a certifiable resource-control API, though a feasibility spike proved a workaround runs on a physical iPhone. The capability and contract you write today carry over unchanged once both embedders ship — the logic-sharing goal is real, just not deliverable across both mobile OSes yet.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/can-traverse-build-mobile-apps.html', label: 'Can I build a mobile app with Traverse?' }, + { href: '/blog/native-ios-runtime-foundation.html', label: 'Native iOS without a JIT: a hands-on feasibility proof' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, +]; +--- + +

This is exactly the problem Traverse is built to eventually solve for mobile, and it's worth being precise about the word "eventually," because it isn't there yet for both platforms simultaneously.

+ +

On Android, packages/kotlin/TraverseEmbedder has a working runtime bridge built on Chicory, with bundle validation and lifecycle handling done. What's left is Compose reference-app integration and a public release — real, tracked, in-progress work, not a stalled idea.

+ +

On iOS, the situation is different in kind, not just degree: it's blocked, not just unfinished. As of the last engine screen, none of the major WASM runtimes (WasmKit, WAMR, Wasmtime, Wasmer) expose the resource-control APIs a certified native embedder needs to clear App Store review. A separate feasibility spike found a workaround — embedding the wasmi interpreter through a Rust static library with host-enforced memory and fuel limits — and it runs clean on a physical iPhone, which is a real result. It's not a shipped SDK you can add to an Xcode project today, though.

+ +

What you can do about it now

+

Write the shared rule as a well-scoped Traverse capability today, targeting the platforms that are already shipped — native desktop and the browser, for testing and for any web-based surface your product has. The contract doesn't change when a mobile embedder ships; the work isn't wasted, it's just not deployable to both phones yet. Watch Platforms for exactly when that changes, rather than guessing from a roadmap date.

+
diff --git a/src/pages/questions/can-i-use-traverse-for-a-saas-product-on-multiple-operating-systems.astro b/src/pages/questions/can-i-use-traverse-for-a-saas-product-on-multiple-operating-systems.astro new file mode 100644 index 0000000..3c60d43 --- /dev/null +++ b/src/pages/questions/can-i-use-traverse-for-a-saas-product-on-multiple-operating-systems.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I use Traverse for a SaaS product that needs to run on multiple operating systems?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes, for the pattern most SaaS products actually need: a web-hosted app plus an optional native companion (a CLI tool, a desktop menu-bar app, an on-prem agent) that both need to enforce the exact same business rules — billing logic, entitlement checks, usage limits. The web frontend and the native companion load the same governed capability instead of maintaining two implementations.", + }, + }], +}); + +const relatedLinks = [ + { href: '/examples.html', label: 'Traverse examples' }, + { href: '/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.html', label: 'Can I run the same business logic in a browser app and a native app?' }, + { href: '/questions/can-i-use-traverse-for-pricing-logic.html', label: 'Can I use Traverse for pricing logic?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, +]; +--- + +

Yes, and the shape this usually takes for a SaaS product is narrower than "the whole product runs everywhere" — it's specifically the handful of rules that have to stay consistent between a web-hosted app and some native companion surface: a CLI tool for power users, a desktop menu-bar utility, an on-prem agent installed at a customer site. Entitlement checks, usage-limit enforcement, and billing calculations are the classic candidates, because getting them inconsistent between the web app and the native tool is a support and revenue problem, not just a code-quality one.

+ +

The pattern: write the entitlement or pricing rule once as a Traverse capability. Your web app's backend calls it through the native executor (since backends run natively). Any native companion tool — a CLI, a desktop agent — embeds the same capability through traverse-embedder. Both get the identical enforced result from the identical contract, so a customer can't end up in a state where the web dashboard says they're over their limit and the CLI tool disagrees.

+ +

Where the honest limits still apply

+

If your SaaS product's "multiple operating systems" requirement is specifically a mobile app, the same mobile-embedder status covered elsewhere on this site applies — Android and .NET are in-progress, unreleased; iOS is blocked. For desktop and web, which is where most SaaS entitlement logic actually needs to be consistent, this is solid, shipped ground today. See the Traverse examples for the fuller worked walkthroughs.

+
diff --git a/src/pages/questions/can-i-use-traverse-in-a-monorepo-with-multiple-apps.astro b/src/pages/questions/can-i-use-traverse-in-a-monorepo-with-multiple-apps.astro new file mode 100644 index 0000000..40e4995 --- /dev/null +++ b/src/pages/questions/can-i-use-traverse-in-a-monorepo-with-multiple-apps.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I use Traverse in a monorepo with multiple apps targeting different platforms?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes — that's a common shape for this to fit well, since a shared registry bundle sitting alongside a web app, a native CLI, and a desktop shell in one repo means every app pulls from the same capabilities and contracts rather than each maintaining its own copy or import path.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-the-capability-registry.html', label: 'What is the capability registry?' }, + { href: '/questions/how-do-i-package-a-capability-for-multiple-platforms.html', label: 'How do I package a capability for multiple platforms?' }, + { href: '/questions/how-do-i-share-business-logic-between-web-and-desktop.html', label: 'How do I share business logic between a web app and a desktop app?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

Yes, and it's one of the more natural places for this pattern to pay off quickly. Put your registry bundle — the capabilities, their contracts, and any events or workflows — in a shared location in the monorepo, and have your web app, native tooling, and desktop shell each depend on it through whichever executor matches their platform (the Web embedder SDK for the web app, traverse-embedder for the native and desktop targets).

+ +

The practical benefit inside a monorepo specifically: a change to a capability's contract is one commit, reviewed once, and every app in the repo picks it up the next time it builds against the updated bundle. There's no separate PR per app to keep three reimplementations in sync, because there aren't three reimplementations — there's one bundle multiple apps reference.

+ +

What to actually structure

+

A reasonable layout: a top-level capabilities/ or bundles/ directory holding your registry bundle(s), separate from each app's own directory. Each app's build or dev script points its executor at that shared path rather than vendoring a copy. CI can validate the bundle once, independent of which apps happen to consume it, using the same bundle inspect/validate commands shown in the quickstart.

+
diff --git a/src/pages/questions/can-i-use-traverse-with-dotnet-maui.astro b/src/pages/questions/can-i-use-traverse-with-dotnet-maui.astro new file mode 100644 index 0000000..14db213 --- /dev/null +++ b/src/pages/questions/can-i-use-traverse-with-dotnet-maui.astro @@ -0,0 +1,37 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I use Traverse with .NET MAUI today?', + acceptedAnswer: { + '@type': 'Answer', + text: "Partially. Traverse's .NET embedder uses a working Wasmtime .NET-backed bridge targeting WinUI, which covers MAUI's Windows target. Request marshalling, event subscriptions, and reference-app integration for the rest of the .NET embedder are still open work, and there's no public release yet, so treat this as close but not a drop-in dependency for a shipping MAUI app across all four of its platforms.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-is-traverse-different-from-dotnet-maui.html', label: 'How is Traverse different from .NET MAUI?' }, + { href: '/questions/can-traverse-build-mobile-apps.html', label: 'Can I build a mobile app with Traverse?' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, + { href: '/questions/what-is-traverse-roadmap.html', label: 'What is the Traverse roadmap?' }, +]; +--- + +

Partially, and worth being precise about which part. packages/dotnet/TraverseEmbedder has a working runtime bridge backed by Wasmtime .NET, targeting WinUI — which is MAUI's Windows rendering target specifically, not the cross-platform MAUI runtime as a whole. Request marshalling, event subscriptions, evidence publication, and the shared cross-SDK conformance suite are still open work, and there's no public release of the package yet.

+ +

So if your MAUI app's Windows build is what you care about pairing with Traverse right now, the underlying pieces exist and are progressing. If you need the same integration working identically on MAUI's iOS and Android targets, that runs into the same mobile-embedder status as any other approach: iOS is blocked on the WASM engine ecosystem, and Android has its own separate, also-unreleased Kotlin bridge that isn't specifically wired for MAUI's Android target.

+ +

The honest recommendation: if you're starting a MAUI project today and want Traverse in it eventually, structure your business logic as a well-scoped capability with a clean contract now. That work carries forward unchanged once the embedder ships — the contract doesn't change when the host does. Track exactly when it does on the Platforms page rather than guessing from a roadmap date.

+
diff --git a/src/pages/questions/can-i-use-traverse-with-electron.astro b/src/pages/questions/can-i-use-traverse-with-electron.astro new file mode 100644 index 0000000..580de63 --- /dev/null +++ b/src/pages/questions/can-i-use-traverse-with-electron.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I use Traverse with Electron?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes. An Electron app's renderer process is a Chromium web page, so it can call a Traverse capability the same way any browser page does — through the Web embedder SDK or the local browser adapter. Electron's main process, being a Node.js process, can also shell out to or bind against a native traverse-embedder host if you want the capability running outside the renderer.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/can-i-use-traverse-with-tauri.html', label: 'Can I use Traverse with Tauri?' }, + { href: '/questions/how-is-traverse-different-from-electron.html', label: 'How is Traverse different from Electron?' }, + { href: '/questions/what-is-the-browser-adapter.html', label: 'What is the browser adapter?' }, + { href: '/docs/guides/react-integration.html', label: 'React Integration guide' }, +]; +--- + +

Yes. Electron's renderer process is, under the hood, a Chromium browser page rendering your web frontend — which means it's already a real WASM host. A Traverse capability loaded through the Web embedder SDK runs there exactly the way it would in a plain browser tab: no Electron-specific adaptation needed. The React integration guide applies directly if your Electron app's renderer is a React app, since the pattern (talk to the local browser adapter over HTTP, or load the embedder SDK directly) doesn't care that Chromium happens to be wrapped in a desktop shell.

+ +

If you'd rather run the capability outside the renderer — say, in Electron's Node.js-based main process, closer to the OS — that process can shell out to a native host running traverse-embedder, or communicate with a locally running traverse-cli adapter over IPC, the same pattern the Lambda and Tauri integration examples use elsewhere on this site.

+ +

Why you'd bother, instead of just writing the rule in JavaScript

+

The same reason as any other host: a plain JS function in your renderer has no enforced contract and produces no trace. If the rule behind that Electron app's UI also needs to run identically in your backend or be callable by an AI agent, wrapping it as a governed capability means all of those callers get the same binary and the same enforced result — instead of a JS copy in the app and a second implementation everywhere else.

+
diff --git a/src/pages/questions/can-i-use-traverse-with-tauri.astro b/src/pages/questions/can-i-use-traverse-with-tauri.astro new file mode 100644 index 0000000..3909d1b --- /dev/null +++ b/src/pages/questions/can-i-use-traverse-with-tauri.astro @@ -0,0 +1,39 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I use Traverse with Tauri?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes, and it's a particularly natural pairing since Tauri's backend is Rust, the same language Traverse capabilities compile from. A Tauri command calls into a governed capability through the public traverse-embedder crate, so the desktop window Tauri renders is backed by the same contract-enforced logic your web app and backend already call.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri (full comparison)' }, + { href: '/questions/how-is-traverse-different-from-electron.html', label: 'How is Traverse different from Electron?' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

Yes — of the cross-platform desktop frameworks, Tauri is the most natural fit, because its backend is already Rust. There's no FFI boundary or language bridge to cross: a Tauri command function can call the public traverse-embedder crate directly, the same way a native CLI tool would, and return the result to the frontend like any other Tauri command.

+ +

The practical shape: initialize a BundleEmbedder once at app startup, hold it in Tauri's shared state, and call submit_and_await (or the async equivalent your embedder version exposes) from inside a #[tauri::command] handler. Your Tauri frontend never knows the difference — it just gets a JSON result back — but the logic behind that result is the same governed, contract-enforced WASM binary your web dashboard, backend, or AI agent calls.

+ +

Why bother, instead of just writing the rule in Rust directly inside the Tauri command? Because a plain function has no contract, no enforced pre/postconditions, and no trace artifact. If that rule needs to be provably identical across your desktop app and three other callers — or if it's the kind of rule (pricing, eligibility, compliance) where drift between copies would actually cost you — wrapping it as a Traverse capability gets you the governance for free everywhere it's called, Tauri included.

+ +

For the full worked example, including the actual command code, see the Traverse vs. cross-platform app frameworks comparison.

+
diff --git a/src/pages/questions/can-non-rust-teams-use-traverse.astro b/src/pages/questions/can-non-rust-teams-use-traverse.astro new file mode 100644 index 0000000..9ed313e --- /dev/null +++ b/src/pages/questions/can-non-rust-teams-use-traverse.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can a team that does not write Rust still use Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes, as a consumer of capabilities — calling a capability over HTTP through the browser adapter, or via an embedder, requires no Rust at all, just JSON in and out. Authoring a new capability currently does require Rust, since that's the language capabilities compile from. A Python SDK is on the roadmap as planned, not yet shipped.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/do-i-need-rust.html', label: 'Do I need to know Rust to use Traverse?' }, + { href: '/questions/can-i-use-traverse-with-python.html', label: 'Can I use Traverse with Python?' }, + { href: '/docs/guides/react-integration.html', label: 'React Integration guide' }, + { href: '/questions/what-is-traverse-roadmap.html', label: 'What is the Traverse roadmap?' }, +]; +--- + +

Depends whether your team is consuming capabilities or authoring them, and those have very different Rust requirements.

+ +

Consuming a capability requires no Rust whatsoever. If you're calling into a capability from a React app, you're sending a plain JSON request to the local browser adapter and reading a JSON response back — the React integration guide covers this in full and never touches Rust or WASM directly. The same is true from any language that can make an HTTP request or bind against an embedder's API.

+ +

Authoring a new capability is a different story today: capabilities compile from Rust to WebAssembly, so writing a new one currently means writing Rust. There isn't yet a path to author a capability directly in Python, JavaScript, or another language and have Traverse compile it — a Python SDK is explicitly on the roadmap as a planned, not-yet-shipped item, aimed specifically at teams that don't write Rust and want to call existing capabilities more idiomatically, or eventually contribute to them.

+ +

A practical split for a mixed team

+

A common shape: one or two people comfortable with Rust write and maintain the capabilities and their contracts, while the rest of the team — frontend, data, ML — consumes them as a plain API. That's not a workaround; it matches how the contract boundary is meant to work. The contract is the interface a non-Rust consumer needs to understand; the Rust implementation behind it is an internal detail they don't have to touch.

+
diff --git a/src/pages/questions/can-traverse-build-mobile-apps.astro b/src/pages/questions/can-traverse-build-mobile-apps.astro new file mode 100644 index 0000000..c661075 --- /dev/null +++ b/src/pages/questions/can-traverse-build-mobile-apps.astro @@ -0,0 +1,45 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can I build a mobile app with Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Not as a shipped, public path yet, and we would rather say that plainly than let you find out mid-project. Android has a working runtime bridge (Chicory-based) with no public release. iOS is blocked: no WASM engine currently exposes the resource-control APIs a certified native embedder needs for App Store distribution, though a separate wasmi feasibility spike proved a workaround runs on a physical iPhone. Neither is a shipped SDK today.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/does-traverse-support-windows-macos-and-linux.html', label: 'Does Traverse support Windows, macOS, and Linux?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/blog/native-ios-runtime-foundation.html', label: 'Native iOS without a JIT: a hands-on feasibility proof' }, + { href: '/questions/what-is-traverse-roadmap.html', label: 'What is the Traverse roadmap?' }, +]; +--- + +

Not as a shipped, public path today — and we'd rather tell you that up front than have you find out after committing to it. Traverse's mature, shipped targets are native (Windows, macOS, Linux) and the browser. Mobile is genuinely being worked on, but "in progress" and "blocked" mean different things, and it matters which one applies to which platform.

+ +

Android — in progress, unreleased

+

packages/kotlin/TraverseEmbedder has a working ChicoryRuntimeBridge pinned to a specific Chicory version. Bundle validation and lifecycle types are in place. What's missing is Compose reference-app integration, which is tracked by its own open issue, and a public release. If you want to help move it forward, that issue is the place to look.

+ +

iOS — blocked, not just unfinished

+

This one is stuck on something outside the project's control, not a backlog item waiting its turn. As of the last candidate engine screen, none of WasmKit, WAMR, Wasmtime, or Wasmer exposed the public, documented resource-control APIs a certified native embedder baseline requires — for reasons ranging from missing resource-control APIs to no supported iOS profile to JIT/entitlement conflicts with App Store distribution.

+

A separate feasibility spike found a workaround: embedding the wasmi interpreter directly through a Rust static library and a narrow C-compatible bridge, with the host enforcing memory and fuel limits, verified running on a physical iPhone. That's a real, working proof — we wrote up the full technical detail — but it's a foundation for a future runtime path, not a shipped SDK you can npm-install or add via Swift Package Manager today.

+ +

.NET / WinUI — in progress, unreleased

+

The same shape as Android: packages/dotnet/TraverseEmbedder has a working Wasmtime .NET-backed bridge. Request marshalling, event subscriptions, evidence publication, and the shared conformance suite are still open work.

+ +

If your app's core problem is mobile UI, Traverse isn't that tool yet. If you're building a desktop or browser app today and want the same governed business logic ready to extend to mobile once these ship, the contract you write now doesn't change when the mobile embedder does. Track live status on the Platforms page — it's the same page we link internally, not a separate marketing version.

+
diff --git a/src/pages/questions/can-traverse-capabilities-call-native-os-apis.astro b/src/pages/questions/can-traverse-capabilities-call-native-os-apis.astro new file mode 100644 index 0000000..5e6f7a1 --- /dev/null +++ b/src/pages/questions/can-traverse-capabilities-call-native-os-apis.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can Traverse capabilities call native OS APIs?', + acceptedAnswer: { + '@type': 'Answer', + text: "Not directly, and that's by design — it's what keeps a capability portable. A capability can only reach outside the WASM sandbox through host calls the contract explicitly declares and the host explicitly implements. If you need OS-level access, you declare the specific host call in the contract, implement it once in your host application, and the capability's own code stays exactly as portable as before.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/questions/what-is-a-contract-in-traverse.html', label: 'What is a contract in Traverse?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/what-is-traverse-security-model.html', label: "What is Traverse's security model?" }, +]; +--- + +

Not directly, and it's worth understanding why that's a feature rather than a limitation someone forgot to fix. A capability runs inside the WASM sandbox, which by default has no visibility into the host operating system at all — no raw filesystem calls, no OS-specific APIs, nothing. If it could call native OS functions directly, the whole reason it can move between Windows, macOS, and Linux without changes would disappear, because now its behavior would depend on which OS's API surface it happened to call.

+ +

What a capability can do is declare, in its contract, that it needs a specific host call — a named function the host application implements and exposes across the sandbox boundary. The capability calls that named function; it has no idea (and doesn't need to know) whether the host implements it using a Windows API, a POSIX call, or something else entirely on each platform. The OS-specific branching, if any exists at all, lives in the host application's implementation of that one host call, not scattered through the capability's logic.

+ +

An example of where this matters

+

Say a capability genuinely needs the current system time zone. Rather than reaching for an OS-specific time API, its contract declares a host_calls entry like "system.timezone". The host application — which does know what OS it's running on — implements that one function however is appropriate per platform. The capability's code, and its portability, never changes.

+
diff --git a/src/pages/questions/do-different-operating-systems-see-different-behavior-from-the-same-capability.astro b/src/pages/questions/do-different-operating-systems-see-different-behavior-from-the-same-capability.astro new file mode 100644 index 0000000..13b5b14 --- /dev/null +++ b/src/pages/questions/do-different-operating-systems-see-different-behavior-from-the-same-capability.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Can different operating systems see different behavior from the same capability?', + acceptedAnswer: { + '@type': 'Answer', + text: "Not from the capability's own logic, which is sandboxed WASM with no OS-visible branching. The one place behavior can legitimately differ is in a host-implemented call the capability's contract declares — if the host implements that call differently per OS, that's a property of the host's implementation, not of the capability, and it's visible in the contract as a named dependency rather than hidden.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/can-traverse-capabilities-call-native-os-apis.html', label: 'Can Traverse capabilities call native OS APIs?' }, + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/questions/how-do-ci-pipelines-test-traverse-across-operating-systems.html', label: 'How does Traverse verify cross-OS behavior actually matches?' }, + { href: '/questions/what-is-a-contract-in-traverse.html', label: 'What is a contract in Traverse?' }, +]; +--- + +

The capability's own code can't see which OS it's running on, so it structurally can't branch on it — there's no API inside the WASM sandbox that exposes "what operating system is this," and nothing to condition behavior on even if a developer wanted to. Given the same input and the same contract, a capability's own logic produces the same output regardless of host OS, because that logic has no OS-dependent path to take.

+ +

The one legitimate exception

+

If a capability's contract declares a host call — something like a system clock read or a lookup the host implements — then the behavior of that specific call depends on how the host application implements it, and a host implementation genuinely could differ across operating systems (a timezone lookup implemented one way on Windows and another on Linux, say). That's not the capability behaving inconsistently; it's a declared external dependency whose implementation is the host's responsibility, and it's visible in the contract's host_calls list rather than buried invisibly in the capability's logic.

+ +

In practice, most well-scoped capabilities (pricing rules, eligibility checks, validation logic) have no legitimate reason to declare any host calls at all, which is exactly what keeps them behaviorally identical everywhere. If you're seeing inconsistent results across operating systems for the same capability and the same input, the contract's declared dependencies — not the capability's own logic — are the first place to look.

+
diff --git a/src/pages/questions/does-traverse-support-windows-macos-and-linux.astro b/src/pages/questions/does-traverse-support-windows-macos-and-linux.astro new file mode 100644 index 0000000..17f7899 --- /dev/null +++ b/src/pages/questions/does-traverse-support-windows-macos-and-linux.astro @@ -0,0 +1,43 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Does Traverse support Windows, macOS, and Linux?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes. Native — Linux, macOS, and Windows — is Traverse's default and most mature target. traverse-runtime's NativeExecutor, ThreadPoolExecutor, and Wasmtime-backed WasmExecutor all run the same way on each OS, and a capability's WASM binary needs no OS-specific code or build flag to move between them.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/can-traverse-run-without-wasm.html', label: 'Can Traverse run without WASM?' }, + { href: '/questions/what-is-the-traverse-cli.html', label: 'What is the Traverse CLI?' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, +]; +--- + +

Yes, and it's the target Traverse is built around first. traverse-runtime ships a NativeExecutor, a ThreadPoolExecutor, and a Wasmtime-backed WasmExecutor for sandboxed capability execution — all of it running identically whether the host is Linux, macOS, or Windows. There's no OS-specific branch in your capability code and no separate build target per operating system; you compile the capability to WASM once, and the same binary is what every native host executes.

+ +

This is also what the CLI itself runs on, and what every quickstart walks through. If you clone the traverse repo and run cargo build on any of the three, you're building and exercising the exact same code path.

+ +

What "supports" means here specifically

+

Native support covers full orchestration: registering capabilities into the registry, discovering them by contract, validating inputs and outputs, executing the WASM binary in a sandbox, emitting declared events, and writing a trace artifact. None of that is stubbed or partial on any of the three operating systems — it's the same crate, the same code, the same behavior.

+ +

What native support does not mean is a native GUI toolkit. Traverse governs the logic layer; it doesn't paint windows. If you're pairing it with a UI, you'll bring your own — the Traverse vs. cross-platform app frameworks comparison walks through what that pairing looks like with Tauri specifically.

+ +

Where the story is different

+

Mobile is not the same shipped status as desktop. Android and .NET/WinUI have real, working runtime bridges in progress with no public release yet, and iOS is currently blocked on the WASM engine ecosystem lacking a certifiable resource-control API for App Store distribution. See the Platforms page for the full breakdown with links to the actual blocking issues.

+
diff --git a/src/pages/questions/does-traverse-work-offline.astro b/src/pages/questions/does-traverse-work-offline.astro new file mode 100644 index 0000000..a65c9e7 --- /dev/null +++ b/src/pages/questions/does-traverse-work-offline.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Does Traverse work offline?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Yes, for the capability execution itself — a capability executes locally by default, on whatever client loaded it, with no network round trip required to run the WASM binary, validate its contract, or produce a trace. Native and browser executors both run entirely on-device unless a capability specifically declares and is granted network access.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-does-device-independent-mean-in-traverse.html', label: 'What does "device-independent" mean in Traverse?' }, + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/questions/how-do-placement-targets-work.html', label: 'How do placement targets work in Traverse?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, +]; +--- + +

Yes, and this follows directly from how execution is modeled, not as a special offline mode bolted on afterward. A Traverse capability is device-independent: it executes locally, on whatever client loaded it, by default. There's no built-in requirement to phone home to a server to run the WASM binary, validate its contract, or generate a trace artifact — all of that happens in-process, on the machine that's already holding the bundle.

+ +

Concretely: the native executor runs entirely on the host it's installed on. The browser embedder, once it's loaded a bundle and its WASM module, executes that capability directly in the browser's own WebAssembly host — no request leaves the machine unless the capability's own logic makes one.

+ +

The one place network involvement is real

+

If a capability's contract declares network_access as required — because the rule genuinely needs to call out to something, a tax rate table or an external lookup — then yes, that specific capability needs connectivity for that specific call. That's a property of the capability, not of the runtime generally, and it's visible in the contract before you ever run it, rather than a surprise at execution time. Most capabilities, especially the pricing/eligibility/validation category this project is built around, have no legitimate reason to need network access at all, and their contracts reflect that with network_access: forbidden.

+ +

Worth noting separately: the client's ability to heuristically delegate part of a capability's work to a server (covered in what "device-independent" means) is an optional decision the client can make based on its own context — not a requirement. Offline, that heuristic simply doesn't fire, and execution stays local.

+
diff --git a/src/pages/questions/how-do-ci-pipelines-test-traverse-across-operating-systems.astro b/src/pages/questions/how-do-ci-pipelines-test-traverse-across-operating-systems.astro new file mode 100644 index 0000000..9b0b02c --- /dev/null +++ b/src/pages/questions/how-do-ci-pipelines-test-traverse-across-operating-systems.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How does Traverse verify a capability actually behaves the same across operating systems?', + acceptedAnswer: { + '@type': 'Answer', + text: 'The v1.0 milestone gates explicitly require a five-platform CI stress matrix, alongside 100% coverage on governed paths and zero open P0/P1 bugs, before that claim is considered fully proven rather than architecturally expected. As of the current release, core crates are coverage-gated, but the full cross-platform CI matrix is one of the gates not yet met as a complete set.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/is-traverse-production-ready.html', label: 'Is Traverse production ready?' }, + { href: '/questions/what-is-traverse-roadmap.html', label: 'What is the Traverse roadmap?' }, + { href: '/questions/does-traverse-support-windows-macos-and-linux.html', label: 'Does Traverse support Windows, macOS, and Linux?' }, + { href: '/security-audit.html', label: 'Security audit' }, +]; +--- + +

It's a fair thing to be skeptical about: "the same binary runs identically everywhere" is an architectural claim, and architectural claims are exactly the kind of thing that should be verified rather than asserted. Traverse's own v1.0 milestone treats it that way — a five-platform CI stress matrix is one of ten explicit, named gates the project has set for calling itself v1.0, alongside every crate published on crates.io, an MCP library surface beyond the stdio subprocess, 100% coverage on governed paths, and zero open P0/P1 bugs.

+ +

As of the current release, the honest state is partial: traverse-contracts, traverse-registry, and traverse-runtime are coverage-gated in CI, meaning their core logic can't merge without passing tests. The full five-platform stress matrix is not yet in place as a complete gate — it's tracked, named, and required before v1.0, not silently assumed to already be true.

+ +

Why this matters more than it might seem

+

A framework that claims cross-platform consistency without a CI matrix actually exercising every claimed platform is trusting the architecture to hold, not proving it does on every release. Naming the gap explicitly — as the v1.0 milestone does — is different from pretending it's already closed. If cross-platform reliability is load-bearing for your decision, that's a real, fair thing to weigh, and the roadmap is where to watch it close rather than assume it already has.

+
diff --git a/src/pages/questions/how-do-i-avoid-rewriting-business-logic-for-every-platform.astro b/src/pages/questions/how-do-i-avoid-rewriting-business-logic-for-every-platform.astro new file mode 100644 index 0000000..81520e3 --- /dev/null +++ b/src/pages/questions/how-do-i-avoid-rewriting-business-logic-for-every-platform.astro @@ -0,0 +1,43 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How do I avoid rewriting business logic for every platform?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Compile the logic once to a WASM binary, attach a machine-readable contract describing its inputs, outputs, and required conditions, and let a runtime that understands that contract execute the same binary on every platform instead of reimplementing the logic in each platform’s native language.', + }, + }], +}); + +const relatedLinks = [ + { href: '/blog/logic-duplication.html', label: 'Why I stopped writing the same business logic four times' }, + { href: '/blog/wasm-business-logic.html', label: 'What WASM actually gives you for business logic' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/what-is-a-contract-in-traverse.html', label: 'What is a contract in Traverse?' }, +]; +--- + +

The usual failure mode looks like this: a pricing rule starts in the backend. Someone needs it in the frontend for instant feedback, so it gets reimplemented in JavaScript. Then the mobile app needs it, so it's rewritten again in Swift or Kotlin. Then an AI agent or a data pipeline needs it, and now there are four copies of the same rule, in four languages, maintained by however many people remembered to update all four when the tax rate changed. They drift. Bugs show up in one copy and not another. Nobody's entirely sure which copy is the real one.

+ +

The structural fix isn't discipline or documentation — it's removing the possibility of a second copy existing. Compile the rule once, to a format that isn't tied to any single host language, and make every caller execute that same artifact instead of their own reimplementation.

+ +

What that looks like concretely

+

WebAssembly is the format that makes this practical: it's a binary instruction format any conformant runtime can execute, independent of the language it was compiled from or the host it runs in. Traverse adds the two pieces raw WASM doesn't give you — a contract (what the capability needs, what it guarantees, what must be true before and after it runs) and a runtime that enforces that contract on every single execution, not just the first one someone tested.

+ +

Concretely: you write the rule once in Rust, compile it to a WASM capability, and register it. From then on, your web app, your backend, your mobile app (where a shipped embedder exists), and an AI agent over MCP all call the same binary and get the same enforced result. There's no second implementation to drift, because there's no second implementation.

+ +

What this doesn't solve

+

It doesn't remove the need for platform-specific UI — you still build a native-feeling frontend for each platform if that's what your product needs. And it isn't free: writing a contract and thinking through preconditions and postconditions is more upfront work than just calling a function. It's worth it specifically for the logic that's genuinely shared, genuinely important, and genuinely getting reimplemented right now. If a rule only ever lives in one place, none of this applies — see why I stopped writing the same business logic four times for the fuller version of this argument.

+
diff --git a/src/pages/questions/how-do-i-choose-between-a-progressive-web-app-and-traverse.astro b/src/pages/questions/how-do-i-choose-between-a-progressive-web-app-and-traverse.astro new file mode 100644 index 0000000..cb305e8 --- /dev/null +++ b/src/pages/questions/how-do-i-choose-between-a-progressive-web-app-and-traverse.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Should I build a Progressive Web App or use Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: "They're not alternatives — a PWA is a delivery model for your UI (any device with a browser, installable, offline-capable to varying degrees), while Traverse governs the business logic underneath any UI, PWA included. A PWA's frontend can call a Traverse capability through the Web embedder SDK the same way any browser-hosted app does.", + }, + }], +}); + +const relatedLinks = [ + { href: '/blog/cross-platform-rarely-means-what-it-sounds-like.html', label: 'Why "cross-platform" rarely means what it sounds like' }, + { href: '/questions/does-traverse-work-offline.html', label: 'Does Traverse work offline?' }, + { href: '/questions/what-is-the-browser-adapter.html', label: 'What is the browser adapter?' }, + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, +]; +--- + +

This isn't really an either/or, because a PWA and Traverse answer different questions. A Progressive Web App is a delivery and packaging model: your web app becomes installable, gets an app icon, and can work offline to whatever degree the specific browser and OS combination supports — with real, honestly-should-be-mentioned variance, since PWA capability support (background sync, push notifications, install prompts) differs meaningfully between, say, desktop Chrome and iOS Safari.

+ +

Traverse doesn't compete with any of that — it has no opinion on how your app gets installed or delivered. What it governs is the logic your PWA's frontend calls into. That logic is a WASM capability with an enforced contract, loadable directly through the Web embedder SDK, which is exactly the same mechanism any browser-hosted app uses — a PWA is still, under the hood, a web page, so nothing about "progressive" changes how it talks to a Traverse capability.

+ +

Where this actually helps a PWA specifically

+

PWAs lean hard on working offline, and Traverse capabilities execute locally by default with no network round trip required — see does Traverse work offline. That's a natural fit: a PWA's offline-first UI calling a capability that's also, by construction, offline-capable, rather than a UI promising offline behavior undermined by logic that secretly needs a server round trip.

+
diff --git a/src/pages/questions/how-do-i-package-a-capability-for-multiple-platforms.astro b/src/pages/questions/how-do-i-package-a-capability-for-multiple-platforms.astro new file mode 100644 index 0000000..56ec9c7 --- /dev/null +++ b/src/pages/questions/how-do-i-package-a-capability-for-multiple-platforms.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How do I package a capability for multiple platforms?', + acceptedAnswer: { + '@type': 'Answer', + text: "You don't package it differently per platform — that's the point of compiling to WASM. You build the capability once into a registry bundle (a manifest plus its contract, WASM module, and any events or workflows it participates in), and the same bundle is what every executor — native or browser — loads. Platform-specific packaging only exists one layer up, in the host application that embeds Traverse.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-the-capability-registry.html', label: 'What is the capability registry?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/docs/concepts.html', label: 'Core Concepts: Traverse Docs' }, +]; +--- + +

You don't, in the sense of maintaining separate build outputs per target — and that's a deliberate design choice, not an oversight. A capability's WASM binary and its contract are compiled once and grouped, along with any events or workflows it participates in, into a registry bundle: a manifest plus a capabilities/ directory holding each capability's contract and module. That bundle is what gets loaded, unchanged, by whichever executor is running it — the native WasmExecutor or the browser's Web embedder SDK.

+ +

The CLI validates a bundle before it's registered, and that validation doesn't vary by target platform either, because the bundle itself has no platform-specific content to validate differently.

+ +

Where platform-specific packaging actually happens

+

It exists, just one layer up — in the host application, not in the capability. A native desktop app embedding traverse-embedder gets built and distributed the normal way for Windows, macOS, or Linux (an installer, a container image, a plain binary). A web app loads the same bundle through the Web embedder SDK as a static asset served alongside the rest of your frontend. Neither of those steps touches or duplicates the bundle itself — they just point their respective executor at the same file.

+ +

Practically: build your bundle once with cargo run -p traverse-cli-rs -- bundle inspect (or the equivalent build step for your capability), confirm it validates, and treat "does this run on platform X" as a question about whether an executor for X exists yet — see Platforms — not a question about whether you need a platform-specific build of your own capability.

+
diff --git a/src/pages/questions/how-do-i-share-business-logic-between-web-and-desktop.astro b/src/pages/questions/how-do-i-share-business-logic-between-web-and-desktop.astro new file mode 100644 index 0000000..7bbe20c --- /dev/null +++ b/src/pages/questions/how-do-i-share-business-logic-between-web-and-desktop.astro @@ -0,0 +1,41 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How do I share business logic between a web app and a desktop app?', + acceptedAnswer: { + '@type': 'Answer', + text: "Write the rule once as a Traverse capability, compile it to WASM with a contract, and let your web app load it through the Web embedder SDK or local browser adapter while your desktop app loads the identical bundle through a native embedder — most naturally traverse-embedder inside a Tauri app if you want both in Rust end to end.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.html', label: 'Can I run the same business logic in a browser app and a native app?' }, + { href: '/questions/can-i-use-traverse-with-tauri.html', label: 'Can I use Traverse with Tauri?' }, + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, + { href: '/docs/guides/react-integration.html', label: 'React Integration guide' }, +]; +--- + +

This is the exact shape of problem Traverse was built around, so the answer is fairly direct: write the rule once as a Rust capability, compile it to a WASM binary, attach a contract, and register it into a bundle. From there, your web app and your desktop app each load that one bundle through whichever executor matches their host — they're not two implementations that happen to agree, they're one implementation two hosts both call.

+ +

The web side

+

Your web frontend talks to the capability either through the local browser adapter over a simple HTTP request (the pattern the React integration guide covers step by step) or, for a single pre-published capability, directly through the Web embedder SDK's verified execution path in the browser's native WASM host.

+ +

The desktop side

+

Your desktop app embeds the same bundle through a native host. If you're building that desktop app in Tauri, this is close to seamless — Tauri's backend is already Rust, so a Tauri command calls straight into the public traverse-embedder crate with no bridge in between (see the worked example in the Traverse vs. cross-platform frameworks comparison). If your desktop app is Electron, its renderer is a Chromium page and can use the same Web embedder path the browser app uses.

+ +

Either way, the guarantee you get is structural, not procedural: the web app and the desktop app can't drift apart on this rule, because there's no second copy of it to drift.

+
diff --git a/src/pages/questions/how-do-i-test-a-capability-before-shipping-it-to-multiple-platforms.astro b/src/pages/questions/how-do-i-test-a-capability-before-shipping-it-to-multiple-platforms.astro new file mode 100644 index 0000000..bd4689d --- /dev/null +++ b/src/pages/questions/how-do-i-test-a-capability-before-shipping-it-to-multiple-platforms.astro @@ -0,0 +1,43 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How do I test a capability before shipping it to multiple platforms?', + acceptedAnswer: { + '@type': 'Answer', + text: "Test the capability once, against its contract, independent of any platform — since the sandboxed WASM binary has no OS-dependent behavior to test per platform in the first place. Validate the bundle with the CLI, exercise it through the native executor with representative inputs, and check the trace output; a capability with no declared host calls needs no further per-OS test pass beyond confirming the executor itself works on that host.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-do-ci-pipelines-test-traverse-across-operating-systems.html', label: 'How does Traverse verify cross-OS behavior actually matches?' }, + { href: '/questions/do-different-operating-systems-see-different-behavior-from-the-same-capability.html', label: 'Can different operating systems see different behavior from the same capability?' }, + { href: '/questions/what-is-a-trace-artifact.html', label: 'What is a trace artifact in Traverse?' }, + { href: '/docs/guides/cross-os-capability.html', label: 'Write once, run on Windows, macOS, Linux, and the browser' }, +]; +--- + +

The reassuring answer is that "test it for each platform" mostly collapses into "test it once," because a capability with no declared host calls has no OS-dependent code path for a platform-specific test to catch. Your test plan should center on the contract, not the target.

+ +

What to actually test

+ + +

What's left to test per platform

+

Realistically, very little: that the executor itself is correctly installed and configured on that host (a native binary that runs, a browser embedder that loads), and — if the capability's contract declares any host calls — that the specific host implementation of those calls behaves correctly on that platform, since that's the one place OS-specific code could legitimately exist. For a capability with an empty host_calls list, there's genuinely nothing else to test per OS beyond confirming the runtime environment itself is set up. The cross-OS capability guide shows this in practice, comparing trace output from a native run against a browser run of the same bundle.

+
diff --git a/src/pages/questions/how-does-versioning-work-across-platforms.astro b/src/pages/questions/how-does-versioning-work-across-platforms.astro new file mode 100644 index 0000000..143fdab --- /dev/null +++ b/src/pages/questions/how-does-versioning-work-across-platforms.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How does capability versioning work when it runs on multiple platforms?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Versioning belongs to the capability and its contract, not to any particular host platform — there is exactly one version number, tracked in the registry, regardless of how many executors (native, browser) load that version. A native host and a browser host can be pinned to different versions of the same capability id if they update on different schedules, but neither host maintains its own separate version history.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-contract-versioning.html', label: 'What is contract versioning in Traverse?' }, + { href: '/questions/what-is-the-capability-registry.html', label: 'What is the capability registry?' }, + { href: '/questions/what-is-the-contract-lifecycle.html', label: 'What is the contract lifecycle in Traverse?' }, + { href: '/questions/can-i-run-the-same-business-logic-in-browser-and-native-apps.html', label: 'Can I run the same business logic in a browser app and a native app?' }, +]; +--- + +

Versioning is a property of the capability and the registry entry that tracks it — namespace.name plus a semantic version — not something each host platform tracks independently. There's one version history for a given capability id, whether it's ever loaded by a native executor, a browser embedder, both, or eventually a mobile one.

+ +

What can legitimately differ between hosts is which version each one has currently pinned. A native backend might already be running pricing.eligibility-check@2.1.0 while a browser deployment is still serving 2.0.0, if the rollout schedules haven't caught up with each other. That's a normal, visible fact about your deployment — the trace artifact for each execution records exactly which version ran — not a hidden inconsistency.

+ +

Why this matters for cross-platform rollout

+

Because versioning lives with the capability, not the platform, a breaking contract change is a single decision with a single new version number, applied everywhere at once conceptually — you then choose, per host, when to actually adopt it. There's no scenario where "the Windows version of this rule" and "the browser version of this rule" silently diverge into separately-numbered lineages; if they're both running capability X, they're both running some version of the same tracked history, and you can always tell which one from the trace.

+
diff --git a/src/pages/questions/how-is-traverse-different-from-a-shared-rust-library.astro b/src/pages/questions/how-is-traverse-different-from-a-shared-rust-library.astro new file mode 100644 index 0000000..7b17a11 --- /dev/null +++ b/src/pages/questions/how-is-traverse-different-from-a-shared-rust-library.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: "Why not just put the business logic in a shared Rust library instead of using Traverse?", + acceptedAnswer: { + '@type': 'Answer', + text: "A shared Rust crate gets you code reuse across Rust callers, but every non-Rust host still needs an FFI binding, there's no enforced contract, and there's no execution trace. A Traverse capability compiles to WASM instead of a native library, so any WASM-hosting caller — Rust, JavaScript, an AI agent over MCP — invokes the exact same binary through one interface, with preconditions and postconditions enforced and every execution recorded.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-do-i-avoid-rewriting-business-logic-for-every-platform.html', label: 'How do I avoid rewriting business logic for every platform?' }, + { href: '/questions/what-is-a-contract-in-traverse.html', label: 'What is a contract in Traverse?' }, + { href: '/questions/what-is-a-trace-artifact.html', label: 'What is a trace artifact in Traverse?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, +]; +--- + +

It's a fair question, because a plain shared library is the simpler-sounding answer to "stop duplicating this logic." Put the pricing rule in a crate, publish it internally, have every Rust service depend on it. For a team that's 100% Rust and never needs the rule outside that ecosystem, that's a reasonable, lighter-weight choice — genuinely, don't reach for Traverse if that's your whole situation.

+ +

The gap shows up at the edges. A shared crate is native code: your JavaScript frontend, your Python data pipeline, and your AI agent can't call it directly. Each of those needs its own FFI binding, a WASM build of the crate compiled separately, or a network hop to a service that wraps it — and now you're maintaining integration surface for every non-Rust caller. A crate also has no built-in contract: nothing stops a caller from passing invalid input, and nothing records what actually happened when it ran, beyond whatever logging you added yourself.

+ +

What a Traverse capability does differently

+

A capability compiles to WebAssembly instead of a native library, so it's not Rust-caller-only — any WASM-hosting environment can load it: a browser, a native host through traverse-embedder, an AI agent through MCP, all through the same interface. The contract attached to it declares preconditions and postconditions the runtime actually enforces, not just documents. And every execution produces a trace artifact — what ran, with what inputs, validated against which contract, with what result.

+ +

The honest tradeoff: a contract is more upfront work than a public function signature, and there's real WASM sandboxing overhead compared to a direct native call. Worth it specifically when the rule needs to be called from outside Rust, needs enforced correctness, or needs an audit trail. Not worth it for logic that's genuinely internal to one Rust service.

+
diff --git a/src/pages/questions/how-is-traverse-different-from-docker.astro b/src/pages/questions/how-is-traverse-different-from-docker.astro new file mode 100644 index 0000000..20f822f --- /dev/null +++ b/src/pages/questions/how-is-traverse-different-from-docker.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How is Traverse different from Docker?', + acceptedAnswer: { + '@type': 'Answer', + text: "Docker packages an entire environment — OS layer, dependencies, runtime — so a service behaves consistently across hosts, at the cost of shipping megabytes to gigabytes per image and needing a container runtime everywhere it runs. Traverse capabilities are WASM binaries, typically kilobytes, with no OS layer at all, governed by a contract instead of an image manifest, and able to run inside a browser tab — somewhere a container fundamentally cannot.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-serverless.html', label: 'Traverse vs Serverless Functions' }, + { href: '/compare/vs-microservices.html', label: 'Traverse vs Microservices' }, + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, +]; +--- + +

Both Docker and Traverse are answers to "make this run consistently somewhere else," but they solve it at completely different layers. Docker packages an entire environment — the OS userland, your dependencies, your runtime, your app — into an image, so the same image behaves the same way on any host with a compatible container runtime installed. That's a heavyweight but very general solution: it works for basically any application, regardless of language or architecture.

+ +

A Traverse capability doesn't package an environment at all — it doesn't need one. It's a WASM binary, sandboxed by the WASM spec itself rather than by container namespaces, with no OS layer, no base image, and typically no dependency footprint beyond what the sandbox already provides. Where a minimal container image is tens of megabytes, a Traverse capability is usually kilobytes.

+ +

The one Docker structurally cannot do

+

A container needs a container runtime — Docker Engine, containerd, something implementing the OCI spec — running on the host. That rules out running a container inside a browser tab, full stop. A Traverse capability runs there today, through the Web embedder SDK, because a WASM binary only needs a WASM host, and every modern browser already is one.

+ +

They're also governed differently: a container's contract with the world is effectively "this image, this entrypoint, these exposed ports" — no built-in enforcement of what the code inside actually does to its inputs. A Traverse capability's contract declares preconditions, postconditions, and permissions, and the runtime checks all of it on every execution, producing a trace. If you need "runs the same everywhere, including places without a container runtime, with enforced input/output guarantees," that's the Traverse case. If you need "package this entire arbitrary service so ops can deploy it anywhere," that's still Docker's job — and the two aren't mutually exclusive; a Traverse-embedding service can absolutely ship inside a container.

+
diff --git a/src/pages/questions/how-is-traverse-different-from-dotnet-maui.astro b/src/pages/questions/how-is-traverse-different-from-dotnet-maui.astro new file mode 100644 index 0000000..5c7f499 --- /dev/null +++ b/src/pages/questions/how-is-traverse-different-from-dotnet-maui.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How is Traverse different from .NET MAUI?', + acceptedAnswer: { + '@type': 'Answer', + text: ".NET MAUI shares one XAML-based UI layer across Windows, macOS, iOS, and Android, all shipped and mature. Traverse has no UI layer — it governs the business logic underneath, as a WASM capability callable from a MAUI app, a backend, or an AI agent alike. Traverse's own .NET/WinUI embedder is real, working code, but unreleased, which is worth knowing if you're specifically looking to pair the two today.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri (full comparison)' }, + { href: '/questions/can-i-use-traverse-with-dotnet-maui.html', label: 'Can I use Traverse with .NET MAUI today?' }, + { href: '/questions/how-is-traverse-different-from-flutter.html', label: 'How is Traverse different from Flutter?' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, +]; +--- + +

.NET MAUI is Microsoft's answer to shipping one UI codebase across Windows, macOS, iOS, and Android, using a shared XAML-based layer over each platform's native controls. It's a mature, shipped UI framework, with all four of those platforms genuinely supported today.

+ +

Traverse doesn't have a UI layer to compare against MAUI's at all. What it governs is the logic behind whatever UI you're using — the rule that runs when a MAUI page's button is tapped. That logic compiles once to a WASM capability with an enforced contract, callable identically from the MAUI app, a backend service, or an AI agent, rather than being C# code that only exists inside that one app.

+ +

The honest caveat if you want to pair them today

+

Calling a Traverse capability directly from a MAUI app on iOS or Android runs into the same mobile-embedder status covered elsewhere on this site: the .NET/WinUI embedder (built on a Wasmtime .NET bridge) is real, working code, but it's unreleased, and it's specifically the Windows/WinUI side of .NET — not yet the cross-platform MAUI runtime targeting iOS and Android. So pairing the two cleanly on Windows desktop is closer than pairing them on MAUI's mobile targets today. See Platforms for the exact, current state before you plan around it.

+
diff --git a/src/pages/questions/how-is-traverse-different-from-electron.astro b/src/pages/questions/how-is-traverse-different-from-electron.astro new file mode 100644 index 0000000..6a9bb08 --- /dev/null +++ b/src/pages/questions/how-is-traverse-different-from-electron.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How is Traverse different from Electron?', + acceptedAnswer: { + '@type': 'Answer', + text: "Electron ships a desktop app by bundling Chromium and Node.js, so your JavaScript logic and your UI both live inside that one packaged app. Traverse has no UI or app-shell layer — it's a contract-governed WASM runtime for the logic behind whatever shell you use, whether that's Electron, a web app, a CLI, or an AI agent, all calling the same binary.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri (full comparison)' }, + { href: '/questions/how-is-traverse-different-from-flutter.html', label: 'How is Traverse different from Flutter?' }, + { href: '/questions/what-is-the-browser-adapter.html', label: 'What is the browser adapter?' }, + { href: '/blog/wasm-business-logic.html', label: 'What WASM actually gives you for business logic' }, +]; +--- + +

Electron solves desktop packaging: it bundles Chromium and Node.js so a web app can ship as a native-feeling Windows, macOS, or Linux application, with your JavaScript running the UI and the logic behind it in the same process. That's a genuinely useful, mature approach, and it's why so many desktop tools (VS Code among them) are built on it.

+ +

Traverse isn't a packaging tool and doesn't produce an app shell at all. It's a runtime for one specific layer: business logic that needs to behave identically no matter what's calling it. You write a capability in Rust, compile it to WASM, attach a contract, and the runtime enforces that contract before and after every execution — whether the caller is an Electron app, a plain web page, a CLI, or an AI agent over MCP.

+ +

The practical difference

+

In Electron, your business logic is just more JavaScript inside the bundle — no separate enforcement, no built-in trace of what ran and why, and no path to reuse that logic from a non-Electron caller without copying the code. In Traverse, the logic is a WASM binary with a machine-readable contract, discoverable through a registry, producing a structured trace on every execution, and callable identically from Electron or from anywhere else.

+ +

They're not mutually exclusive. An Electron app can call into a Traverse capability the same way a browser tab does — through the browser adapter or an embedder — for the specific rules where consistency and auditability actually matter, while Electron keeps doing the packaging and windowing work it's built for. The full comparison covers the pattern in more depth, with a concrete example using Tauri (Electron's Rust-based sibling).

+
diff --git a/src/pages/questions/how-is-traverse-different-from-flutter.astro b/src/pages/questions/how-is-traverse-different-from-flutter.astro new file mode 100644 index 0000000..fe59add --- /dev/null +++ b/src/pages/questions/how-is-traverse-different-from-flutter.astro @@ -0,0 +1,41 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'How is Traverse different from Flutter?', + acceptedAnswer: { + '@type': 'Answer', + text: "Flutter is a UI framework: it renders a widget tree to native-feeling screens on Windows, macOS, Linux, iOS, Android, and the web from one Dart codebase. Traverse has no UI layer at all — it governs the business logic underneath any UI, as a contract-enforced WASM capability that's also callable from a backend, a CLI, or an AI agent, not just from inside one Flutter app.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri (full comparison)' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/how-is-traverse-different-from-a-plugin-system.html', label: 'How is Traverse different from a plugin system?' }, + { href: '/questions/what-is-a-wasm-capability.html', label: 'What is a WASM capability in Traverse?' }, +]; +--- + +

Flutter and Traverse aren't really in the same category, even though they both get pulled into "cross-platform" conversations. Flutter is a UI framework: you write widgets in Dart, and Flutter's engine renders them consistently on Windows, macOS, Linux, iOS, Android, and the web. It's shipped, mature, and genuinely good at exactly that.

+ +

Traverse has no rendering engine and no widget system. What it governs is what happens behind the UI — the pricing calculation, the eligibility check, the validation rule your Flutter app's button press eventually calls into. That logic compiles once to WebAssembly with a machine-readable contract, and the same binary is callable from your Flutter app, your backend, your CLI, or an MCP-connected AI agent, all getting the identical result because it's the identical binary — not a Dart implementation and a separate server-side reimplementation that can drift apart.

+ +

Where the OS-reach honestly differs

+

Worth saying directly: Flutter's OS coverage is broader today. It ships on desktop, mobile, and web, all mature. Traverse's device-independent WASM capabilities run natively on Windows, macOS, and Linux and in the browser today; Android and .NET/WinUI embedders are in progress without a public release, and iOS is blocked on the WASM engine ecosystem. See Platforms for the specifics.

+ +

Using them together

+

A Flutter app can call into a Traverse capability the same way any other host does — through an embedder or an HTTP adapter, depending on the target. The Flutter shell keeps rendering the UI it's good at; the rule underneath gets a contract, an enforcement point, and a trace artifact it wouldn't otherwise have. The full breakdown, including a concrete integration example, is on the Traverse vs. cross-platform app frameworks comparison page.

+
diff --git a/src/pages/questions/index.astro b/src/pages/questions/index.astro index ca49212..2fd466b 100644 --- a/src/pages/questions/index.astro +++ b/src/pages/questions/index.astro @@ -59,6 +59,53 @@ const groups = [ ['what-is-contract-driven-ai-development.html', 'What is contract-driven AI development?'], ], }, + { + label: 'Platforms and portability', + items: [ + ['what-framework-runs-business-logic-on-any-os.html', 'What framework lets me write business logic once and run it on any OS?'], + ['does-traverse-support-windows-macos-and-linux.html', 'Does Traverse support Windows, macOS, and Linux?'], + ['what-operating-systems-does-traverse-support.html', 'What operating systems does Traverse support?'], + ['can-traverse-build-mobile-apps.html', 'Can I build a mobile app with Traverse?'], + ['what-does-device-independent-mean-in-traverse.html', 'What does "device-independent" mean in Traverse?'], + ['how-do-i-avoid-rewriting-business-logic-for-every-platform.html', 'How do I avoid rewriting business logic for every platform?'], + ['how-is-traverse-different-from-flutter.html', 'How is Traverse different from Flutter?'], + ['how-is-traverse-different-from-electron.html', 'How is Traverse different from Electron?'], + ['can-i-use-traverse-with-tauri.html', 'Can I use Traverse with Tauri?'], + ['can-i-use-traverse-with-electron.html', 'Can I use Traverse with Electron?'], + ['how-is-traverse-different-from-dotnet-maui.html', 'How is Traverse different from .NET MAUI?'], + ['can-i-use-traverse-with-dotnet-maui.html', 'Can I use Traverse with .NET MAUI today?'], + ['can-i-share-logic-between-ios-and-android-apps.html', 'Can I share business logic between an iOS app and an Android app?'], + ['what-happens-if-traverse-doesnt-support-my-platform-yet.html', "What happens if Traverse doesn't support my platform yet?"], + ['is-traverse-a-cross-platform-framework.html', 'Is Traverse a cross-platform framework?'], + ['is-traverse-suitable-for-a-cross-platform-desktop-app.html', 'Is Traverse suitable for a cross-platform desktop app?'], + ['what-is-the-difference-between-portable-and-cross-platform.html', 'What is the difference between "portable" and "cross-platform"?'], + ['can-i-migrate-existing-business-logic-to-traverse.html', 'Can I migrate existing business logic into Traverse?'], + ['how-do-ci-pipelines-test-traverse-across-operating-systems.html', 'How does Traverse verify cross-OS behavior actually matches?'], + ['can-i-run-the-same-business-logic-in-browser-and-native-apps.html', 'Can I run the same business logic in a browser app and a native app?'], + ['how-do-i-share-business-logic-between-web-and-desktop.html', 'How do I share business logic between a web app and a desktop app?'], + ['does-traverse-work-offline.html', 'Does Traverse work offline?'], + ['is-webassembly-cross-platform.html', 'Is WebAssembly cross-platform?'], + ['what-is-the-wasm-sandbox.html', 'What is the WASM sandbox?'], + ['how-is-traverse-different-from-a-shared-rust-library.html', 'Why not just use a shared Rust library instead of Traverse?'], + ['how-is-traverse-different-from-docker.html', 'How is Traverse different from Docker?'], + ['can-i-run-traverse-capabilities-in-a-docker-container.html', 'Can I run Traverse capabilities inside a Docker container?'], + ['how-do-i-package-a-capability-for-multiple-platforms.html', 'How do I package a capability for multiple platforms?'], + ['can-traverse-capabilities-call-native-os-apis.html', 'Can Traverse capabilities call native OS APIs?'], + ['can-non-rust-teams-use-traverse.html', "Can a team that doesn't write Rust still use Traverse?"], + ['is-there-a-performance-cost-to-running-the-same-binary-on-every-os.html', 'Is there a performance cost to running the same binary on every OS?'], + ['what-teams-should-not-use-traverse-for-cross-platform-apps.html', 'When should a team NOT use Traverse for a cross-platform app?'], + ['what-questions-should-i-ask-before-picking-a-cross-platform-approach.html', 'What should I ask before picking a cross-platform approach?'], + ['do-different-operating-systems-see-different-behavior-from-the-same-capability.html', 'Can different operating systems see different behavior from the same capability?'], + ['how-does-versioning-work-across-platforms.html', 'How does capability versioning work across multiple platforms?'], + ['can-i-use-traverse-in-a-monorepo-with-multiple-apps.html', 'Can I use Traverse in a monorepo with multiple apps?'], + ['what-is-a-registry-bundle-and-does-it-work-on-every-os.html', 'What is a registry bundle, and does it work on every OS?'], + ['how-do-i-choose-between-a-progressive-web-app-and-traverse.html', 'Should I build a Progressive Web App or use Traverse?'], + ['can-ai-agents-call-the-same-capability-regardless-of-os.html', 'Can an AI agent call the same capability my app uses, regardless of OS?'], + ['how-do-i-test-a-capability-before-shipping-it-to-multiple-platforms.html', 'How do I test a capability before shipping it to multiple platforms?'], + ['what-is-the-smallest-possible-traverse-capability.html', 'What is the smallest possible Traverse capability?'], + ['can-i-use-traverse-for-a-saas-product-on-multiple-operating-systems.html', 'Can I use Traverse for a SaaS product on multiple operating systems?'], + ], + }, { label: 'How Traverse compares', items: [ diff --git a/src/pages/questions/is-there-a-performance-cost-to-running-the-same-binary-on-every-os.astro b/src/pages/questions/is-there-a-performance-cost-to-running-the-same-binary-on-every-os.astro new file mode 100644 index 0000000..a95a4d8 --- /dev/null +++ b/src/pages/questions/is-there-a-performance-cost-to-running-the-same-binary-on-every-os.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Is there a performance cost to running the same binary on every OS?', + acceptedAnswer: { + '@type': 'Answer', + text: "There's a real, non-zero WASM sandboxing and contract-validation overhead compared to calling a native function directly in-process — that's the price of the sandbox and the governance, not of cross-OS portability specifically. The execution itself, once compiled, runs at near-native speed under Wasmtime; the overhead is at the boundary (input/output validation, contract checks, trace writing), not in the computation.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-traverse-performance.html', label: "What is Traverse's performance like?" }, + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/questions/what-is-a-trace-artifact.html', label: 'What is a trace artifact in Traverse?' }, + { href: '/questions/how-is-traverse-different-from-a-shared-rust-library.html', label: 'Why not just use a shared Rust library instead of Traverse?' }, +]; +--- + +

Worth separating two different costs that get conflated under "performance overhead," because only one of them has anything to do with cross-OS portability.

+ +

Cross-OS portability itself is essentially free. Wasmtime compiles WASM to native machine code ahead of execution and runs it at close to native speed, on Windows, macOS, or Linux alike — there's no interpretation layer or per-OS translation step slowing things down because the binary happens to be portable. The "same binary everywhere" property doesn't trade away raw execution speed.

+ +

The governance layer has a real, separate cost. Contract validation on the way in, postcondition checks on the way out, and writing a structured trace artifact for every execution are actual work the runtime does that a bare function call wouldn't. That cost exists whether you're running on one OS or five — it's the price of getting enforced correctness and an audit trail, not the price of portability.

+ +

Whether that tradeoff is worth it

+

For a capability called occasionally — a pricing calculation, an eligibility check — the governance overhead is very unlikely to be the bottleneck in your system. For something called in an extremely tight hot loop at very high frequency, the validation and tracing cost is worth actually measuring against your latency budget before committing. There's no substitute for benchmarking your specific capability and call pattern; see Traverse's performance page for what's measured today, and treat anything not measured there as genuinely unmeasured rather than assumed fine.

+
diff --git a/src/pages/questions/is-traverse-a-cross-platform-framework.astro b/src/pages/questions/is-traverse-a-cross-platform-framework.astro new file mode 100644 index 0000000..0037023 --- /dev/null +++ b/src/pages/questions/is-traverse-a-cross-platform-framework.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Is Traverse a cross-platform framework?', + acceptedAnswer: { + '@type': 'Answer', + text: "It's a cross-platform framework for business logic specifically, not for building UIs. Traverse capabilities compile once and run unmodified on Windows, macOS, Linux, and in the browser today, with mobile embedders in progress or blocked. It doesn't render a UI on any of those platforms — pair it with whatever UI framework you're already using.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, + { href: '/questions/what-operating-systems-does-traverse-support.html', label: 'What operating systems does Traverse support?' }, + { href: '/questions/what-is-traverse.html', label: 'What is Traverse?' }, +]; +--- + +

Depends what you mean by "cross-platform," and that word carries more assumptions than it seems to. If you mean "one codebase that renders a native-feeling UI on multiple operating systems" — the Flutter/Electron/Tauri sense — no, Traverse doesn't do that and isn't trying to. It has no UI layer at all.

+ +

If you mean "one piece of logic that produces the same result no matter which operating system, UI framework, or non-UI caller invokes it" — yes, precisely and by design. You write a capability once, compile it to WASM, attach a contract, and the runtime enforces that contract wherever the binary executes. Today that's natively on Windows, macOS, and Linux, and in the browser; the same binary, no per-OS branch.

+ +

Why the distinction matters

+

Calling Traverse "cross-platform" without that qualifier invites the wrong comparison — stacking it against Flutter feature-for-feature on UI, where it simply has nothing to offer, since it isn't a UI tool. The honest framing is that it's cross-platform for the layer underneath the UI, and it's meant to pair with a UI framework, not replace one. The full comparison spells out exactly where that boundary sits and how the two categories combine.

+
diff --git a/src/pages/questions/is-traverse-suitable-for-a-cross-platform-desktop-app.astro b/src/pages/questions/is-traverse-suitable-for-a-cross-platform-desktop-app.astro new file mode 100644 index 0000000..404d2aa --- /dev/null +++ b/src/pages/questions/is-traverse-suitable-for-a-cross-platform-desktop-app.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Is Traverse suitable for a cross-platform desktop app?', + acceptedAnswer: { + '@type': 'Answer', + text: "For the business-logic layer, yes — native Windows, macOS, and Linux support is Traverse's most mature, shipped target. For the UI itself, no, since Traverse has no UI layer; pair it with a desktop UI framework (Tauri is a particularly natural fit, since both are Rust) and let Traverse govern the logic that framework calls into.", + }, + }], +}); + +const relatedLinks = [ + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, + { href: '/questions/can-i-use-traverse-with-tauri.html', label: 'Can I use Traverse with Tauri?' }, + { href: '/questions/does-traverse-support-windows-macos-and-linux.html', label: 'Does Traverse support Windows, macOS, and Linux?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

Split the question in two, because the honest answer is different for each half. For the business logic behind a desktop app — the rules, calculations, and validations the UI calls into — yes, unreservedly. Native (Windows, macOS, Linux) is Traverse's default, most mature, shipped target, and a capability built for it needs no OS-specific code to run identically on all three.

+ +

For the desktop app's UI itself, Traverse isn't the tool — it has no windowing system, no widget library, nothing that paints a screen. You'll still pick a UI framework: Tauri, Electron, Flutter, or a native toolkit per OS if you want that level of control.

+ +

Which UI framework pairs best

+

Tauri is the most natural fit specifically, because its backend is Rust — the same language Traverse capabilities compile from. A Tauri command can call directly into the public traverse-embedder crate with no FFI boundary to cross. Electron works too, through its Chromium-based renderer, which is already a WASM host. Flutter's Dart runtime doesn't host WASM the same way, so pairing there typically goes through a native plugin bridging to a traverse-embedder-based process instead of an in-process call.

+ +

The full comparison walks through the Tauri pairing with a real code example, if that's the combination you're considering.

+
diff --git a/src/pages/questions/is-webassembly-cross-platform.astro b/src/pages/questions/is-webassembly-cross-platform.astro new file mode 100644 index 0000000..5f4f478 --- /dev/null +++ b/src/pages/questions/is-webassembly-cross-platform.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'Is WebAssembly cross-platform?', + acceptedAnswer: { + '@type': 'Answer', + text: "Yes — that's the point of the format. A WASM binary is a portable instruction set, not machine code for a specific CPU or OS, so any conformant runtime executes it the same way. That's necessary but not sufficient for building a real cross-platform system: WASM alone gives you a portable binary, not a way to describe what it does, validate it, or trace what happened when it ran. Traverse adds that layer on top.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/questions/what-is-the-wasm-sandbox.html', label: 'What is the WASM sandbox?' }, + { href: '/blog/wasm-business-logic.html', label: 'What WASM actually gives you for business logic' }, + { href: '/questions/can-traverse-run-without-wasm.html', label: 'Can Traverse run without WASM?' }, +]; +--- + +

Yes. WebAssembly is a formally specified binary instruction format, not native code tied to a particular processor or operating system. Any runtime that implements the spec — a browser, Wasmtime, Wasmer, a custom embedder — executes a given .wasm file the same way. You compile once; you don't recompile per target the way you would for native machine code.

+ +

This is different from, say, a Java .jar, which needs a JVM present and configured per platform, or a native binary, which needs a separate build per OS and CPU architecture entirely. WASM's portability is closer to "the artifact itself doesn't know or care what's hosting it."

+ +

Why that's not the full answer for building a real system

+

A raw WASM binary is portable, but it's also just a file with some exported function names. It doesn't tell you what those functions expect as input, what they guarantee as output, what permissions they need, or whether a given execution actually behaved correctly. Two different callers could invoke it with incompatible assumptions and both technically "work," right up until they don't.

+ +

That's the gap Traverse fills on top of WASM's portability: a contract that declares inputs, outputs, preconditions, and postconditions, a runtime that enforces the contract on every execution, and a trace artifact recording what actually happened. The portability is WebAssembly's contribution. The governance — the part that makes it safe to build a real, auditable system out of that portability — is Traverse's.

+
diff --git a/src/pages/questions/what-does-device-independent-mean-in-traverse.astro b/src/pages/questions/what-does-device-independent-mean-in-traverse.astro new file mode 100644 index 0000000..a3d5715 --- /dev/null +++ b/src/pages/questions/what-does-device-independent-mean-in-traverse.astro @@ -0,0 +1,43 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What does "device-independent" mean in Traverse?', + acceptedAnswer: { + '@type': 'Answer', + text: "A device-independent capability is a WASM binary that runs unmodified on any client that loads it — the runtime doesn't recompile or branch per host. Execution happens locally on that client by default; the client can heuristically delegate a subset of the work to a server based on its own context (resource constraints, latency), rather than the capability being pinned to a fixed deployment target chosen ahead of time.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-traverse.html', label: 'What is Traverse?' }, + { href: '/questions/how-do-placement-targets-work.html', label: 'How do placement targets work in Traverse?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/docs/concepts.html', label: 'Core Concepts: Traverse Docs' }, +]; +--- + +

"Device-independent" describes the capability itself, not just where it happens to be deployed. A Traverse capability compiles to a single WASM binary. That binary carries its own contract — inputs, outputs, preconditions, postconditions — and any conformant WASM host can load and run it without recompiling it or maintaining a separate build per target. The same file that runs on your laptop through the CLI is the same file the browser embedder loads.

+ +

The independence goes further than "the binary is portable," though. Execution happens on the client by default — wherever the capability was loaded — and the client decides, using its own heuristics (things like resource constraints or latency), whether to run the whole thing locally or delegate some subset of it to a server. That decision isn't baked into the capability at authoring time. It isn't a fixed "this capability runs in the cloud" flag someone set once. It's evaluated live, by the client, against its own current context.

+ +

Why this is a meaningfully different model from "pick a target"

+

Earlier placement-oriented models (including Traverse's own older documentation) framed this as choosing a target — browser, edge, cloud, ai-pipeline — ahead of time, the way you'd pick a deployment region. The device-independent framing inverts that. The capability doesn't know or care where it will run. The client does, and it decides at the moment of execution, not at build time.

+ +

In practice, right now, that means local (native) and browser are the two contexts with a real, shipped executor behind this model — see Platforms for the honest, evidence-linked state of every target. The concept itself — one binary, client-decided execution — is what's designed to extend as more executors ship.

+ +

Why it matters for "any OS"

+

This is the underlying reason a Traverse capability can move between Windows, macOS, Linux, and the browser without a rewrite: the binary was never written with an assumption about its host baked in. Contrast that with typical application code, which usually has at least implicit OS assumptions (file paths, threading models, UI toolkit) baked into it from the start.

+
diff --git a/src/pages/questions/what-framework-runs-business-logic-on-any-os.astro b/src/pages/questions/what-framework-runs-business-logic-on-any-os.astro new file mode 100644 index 0000000..42c7f68 --- /dev/null +++ b/src/pages/questions/what-framework-runs-business-logic-on-any-os.astro @@ -0,0 +1,73 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const faqEntries = [ + { + q: 'What framework lets me write business logic once and run it on any OS?', + a: "Traverse. You write a capability once in Rust, compile it to a WASM binary, and attach a machine-readable contract. The same binary runs natively on Windows, macOS, and Linux today through traverse-runtime's Wasmtime-backed executor, and in the browser through the Web embedder SDK — no per-OS rewrite. Mobile support (Android, iOS) is still in progress or blocked; see traverse-framework.com/platforms.html for the exact, evidence-linked status of each target.", + }, + { + q: 'Can I build an app that runs on Windows, macOS, and Linux without rewriting the business logic?', + a: 'Yes, for the business-logic layer specifically. Traverse compiles your capability to WebAssembly once. The traverse-runtime crate runs that same WASM binary unmodified on Windows, macOS, and Linux — this is the most mature, shipped target today. You still write your own UI shell per platform, or pair it with a cross-platform UI toolkit; Traverse governs the logic underneath it, not the windowing layer.', + }, + { + q: 'Is there a framework where the same code runs on any operating system without a rewrite?', + a: "For UI-heavy native apps, no single framework the industry has produced is honest about running the exact same code identically on desktop, mobile, and web — every one of them (Flutter, Electron, Tauri, React Native, .NET MAUI) has real per-platform seams. For the business-logic layer alone, Traverse's WASM capabilities are the closest genuine answer: same binary, same contract, same behavior, wherever a WASI-compatible runtime exists.", + }, +]; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: faqEntries.map((e) => ({ + '@type': 'Question', + name: e.q, + acceptedAnswer: { '@type': 'Answer', text: e.a }, + })), +}); + +const relatedLinks = [ + { href: '/questions/what-is-traverse.html', label: 'What is Traverse?' }, + { href: '/questions/what-is-a-wasm-capability.html', label: 'What is a WASM capability in Traverse?' }, + { href: '/questions/how-do-placement-targets-work.html', label: 'How do placement targets work in Traverse?' }, + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, +]; +--- + +

Traverse. You write a capability once in Rust, compile it to a WebAssembly binary, and attach a machine-readable contract that says what it does, what it needs, and what must be true before and after it runs. The runtime — not your app code — decides where that binary executes. Today, that means the same unmodified binary runs natively on Windows, macOS, and Linux through traverse-runtime's Wasmtime-backed executor, and in the browser through the Web embedder SDK. No recompiling for the target OS. No forked codepath for "the Windows version."

+ +

That's the real, shipped answer. It's narrower than the breathless "write once, run anywhere on every device" pitch you'll see from most cross-platform tools, and it's narrower on purpose — because the honest version is the only one that survives contact with production.

+ +

What "any OS" actually covers today

+

Three targets have a real executor behind them right now:

+ + +

Mobile is a different story, and we'd rather say that plainly than let you find out after you've built on top of it:

+ +

The full, evidence-linked breakdown — with links to the actual crates and blocking issues — lives on the Platforms page. We'd rather send you there than oversell it here.

+ +

Why the same binary can move between operating systems at all

+

This isn't magic, and it isn't unique to Traverse — it's what WebAssembly is for. A WASM module is a portable instruction format, not native machine code. Any conformant runtime executes it the same way, whether that runtime is embedded in a browser tab, a Rust CLI on Windows, or a server process on Linux. Traverse's job is what sits on top of that: the contract that says what a capability is allowed to do, the registry that makes it discoverable, and the runtime that validates inputs and outputs before and after execution. The portability is WASM's. The governance is Traverse's.

+ +

This is not a Flutter or Electron replacement

+

If what you actually want is one codebase that paints a native-looking UI on Windows, macOS, Linux, iOS, and Android, that's a different problem — and Flutter, Tauri, Electron, and .NET MAUI are built to solve it, with UI toolkits Traverse doesn't provide. Traverse solves the layer underneath that: the pricing rule, the eligibility check, the validation logic that needs to produce the exact same result no matter which shell is calling it, including a shell built with one of those frameworks. We wrote up the specific overlap and the honest boundary between the two categories on the Traverse vs. cross-platform app frameworks comparison page.

+ +

Try it

+

The fastest way to see the native path for yourself is the quickstart: clone the repo, run cargo build, and inspect the shipped expedition example bundle. That build and every command in it runs unmodified on Linux, macOS, and Windows — it's the same Rust toolchain either way.

+
diff --git a/src/pages/questions/what-happens-if-traverse-doesnt-support-my-platform-yet.astro b/src/pages/questions/what-happens-if-traverse-doesnt-support-my-platform-yet.astro new file mode 100644 index 0000000..2ad2f01 --- /dev/null +++ b/src/pages/questions/what-happens-if-traverse-doesnt-support-my-platform-yet.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: "What happens if Traverse doesn't support my platform yet?", + acceptedAnswer: { + '@type': 'Answer', + text: "Your capability and its contract don't change when a new executor ships — only the host adapter does. So the practical answer is: write the capability now against a shipped target (native or browser), and when your platform's embedder ships, the same WASM binary and contract move over without a rewrite. For a platform that's genuinely blocked (iOS today), the honest move is to design around the shipped targets and revisit once the blocker clears.", + }, + }], +}); + +const relatedLinks = [ + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, + { href: '/questions/what-is-traverse-roadmap.html', label: 'What is the Traverse roadmap?' }, + { href: '/questions/can-traverse-build-mobile-apps.html', label: 'Can I build a mobile app with Traverse?' }, + { href: '/questions/what-does-device-independent-mean-in-traverse.html', label: 'What does "device-independent" mean in Traverse?' }, +]; +--- + +

This comes up most often around mobile, but the answer generalizes to any target that isn't shipped yet: edge, cloud, or a platform not on the roadmap at all. The reassuring part is structural, not aspirational — a Traverse capability's WASM binary and contract don't reference a specific host. What changes between platforms is the executor that loads and runs that binary, which lives outside the capability entirely.

+ +

Practically: write and test your capability today against a target that's actually shipped — native (Windows, macOS, Linux) or the browser. When an executor for your target platform ships (an Android embedder, say, or the eventual edge executor), the exact same binary and contract are what that new executor loads. You're not rewriting the capability; you're gaining a new place to run the one you already have.

+ +

What if the platform is genuinely blocked, not just unshipped?

+

iOS is the honest example here — blocked on the WASM engine ecosystem lacking a certifiable resource-control API, not simply unprioritized. In that case, the reasonable move is to design your system around the platforms that are actually available now, keep the capability platform-agnostic (which it already is by construction), and treat mobile as a target you'll extend to once the blocker clears rather than one you build around today. Watching Platforms is the way to know exactly when that changes — it's the same page used internally to track it, not a rounded-up public version.

+
diff --git a/src/pages/questions/what-is-a-registry-bundle-and-does-it-work-on-every-os.astro b/src/pages/questions/what-is-a-registry-bundle-and-does-it-work-on-every-os.astro new file mode 100644 index 0000000..32b89b2 --- /dev/null +++ b/src/pages/questions/what-is-a-registry-bundle-and-does-it-work-on-every-os.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What is a registry bundle, and does it work on every OS?', + acceptedAnswer: { + '@type': 'Answer', + text: 'A registry bundle is a manifest plus the capability contracts, WASM modules, event contracts, and workflow definitions it groups together into one deployable, CLI-validated unit. It has no OS-specific content, so the identical bundle is what every shipped executor — native or browser — loads.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/what-is-the-capability-registry.html', label: 'What is the capability registry?' }, + { href: '/questions/how-do-i-package-a-capability-for-multiple-platforms.html', label: 'How do I package a capability for multiple platforms?' }, + { href: '/docs/concepts.html', label: 'Core Concepts: Traverse Docs' }, + { href: '/docs/guides/cross-os-capability.html', label: 'Write once, run on Windows, macOS, Linux, and the browser' }, +]; +--- + +

A registry bundle is the deployable unit a Traverse runtime actually loads: a top-level manifest describing what's inside, a capabilities/ directory holding each capability's contract and compiled WASM module, an events/ directory for event contracts, and a workflows/ directory for any workflow definitions that compose those capabilities together. The CLI validates the whole bundle — checking that contracts are well-formed and that referenced modules actually exist — before it's registered.

+ +

None of that content is OS-specific. A manifest is JSON. A contract is JSON. A capability module is a portable WASM binary. There's nothing in a bundle's structure that would need to differ if it were being loaded on Windows versus loaded in a browser tab — which is exactly why it doesn't.

+ +

So yes — one bundle, every shipped target

+

The same bundle a native executor loads through traverse-cli-rs -- bundle inspect is the same file the Web embedder SDK loads and digest-verifies before executing a capability in a browser. There's no "browser bundle" and "native bundle" as separate build artifacts — see the cross-OS capability guide for a step-by-step walkthrough that inspects one bundle and then runs it through both.

+
diff --git a/src/pages/questions/what-is-the-difference-between-portable-and-cross-platform.astro b/src/pages/questions/what-is-the-difference-between-portable-and-cross-platform.astro new file mode 100644 index 0000000..5ed8cee --- /dev/null +++ b/src/pages/questions/what-is-the-difference-between-portable-and-cross-platform.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What is the difference between "portable" and "cross-platform"?', + acceptedAnswer: { + '@type': 'Answer', + text: '"Cross-platform" usually describes a tool that ships a UI across multiple operating systems from one codebase. "Portable" describes an artifact — like a WASM binary — that runs unmodified wherever a compatible runtime exists, independent of any particular UI or deployment target. Traverse capabilities are portable in this second sense, which is a narrower and more precise claim than "cross-platform" implies.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/is-webassembly-cross-platform.html', label: 'Is WebAssembly cross-platform?' }, + { href: '/questions/is-traverse-a-cross-platform-framework.html', label: 'Is Traverse a cross-platform framework?' }, + { href: '/questions/what-does-device-independent-mean-in-traverse.html', label: 'What does "device-independent" mean in Traverse?' }, + { href: '/blog/cross-platform-rarely-means-what-it-sounds-like.html', label: 'Why "cross-platform" rarely means what it sounds like' }, +]; +--- + +

They get used interchangeably in casual conversation, but they're pointing at different things, and the difference matters when you're evaluating a tool against a real requirement.

+ +

"Cross-platform" is almost always a claim about a UI or an application: one codebase, one team, shipping to multiple operating systems or devices. Flutter, Electron, Tauri, and React Native are all cross-platform in this sense — the thing being made portable is the app's rendered surface and the framework that produces it.

+ +

"Portable" is a claim about an artifact, independent of any UI at all. A WebAssembly binary is portable because any conformant WASM runtime executes it identically, regardless of what's hosting that runtime — a browser, a native process, an embedded device. Nothing about "portable" implies there's a UI involved, or that the artifact was designed with any particular deployment target in mind.

+ +

Why Traverse leans on the second word

+

A Traverse capability is portable in the strict sense: the WASM binary and its contract carry no assumptions about a host, and any conformant executor can run it. It is not, on its own, "cross-platform" in the UI sense, because it has no UI to be cross-platform about. Calling it "cross-platform" without qualification invites people to compare it to Flutter on UI grounds, which is a comparison it was never trying to win. "Portable business logic that pairs with whatever UI framework you choose" is a longer sentence, but it's the accurate one — and the longer piece on this goes through why most "cross-platform" claims in the industry are quietly making the same UI-only promise.

+
diff --git a/src/pages/questions/what-is-the-smallest-possible-traverse-capability.astro b/src/pages/questions/what-is-the-smallest-possible-traverse-capability.astro new file mode 100644 index 0000000..e84ff92 --- /dev/null +++ b/src/pages/questions/what-is-the-smallest-possible-traverse-capability.astro @@ -0,0 +1,38 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What is the smallest possible Traverse capability?', + acceptedAnswer: { + '@type': 'Answer', + text: 'A minimal capability is a small compiled WASM module — typically kilobytes, not megabytes — plus a contract declaring one input, one output, and no host calls or permissions at all. There is no minimum complexity requirement; a single pure function with a well-defined precondition and postcondition is a complete, valid, portable capability.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/how-long-to-get-started.html', label: 'How long does it take to get started with Traverse?' }, + { href: '/questions/how-do-i-write-a-capability-contract.html', label: 'How do I write a capability contract?' }, + { href: '/questions/how-is-traverse-different-from-docker.html', label: 'How is Traverse different from Docker?' }, + { href: '/docs/quickstart.html', label: 'Quickstart' }, +]; +--- + +

There's no floor on complexity. A capability doesn't need multiple functions, elaborate state, or a workflow around it to be valid — a single pure computation, like rounding a currency amount to the correct number of decimal places for a given jurisdiction, is a complete capability on its own: one input schema, one output schema, no preconditions beyond basic type validity, no postconditions beyond "the output matches the schema," and no declared host calls at all.

+ +

Because it declares no network_access, filesystem_access, or host_calls, its contract is close to the shortest one you can write, and the compiled WASM module for a function that small is typically a matter of kilobytes — nowhere near the size of even a minimal container image, which is part of what makes it practical to load directly in a browser tab.

+ +

Why size matters here specifically

+

A capability this small is cheap to compile, cheap to validate, cheap to load, and fast to execute — there's very little sandboxing overhead to amortize when the computation itself is trivial. It's also the right place to start if you're evaluating Traverse for the first time: write one small, genuinely useful pure function as a capability, run it through the quickstart path, and get a feel for the contract-and-trace mechanics before committing a larger, more consequential rule to the same pattern.

+
diff --git a/src/pages/questions/what-is-the-wasm-sandbox.astro b/src/pages/questions/what-is-the-wasm-sandbox.astro new file mode 100644 index 0000000..b81d0d7 --- /dev/null +++ b/src/pages/questions/what-is-the-wasm-sandbox.astro @@ -0,0 +1,40 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What is the WASM sandbox?', + acceptedAnswer: { + '@type': 'Answer', + text: 'The WASM sandbox is the default-deny execution boundary a WebAssembly module runs inside: no filesystem access, no network access, no ability to spawn threads or call host system functions unless the host explicitly grants it. Traverse capabilities declare exactly what they need in their contract, and the runtime enforces that boundary at execution time.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/is-webassembly-cross-platform.html', label: 'Is WebAssembly cross-platform?' }, + { href: '/questions/what-is-a-contract-in-traverse.html', label: 'What is a contract in Traverse?' }, + { href: '/blog/wasm-business-logic.html', label: 'What WASM actually gives you for business logic' }, + { href: '/questions/what-is-traverse-security-model.html', label: "What is Traverse's security model?" }, +]; +--- + +

By default, a WebAssembly module can't do anything to the outside world. No reading or writing files, no opening network sockets, no spawning threads, no calling arbitrary host functions. It takes inputs, runs pure computation over its own linear memory, and returns outputs. Anything beyond that has to be explicitly imported by the host — the module can't reach out and grab a capability the host didn't hand it.

+ +

In Traverse, what a capability is allowed to reach outside the sandbox is declared in its contract — things like network_access, filesystem_access, and host_api_access, each defaulting to denied. If a capability tries to do something its contract doesn't declare, the runtime rejects it at the boundary, not somewhere downstream after damage is done.

+ +

Why this matters for cross-OS portability specifically

+

Every one of those boundary-crossing operations — file paths, socket APIs, thread models — is exactly where OS differences usually leak into application code. A sandbox that denies all of it by default means a capability that never touches the sandbox boundary genuinely has no OS-specific behavior baked in. It's not that Traverse specially handles Windows-vs-Linux filesystem quirks; it's that a well-scoped capability never has to.

+ +

The sandbox is also a testability property, not just a security one: logic that can't produce side effects is logic you can test in isolation, without mocking a filesystem or a network. That's a separate benefit from portability, but it comes from the same design decision.

+
diff --git a/src/pages/questions/what-operating-systems-does-traverse-support.astro b/src/pages/questions/what-operating-systems-does-traverse-support.astro new file mode 100644 index 0000000..5328b93 --- /dev/null +++ b/src/pages/questions/what-operating-systems-does-traverse-support.astro @@ -0,0 +1,42 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What operating systems does Traverse support?', + acceptedAnswer: { + '@type': 'Answer', + text: 'Windows, macOS, and Linux are shipped natively today, plus the browser as a fourth, non-OS context. Android and .NET/WinUI have working embedders in progress with no public release. iOS is blocked on the WASM engine ecosystem lacking a certifiable resource-control API.', + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/does-traverse-support-windows-macos-and-linux.html', label: 'Does Traverse support Windows, macOS, and Linux?' }, + { href: '/questions/can-traverse-build-mobile-apps.html', label: 'Can I build a mobile app with Traverse?' }, + { href: '/questions/what-framework-runs-business-logic-on-any-os.html', label: 'What framework lets me write business logic once and run it on any OS?' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, +]; +--- + +

Short answer, as of the current release:

+ + +

This list is deliberately shorter than what most cross-platform tooling claims, because it's scored against real crates and blocking issues rather than a roadmap. For the full breakdown — including which crate implements each target and links to the actual blocking issues — see the Platforms page, which is the same page the team uses internally, not a separate marketing version. For the fuller "how does this actually work" answer, see what framework lets me write business logic once and run it on any OS.

+
diff --git a/src/pages/questions/what-questions-should-i-ask-before-picking-a-cross-platform-approach.astro b/src/pages/questions/what-questions-should-i-ask-before-picking-a-cross-platform-approach.astro new file mode 100644 index 0000000..e62d060 --- /dev/null +++ b/src/pages/questions/what-questions-should-i-ask-before-picking-a-cross-platform-approach.astro @@ -0,0 +1,48 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'What should I ask before picking a cross-platform approach?', + acceptedAnswer: { + '@type': 'Answer', + text: "Separate the UI question from the logic question first. Then ask which operating systems you need today versus later, whether any rule needs to be provably identical across more than one caller, whether you need an audit trail of what executed and why, and whether your team can write the language the tool actually requires. Most cross-platform disappointments come from skipping the first question.", + }, + }], +}); + +const relatedLinks = [ + { href: '/blog/cross-platform-rarely-means-what-it-sounds-like.html', label: 'Why "cross-platform" rarely means what it sounds like' }, + { href: '/compare/vs-cross-platform-frameworks.html', label: 'Traverse vs Flutter, Electron, and Tauri' }, + { href: '/questions/is-traverse-a-cross-platform-framework.html', label: 'Is Traverse a cross-platform framework?' }, + { href: '/questions/what-teams-should-not-use-traverse-for-cross-platform-apps.html', label: 'When should a team NOT use Traverse?' }, +]; +--- + +

Almost every regretted "cross-platform" choice traces back to one missing step at the start: nobody separated the UI question from the logic question, so the team evaluated one tool against requirements that actually belonged to two different layers. Do that split first, then work through the rest.

+ +

1. Is this a UI decision, a logic decision, or both?

+

If you need a native-feeling UI across operating systems, you're choosing between Flutter, Electron, Tauri, React Native, or .NET MAUI — that's a UI-layer decision, and none of those tools govern the business logic underneath the UI any differently than plain application code would. If you're choosing how to keep a rule consistent across an app, a backend, and maybe an AI agent, that's a logic-layer decision, and the UI framework you eventually pick is mostly irrelevant to it.

+ +

2. Which operating systems do you need, and by when?

+

"Eventually, everything" is not a real requirement. Write down which platforms are needed for launch versus which are aspirational, and check each candidate tool's actual, current — not roadmapped — support for exactly those. Evidence-linked status pages, where a tool publishes one, are worth more than a marketing page's platform-logo row.

+ +

3. Does any rule need to be provably identical across more than one caller?

+

If a pricing or eligibility rule only ever lives in one app, in one language, you don't need a governance layer for it — a plain function is fine. If it needs to produce the same answer in a web app, a backend, and an AI pipeline, that's specifically the problem a contract-governed capability solves and a UI framework doesn't.

+ +

4. Do you need an audit trail of what actually ran?

+

Compliance, financial logic, and AI-agent-invoked actions often need a record of what executed, with what inputs, under which contract version. Most UI frameworks and plain function calls produce none of that by default; it has to be built or bolted on.

+ +

5. Can your team write the language the tool actually requires?

+

Flutter means Dart. React Native and Electron mean JavaScript/TypeScript. .NET MAUI means C#. Authoring a new Traverse capability means Rust today. Pick based on what your team can actually staff and maintain, not on which tool has the best marketing page — the fourth or fifth rewrite of a "temporary" prototype is usually where a language mismatch that got waved away the first time finally gets paid for.

+
diff --git a/src/pages/questions/what-teams-should-not-use-traverse-for-cross-platform-apps.astro b/src/pages/questions/what-teams-should-not-use-traverse-for-cross-platform-apps.astro new file mode 100644 index 0000000..5af18cd --- /dev/null +++ b/src/pages/questions/what-teams-should-not-use-traverse-for-cross-platform-apps.astro @@ -0,0 +1,42 @@ +--- +import QuestionLayout from '@layouts/QuestionLayout.astro'; + +const jsonLd = JSON.stringify({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: [{ + '@type': 'Question', + name: 'When should a team NOT use Traverse for a cross-platform app?', + acceptedAnswer: { + '@type': 'Answer', + text: "When you need a native mobile UI shipped soon (Traverse has no UI layer and mobile embedders are unreleased or blocked), when your team is not willing to write the logic in Rust and cannot wait for the planned Python SDK, when the logic in question lives in exactly one place and is unlikely to need reuse, or when your platform target is iOS specifically and you cannot wait on the WASM-engine blocker.", + }, + }], +}); + +const relatedLinks = [ + { href: '/questions/can-traverse-build-mobile-apps.html', label: 'Can I build a mobile app with Traverse?' }, + { href: '/questions/can-non-rust-teams-use-traverse.html', label: 'Can a team that does not write Rust still use Traverse?' }, + { href: '/blog/logic-duplication.html', label: 'Why I stopped writing the same business logic four times' }, + { href: '/platforms.html', label: 'Where Traverse actually runs (platform status)' }, +]; +--- + +

Most of this site makes the case for when Traverse fits. It's at least as useful to be specific about when it doesn't, since a mismatched tool costs more than a missing feature.

+ + + +

None of this is a knock on the project — a tool that's honest about its worst fit is more trustworthy about its best one.

+