# Meshtastic Web Monorepo [![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/web/ci.yml?branch=main&label=Web%20CI&logo=github&color=yellow)](https://github.com/meshtastic/web/actions/workflows/ci.yml) [![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/js/ci.yml?branch=master&label=JS%20CI&logo=github&color=yellow)](https://github.com/meshtastic/js/actions/workflows/ci.yml) [![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/web)](https://cla-assistant.io/meshtastic/web) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) ## Overview This monorepo consolidates the official [Meshtastic](https://meshtastic.org) web interface, the domain-driven JavaScript SDK that drives it, and a set of runtime-specific transport packages. Everything you need to read state from or send commands to a Meshtastic device lives here. > [!NOTE] > You can find the main Meshtastic documentation at https://meshtastic.org/docs/introduction/. ## Packages All projects live under `packages/`. | Package | Purpose | | --- | --- | | `packages/sdk` | Framework-agnostic TypeScript SDK. Domain-driven feature slices (device, chat, nodes, channels, config, telemetry, position, traceroute, files) built around a `MeshClient` orchestrator with `@preact/signals-core` reactive state. | | `packages/sdk-react` | React hooks + `MeshProvider` on top of `@meshtastic/sdk`. Wraps signals in `useSyncExternalStore` for concurrent-safe renders. | | `apps/web` | Reference React web client. Hosted at [client.meshtastic.org](https://client.meshtastic.org). | | `packages/ui` | Shared Radix + Tailwind component library. | | `packages/protobufs` | Generated TypeScript stubs from [`meshtastic/protobufs`](https://github.com/meshtastic/protobufs), produced via `buf generate`. Source of truth for every wire-level type. | | `packages/transport-http` | HTTP transport for devices exposing a network interface. | | `packages/transport-web-bluetooth` | Web Bluetooth transport for BLE-capable devices (browsers). | | `packages/transport-web-serial` | Web Serial transport for USB-serial devices (browsers). | | `packages/transport-node` | TCP transport for Node.js. | | `packages/transport-node-serial` | Serial transport for Node.js. | | `packages/transport-deno` | TCP transport for Deno. | | `packages/transport-mock` | In-memory transport for tests. | All publishable packages ship to both [JSR](https://jsr.io/@meshtastic) and [NPM](https://www.npmjs.com/org/meshtastic). ## Architecture `@meshtastic/sdk` organises its source by feature slice. Each slice follows the same DDD layout: ``` features// domain/ # entities & value objects — pure TypeScript types application/ # use-cases (SendTextUseCase, FavoriteNodeUseCase, …) infrastructure/ # protobuf ↔ domain mappers, admin-message adapters state/ # signals-backed reactive stores Client.ts # public facade exposing readable signals + command methods index.ts ``` The shared kernel under `packages/sdk/src/core/` owns: - **`client/`** — `MeshClient`, the thin orchestrator that owns the transport, queue, event bus, and one instance of every slice client. - **`transport/`** — the `Transport` interface every `transport-*` package implements. - **`event-bus/`** — typed pub/sub channels populated by the packet codec. - **`packet-codec/`** — frame parser (0x94 0xC3), `FromRadio` decoder, portnum router. - **`queue/`**, **`xmodem/`** — packet ack/timeout pipeline and file-transfer protocol. - **`signals/`** — signal and keyed-collection helpers consumed by every slice. - **`logging/`** — `tslog` factory used consistently by every class. - **`identifiers/`**, **`errors/`** — small primitives shared across slices. The protobuf boundary is strict: wire messages enter through the packet codec, get mapped into domain entities inside `features/*/infrastructure/*Mapper.ts`, and signals only ever expose the domain shape. ``` Transport ─▶ Packet codec ─▶ EventBus ─▶ Slice infrastructure │ ▼ Signals (state) ─▶ sdk-react hooks ─▶ UI ▲ │ Slice application (use-cases) ─▶ MeshClient.sendPacket ─▶ Queue ─▶ Transport ``` Expected domain errors are returned as `Result` via [`better-result`](https://www.npmjs.com/package/better-result); exceptions are reserved for programmer errors and truly exceptional conditions. ## Getting Started ### Prerequisites You need [pnpm](https://pnpm.io/) installed. If you plan to regenerate protobufs, also install the [Buf CLI](https://buf.build/docs/cli/installation/). ### Setup ```bash git clone https://github.com/meshtastic/web.git cd web pnpm install ``` ### Run the web client ```bash pnpm --filter @meshtastic/web dev ``` ### Build everything ```bash pnpm -r build ``` ### Run tests ```bash pnpm -r test ``` ### Lint + format ```bash pnpm check pnpm check:fix ``` ## Developing ### Adding a new feature slice to `@meshtastic/sdk` 1. Create `packages/sdk/src/features//` with `domain/`, `application/`, `infrastructure/`, `state/` subdirectories plus an `index.ts` barrel. 2. Implement a signals-backed store in `state/`. 3. Subscribe to the relevant `EventBus` channel(s) inside a `Client.ts` class and write mapped domain entities to the store. 4. Wire the new client into `MeshClient` and re-export types from `packages/sdk/mod.ts`. 5. Add vitest coverage: domain invariants, use-cases against `createFakeTransport()`, and round-trip mapper fixtures. 6. If the slice has React callers, add a matching hook under `packages/sdk-react/src/hooks/`. ### Adding a new transport Implement the `Transport` interface exported from `@meshtastic/sdk/transport`: ```ts interface Transport { toDevice: WritableStream; fromDevice: ReadableStream; disconnect(): Promise; } ``` The SDK does the framing and decoding — transports only supply raw bytes. ### Testing Vitest is wired at the repo root and picks up `packages/*` projects. The SDK ships `@meshtastic/sdk/testing` with `createFakeTransport()` for wiring tests without real hardware. ## Publishing Each publishable package has `build:npm` / `publish:npm` / `prepare:jsr` / `publish:jsr` scripts. See each package's `package.json` for details. ## Repository activity | Project | Repobeats | | :------------- | :-------------------------------------------------------------------------------------------------------------------- | | Meshtastic Web | ![Alt](https://repobeats.axiom.co/api/embed/e5b062db986cb005d83e81724c00cb2b9cce8e4c.svg "Repobeats analytics image") | ## Feedback If you encounter any issues, please report them in our [issues tracker](https://github.com/meshtastic/web/issues). Your feedback helps improve the stability of future releases. ## Star history Star History Chart ## Contributors ## License GPL-3.0-only. See [LICENSE](LICENSE).