codingetandCodex 493eef3b7b
CI / lint (pull_request) Successful in 4m19s
CI / format (pull_request) Successful in 4m2s
CI / install (pull_request) Successful in 10m5s
CI / typetest (pull_request) Successful in 3m11s
CI / typecheck (pull_request) Successful in 3m18s
CI / node-tests (pull_request) Successful in 3m25s
CI / browser-tests (pull_request) Successful in 5m24s
docs: correct package guidance and label ownership
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-15 02:54:37 +00:00
2026-06-23 22:13:38 +00:00

webnet

A TypeScript monorepo for transport-based networking, anchored by a WebAssembly Tailscale SDK. It provides a layered stack of packages — from raw transport and virtual filesystem abstractions through HTTP, WebSocket, WebDAV, FTP, SSH, SFTP, SMB, and Taildrive — that work in browsers, Node.js, and any environment that can supply a transport.

Those packages exist to be composed into an application. That application is Tailshare.

Tailshare

packages/tailshare is the flagship application of this repository, and the reason the rest of it exists. It is a browser app that joins a tailnet directly from the page and moves files across it, and it is the intended surface for everything the stack implements: Tailscale connectivity over WebAssembly, remote filesystems browsed over the protocol packages, and peer-to-peer transfers with no server in the middle.

The other packages are libraries; Tailshare is the product. When a capability lands in a library package — or is planned in the open issues — Tailshare is where it is expected to become usable. example-app and test-app are development and protocol-testing surfaces, not the product.

Tailshare is under active development and does not yet expose the whole stack. Its README tracks what works today and what the open issues intend for it.

Inspiration

This is heavily inspired by the WebVM networking stack that leverages Tailscale in the browser. Note that this doesn't lift any code from that project, only ideas.

Another inspiration is the ElysiaJS documentation that seemingly allows running a webserver from the docs directly in the browser (even if it is just a feature of the framework itself and not real networking).

How it works

Tailscale already ships a tsconnect package that compiles the IPN (in-process networking) stack to WASM via GOARCH=wasm. This repo builds on top of that with a layered set of packages:

  1. Patching tsconnect: the tailscale submodule tracks a fork on the webnet branch that extends the Go-to-JS bridge (wasm_js.go) to expose lower-level networking primitives: raw TCP/UDP connections, ICMP, TLS dialing, and TCP listening.
  2. @webnet/transport: declares the RawTransport, RawListener, and RawDialer interfaces, plus buffer utilities and transport implementations for loopback, Node.js streams, and WebRTC.
  3. @webnet/state-transfer: provides the generic StateTransferable ownership-transfer contract and runtime type guard without transport or protocol dependencies.
  4. @webnet/tsconnect: builds the WASM artifact, ships it alongside a Mozilla CA bundle and wasm_exec.js, and wraps the raw JS bridge in typed TypeScript classes. Its Conn, TCPListener, and IPNDialer implement the @webnet/transport interfaces, making it a drop-in transport source for the rest of the stack.
  5. @webnet/tsconnect-redux / @webnet/tsconnect-react: Redux Toolkit (RTK) slice and React hooks/context for IPN state management and control, extracted from the core SDK so consumers can bring their own UI framework.
  6. @webnet/tsconnect-worker: runs the IPN in a SharedWorker, synchronizes state through Redux, and can fall back to the main thread when workers are unavailable.
  7. @webnet/vfs: defines the shared async virtual filesystem used by the file protocols, with in-memory, Node.js, and File System Access API implementations.
  8. Protocol packages: client and server implementations for HTTP, WebSocket, WebDAV, FTP/FTPS, SSH, and SFTP are built on the transport and VFS layers, alongside an SMB client. @webnet/http-static serves a VFS over HTTP, while @webnet/taildrive connects WebDAV shares to Tailscale peers.
  9. Apps and UI helpers: reusable browser and React utilities support the example and test applications, and above all Tailshare, the flagship app that composes the whole stack into a usable product.

Packages

Each package has its own README with entry points and usage; the table links to them.

Package Description
packages/tailshare Flagship application: tailnet file sharing in the browser
packages/transport Transport interfaces with loopback, Node.js streams, and WebRTC implementations
packages/state-transfer Generic ownership-transfer contract and runtime type guard
packages/tsconnect Tailscale WASM SDK, IPN lifecycle, typed wrappers, and transport implementation
packages/tsconnect-worker SharedWorker and main-thread bindings for @webnet/tsconnect with Redux state synchronization
packages/tsconnect-redux Redux Toolkit slice, bindings, actions, and selectors for IPN state management
packages/tsconnect-react React hooks and context for IPN state management and control
packages/vfs Async virtual filesystem interface, implementations, fallbacks, and conformance tests
packages/http HTTP/1.1 client and server, connection pool, redirect following, and middleware router
packages/http-static Static file HTTP handler backed by an async VFS
packages/websocket WebSocket client and server based on @webnet/http
packages/webdav WebDAV Level 1 and optional Level 2 client and server based on @webnet/http
packages/ftp FTP/FTPS client and server backed by an async VFS
packages/ssh SSH-2 client and server connections, channels, sessions, and TCP forwarding
packages/sftp SFTP client and server backed by an async VFS
packages/smb2 SMB2/3 client implementing the async VFS interface
packages/taildrive Taildrive peer discovery, WebDAV client helpers, and server bridge
packages/xml XML parsing and serialization with browser-native and Node.js backends
packages/react Shared React hooks, error display, and browser capability helpers
packages/utils Browser, binary-data, upload, download, and formatting utilities
packages/browser-test-utils Shared Playwright utilities for browser integration tests
packages/example-app Example app demonstrating the browser stack
packages/test-app Vite app for manual and end-to-end protocol testing

Submodules

The tailscale/ directory is a git submodule pointing to a fork of the Tailscale repository. The webnet branch on that fork contains the Go-side patches to tsconnect.

git submodule update --init tailscale

Development

# Build the WASM assets
npm run build-go --workspace=packages/tsconnect

# Build the TypeScript package
npm run build --workspace=packages/tsconnect

# Start the test app
npm run dev --workspace=packages/test-app

# Expose a development app to a trusted remote host or reverse proxy
npm run dev:host --workspace=packages/test-app

# Lint and format
npm run lint
npm run format

Remote-host development

Development apps provide two deliberate modes:

  • npm run dev --workspace=packages/<app> is local-only and retains the dev server's host-header protections.
  • npm run dev:host --workspace=packages/<app> binds to all network interfaces and accepts forwarded hostnames. Use it only on a trusted network, such as a Tailnet or an authenticated code-server proxy: a dev server can expose source maps, development endpoints, and application credentials or state.

The hosted mode leaves the HMR websocket URL relative to the page URL, so it works through a reverse proxy without baking a container or localhost address into the app. Configure that proxy to forward WebSocket upgrade requests (Upgrade and Connection headers) to the dev server, including the Vite HMR endpoint or webpack-dev-server's /ws endpoint.

Commits must follow the Conventional Commits spec. ESLint and Prettier are also required to pass. This is enforced at commit time by husky with commitlint and lint-staged.

Package boundaries

Each package owns its public API. Packages may import another package's public entry points, but may not re-export those dependencies; consumers should import symbols from the package that defines them. Wildcard exports are also forbidden so API changes remain explicit and reviewable.

_internals entry points are intentionally unstable and carry no semantic versioning compatibility guarantee. They are available only to their owning package's tests and tooling. Cross-package _internals imports are forbidden in both production and test code; tests should use public APIs or package-local fixtures instead.

AI disclosure

Most of the code in this repository was AI-generated. The entire patch set in the Tailscale fork under tailscale/ was also AI-generated.

S
Description
No description provided
Readme
14 MiB
Languages
TypeScript 98.7%
JavaScript 0.6%
Shell 0.3%
SCSS 0.2%
HTML 0.1%