<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/szTheory/crosswake/main/brandbook/collateral/readme-header-dark.svg">
<img src="https://raw.githubusercontent.com/szTheory/crosswake/main/brandbook/collateral/readme-header.svg" alt="Crosswake">
</picture>
</p>
# Crosswake
> **Declare the crossing.**
> Phoenix-native route policy for apps that go mobile.
Crosswake is an open-source Elixir library for shipping iOS and Android apps from
Phoenix applications without pretending one runtime should own every screen.
Server-centric routes can stay LiveView, device-heavy flows can move into explicit
native screens, and local-first work can live in honest offline islands.
Crosswake's one job is to declare, enforce, and diagnose which runtime owns each
route as a Phoenix app crosses into mobile.
## What this is
Crosswake gives Phoenix apps a mobile runtime contract built around:
- route policy
- a versioned runtime manifest
- host-owned native shells
- a bounded bridge for low-frequency native affordances
- explicit pack and transfer seams
- offline islands and cached read-only routes
The core idea is simple: **runtime ownership is explicit per route**.
## What this is not
Crosswake is not:
- React Native for Phoenix
- a generic WebView wrapper
- LiveView rendering native UI directly
- a universal shared UI framework
- “write once, run anywhere”
- “offline magically works”
## See it run
```bash
bin/see-it-run.sh
```
Boots the shared backend on port 4700 and auto-opens the browser. Requires Docker.
<img
src="https://raw.githubusercontent.com/szTheory/crosswake/main/brandbook/collateral/see-it-run/three-runtime-montage.png"
alt="Three-runtime Crosswake comparison: web (localhost:4700), iOS Simulator (emulator evidence — advisory native, not a physical device), Android Emulator (emulator evidence — advisory native, not a physical device)"
width="900"
/>
Three routes, one shared backend at `http://localhost:4700`:
- `/` — home (Phoenix LiveView)
- `/offline` — offline island (app-owned, socketless)
- `/bridge-proof` — bounded bridge (share capability)
> **Advisory native collateral.** The iOS Simulator and Android Emulator frames above are
> `emulator evidence` — advisory, not physical-device proof. A successful simulator or
> emulator run confirms the dev wiring reaches the local backend, but does not prove
> it works on a physical device. See the
> [support-truth label legend](guides/support_matrix.md#support-truth-label-legend).
For a guided walkthrough: [guides/see_it_run.md](guides/see_it_run.md).
For the full proof command reference: [examples/QUICK_START.md](https://github.com/szTheory/crosswake/blob/main/examples/QUICK_START.md).
## Choose your path
### Evaluating Crosswake
Start with:
- [guides/route_policy.md](guides/route_policy.md) for the start-here route-owner map
- [guides/web_to_mobile_migration.md](guides/web_to_mobile_migration.md) for an operational Phoenix route inventory pass
- [guides/user_flows.md](guides/user_flows.md) for the fastest JTBD and user-flow ramp-up
- [guides/adopter_profiles.md](guides/adopter_profiles.md) for the three target app shapes
- [guides/install.md](guides/install.md) for the public install and proof path
- [guides/support_matrix.md](guides/support_matrix.md) for the current supported baseline
- [examples/phoenix_host/README.md](https://github.com/szTheory/crosswake/blob/main/examples/phoenix_host/README.md) for the shared exemplar host contract
### Integrating Crosswake
Use the current host-owned path:
```bash
mix deps.get
mix crosswake.install
mix crosswake.gen.shell ios
mix crosswake.gen.shell android
mix crosswake.doctor --router Elixir.YourAppWeb.Router
```
Then run the checked-in proof lane:
```bash
bash script/verify_phase5_example_hosts.sh
```
Crosswake owns the DSL, manifest contract, doctor tooling, and proof posture.
Your Phoenix host and generated shells are **host-owned** after generation.
### Contributing or maintaining
Read:
- [AGENTS.md](https://github.com/szTheory/crosswake/blob/main/AGENTS.md)
- [guides/install.md](guides/install.md)
- [guides/native_shell.md](guides/native_shell.md)
- [guides/packs.md](guides/packs.md)
- [guides/offline.md](guides/offline.md)
The checked-in example hosts under `examples/` are the primary public proof artifacts.
## Architecture at a glance
Crosswake is strongest when teams can answer these route-by-route questions clearly:
- Which routes stay `:live_view`?
- Which routes can be cached read-only?
- Which flows need an `:offline_island`?
- Which routes must become `:native_screen`?
- Which capabilities, packs, transfers, and security posture does each route need?
The current runtime ladder is:
1. `:live_view`
2. `:live_view` inside a native shell
3. `:live_view` plus bounded native affordances
4. cached read-only routes
5. `:offline_island`
6. `:native_screen`
## Where Crosswake fits
Crosswake is currently shaped around three adopter profiles:
- **Phoenix SaaS Portal**: mostly LiveView, one bounded native affordance
- **Selective Native Flow**: mostly Phoenix-owned, one explicit native route
- **Local-First Study Flow**: one honest offline island plus cached neighbors
See [guides/adopter_profiles.md](guides/adopter_profiles.md) for the profile matrix,
representative routes, and explicit non-goals.
For the fastest "how would I actually use this in my app?" pass, start with
[guides/user_flows.md](guides/user_flows.md).
## Proof and support posture
Crosswake treats diagnostics, support truth, and proof lanes as part of the product
surface.
- [guides/support_matrix.md](guides/support_matrix.md) is the canonical support-status surface.
- [guides/support_matrix.md#support-truth-label-legend](guides/support_matrix.md#support-truth-label-legend) defines support-truth labels: merge-blocking proof, advisory evidence, checked-in public-coordinate proof, local-dev proof, generated public-coordinate proof, JVM hermetic proof, emulator evidence, device evidence, verification-required, and rebuild-required.
- [guides/troubleshooting.md](guides/troubleshooting.md) maps doctor findings, denial reasons, route-unavailable states, offline replay outcomes, and native evidence labels to route-owner fixes.
- [guides/install.md](guides/install.md) is the canonical install and proof-entry guide.
- The checked-in `examples/ios_shell_host` and `examples/android_shell_host` hosts are `checked-in public-coordinate proof`; use `--local` only for maintainer/local-dev proof.
- `bash script/verify_phase5_example_hosts.sh` is the primary checked-in proof lane.
- The route-tour evidence path uses `merge-blocking proof` for browser semantic assertions, manifest labels for artifacts, and `advisory evidence` for native simulator/emulator collateral.
- `mix crosswake.doctor --router Elixir.YourAppWeb.Router --native-checks` reruns the local generated-shell verification hooks.
Crosswake stays deliberately narrow and explicit. Unsupported or incompatible routes
fail closed onto explicit denial behavior instead of silently degrading into a generic
container.
## Guide map
- [guides/install.md](guides/install.md) — Phoenix install path and native shell generation
- [guides/route_policy.md](guides/route_policy.md) — start-here route-owner decisions and DSL examples
- [guides/web_to_mobile_migration.md](guides/web_to_mobile_migration.md) — route inventory pass for existing Phoenix SaaS apps
- [guides/user_flows.md](guides/user_flows.md) — JTBD and route-by-route adopter ramp-up
- [guides/native_shell.md](guides/native_shell.md) — manifest-first activation and shell contract
- [guides/bridge.md](guides/bridge.md) — bounded bridge vocabulary
- [guides/packs.md](guides/packs.md) — required packs, transfers, and native capture handoff
- [guides/offline.md](guides/offline.md) — cached read-only and offline-island posture
- [guides/compatibility.md](guides/compatibility.md) — compatibility and denial posture
- [guides/support_matrix.md](guides/support_matrix.md) — proof classes, support labels, and rebuild truth
- [guides/troubleshooting.md](guides/troubleshooting.md) — route-owner fixes for doctor findings, denials, offline outcomes, and native evidence labels
## Current baseline
- Elixir `~> 1.19`
- Phoenix `~> 1.8`
- Phoenix LiveView `~> 1.1`
- Crosswake version `0.2.0` <!-- x-release-please-version -->
- Generated non-local native shell core coordinates resolve at the Crosswake package version.
See [mix.exs](mix.exs) and [guides/support_matrix.md](guides/support_matrix.md) for
the current package and platform baseline.