Native window. Zero network. TypeScript end-to-end. Write your backend and frontend in TypeScript, ship a small native binary — no extra language to learn, no codegen step.
bunx @tynd/cli create my-app- TypeScript top to bottom. Backend, frontend, IPC, config — same language, no codegen.
- Two runtime modes, one API. Start with
lite(~6.5 MB native binary, no extra runtime needed). Switch tofullwith one config line when you need Bun's JIT or native-binding npm packages. - Native window, zero network. No HTTP server, no loopback TCP port, no firewall prompt. Frontend and IPC ride a native custom scheme.
- 30 OS APIs, identical in both modes —
fs(+ watcher, handles, symlinks, trash),sql(embedded SQLite),http,websocket,terminal(real PTY),compute(blake3/sha/CSPRNG),dialog,tray(runtime mutation + mouse enter/leave),menu(accelerators + checkbox/radio + context menu),notification(icon/sound/actions/schedule),clipboard(image + HTML + change monitor),shell(incl. reveal),process,sidecar,singleInstance(with argv forwarding + deep links),shortcuts(system-wide hotkeys),keyring(OS-encrypted secrets),autolaunch(start at boot),store,updater(signed auto-update + periodic check),workers,log(JSON-lines + rotation + console capture),power(idle time),security(capability ACL for fs + http),app(name/version/exit/relaunch),os/path,tyndWindow(multi-window + events + cursor + backdrop), plus typed emitters (bidirectional) and streaming RPC. - Zero-copy binary IPC. Multi-MB payloads (
fs.readBinary,compute.hash, …) skip JSON/base64 entirely — roughly 5-10× faster than the usual webview-framework binary path. - First-class installers.
tynd build --bundleemits.app/.dmg/.deb/.rpm/.AppImage/ NSIS.exe/.msi. Installer tools auto-download on first build — no manual setup. Built-in code signing (signtoolon Windows,codesign+ optional notarization on macOS). - Security defaults. Auto-injected CSP on every HTML response, OS-backed secret storage via
keyring, Ed25519-signed auto-updater so tampered binaries are rejected. - Streaming RPC that doesn't flinch. Async-generator backend handlers stream to the frontend with per-chunk flow control + batched DOM updates — 10k+ yields/sec without freezing the UI.
- Framework-agnostic. React, Vue, Svelte, Solid, Preact, Lit, Angular — anything that outputs a pure SPA.
- TypeScript backend, no codegen. The frontend types backend calls from
typeof backend— no.d.tsgeneration, no IDL, no schema file. - Native OS webview. The final binary doesn't ship a browser — it uses WebView2 / WKWebView / WebKitGTK, so you inherit the OS's paint loop, font stack, and accessibility for free.
- Two modes, one API.
litefor the smallest binary (~6.5 MB, embedded JS engine).fullwhen you need Bun's JIT or native-binding npm packages. Switch via one config line — every OS API works the same in both. - Zero network IPC. RPC and assets never touch TCP — no loopback port, no firewall prompt on first launch.
See COMPARISON.md for the full Tynd vs Tauri / Wails / Electron matrix (39 categories, 500+ rows).
TypeScript backend Native OS window
────────────────────────── ─────────────────────────
export async function greet() ◄── IPC ─ await api.greet("Alice")
events.emit("ready", payload) ─── push ─► api.on("ready", handler)
│
▼
tynd-full — your TypeScript runs on Bun, wrapped in a native host
tynd-lite — your TypeScript runs inside the native host, no extra runtime
Zero network. Frontend assets and IPC ride a native custom scheme — no HTTP server, no loopback port, no firewall prompt. Multi-MB binary payloads (fs.readBinary, fs.writeBinary, compute.hash, …) skip JSON entirely via a dedicated binary channel.
lite |
full |
|
|---|---|---|
| JS runtime | embedded interpreter — ships inside the native binary | Bun, packed into the native binary |
| Hot JS speed | interpreter — fine for IPC glue, slower on tight loops | Bun JIT — often 10-100× faster on CPU-bound JS |
| IPC overhead | in-process, no serialization hop | one serialization hop (OS pipe) |
fs / http / websocket / sql / compute / terminal / … |
yes, same API | yes, same API |
JS-level fetch / Bun.file / bun:sqlite |
no (use the Tynd API) | yes |
| Pure-JS npm packages | yes (bundled) | yes |
| npm with native bindings | no | yes |
| Binary size | smaller (~6.5 MB) | larger (~44 MB, Bun compressed) |
| Startup | faster (everything in-process) | slower (spawns Bun) |
-> See RUNTIMES.md for the full comparison (APIs, performance, detection, examples).
Bun is required for app developers. Tynd is a Bun-first framework — the CLI, the dev server, and the full runtime all run on Bun. Node.js is not supported as a replacement.
# macOS / Linux / WSL
curl -fsSL https://bun.sh/install | bash
# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"End users of your built app need nothing — whichever runtime mode you picked is already packed into the distributed binary.
bunx tynd create my-app
cd my-app
bun run devWith a specific framework / runtime:
bunx tynd create my-app --framework react --runtime full
bunx tynd create my-app --framework vue --runtime litetynd create [name] # scaffold a new project (interactive if no args)
--framework react|vue|svelte|solid|preact|lit|angular
--runtime full|lite
tynd dev # start app in development mode (HMR)
tynd start # classic JS build (frontend + backend) then run (no HMR)
tynd build # bundle backend + frontend -> single binary
--bundle [targets] # + installers: app, dmg, deb, rpm, appimage, nsis, msi (or "all")
tynd init # add tynd to an existing project
tynd clean # remove build artifacts (.tynd/cache, release/)
tynd validate # check config and project structure
tynd upgrade # upgrade @tynd/cli and @tynd/core to latest
tynd info # show environment info (Bun version, WebView, paths)
tynd keygen # generate an Ed25519 keypair for the auto-updater
tynd sign <file> # sign a file with an updater private key| Framework | Scaffold | Build | Fast Refresh (HMR) |
|---|---|---|---|
| React | Vite react-ts |
yes | Partial — breaks if React Compiler is enabled |
| Vue / Svelte / Solid / Preact | Vite <name>-ts |
yes | yes |
| Lit | Vite lit-ts |
yes | Full reload only — Web Components by design |
| Angular | Angular CLI | yes | Full reload by default (opt-in HMR via ng serve --hmr) |
tynd init also detects existing Vite, CRA, Angular CLI, Parcel, Rsbuild, and Webpack setups.
Blocked (SSR): Next.js, Nuxt, SvelteKit, Remix, Gatsby, Blitz.js, RedwoodJS, SolidStart, Angular Universal, Analog, Qwik City, Astro, TanStack Start, Vike. Use the SPA variant instead (plain Svelte vs SvelteKit, plain Solid vs SolidStart, …).
See FRAMEWORKS.md for the full matrix, per-framework notes, output-dir rules, and the React Compiler workaround.
my-app/
├── tynd.config.ts ← project config
├── package.json
├── backend/
│ └── main.ts ← backend entry — app.start() here
└── src/ ← frontend source (React / Vue / Svelte…)
└── main.tsx
Tynd exposes three surfaces — backend module, typed frontend RPC, and direct OS APIs:
| Surface | Import | Purpose |
|---|---|---|
| Backend | @tynd/core |
app.start, app.onReady, app.onClose, createEmitter |
| Frontend RPC | @tynd/core/client |
createBackend<typeof backend>() — typed proxy |
| OS APIs | @tynd/core/client |
app, dialog, tyndWindow, monitors, menu, clipboard, shell, notification, tray, process, fs, shortcuts, keyring, autolaunch, store, updater, log, power, security, os, path, http, websocket, sql, sidecar, terminal, compute, workers, singleInstance |
| Web APIs | @tynd/core/client |
fetch, WebSocket, EventSource, crypto, URL, Blob, FormData, AbortController, TextEncoder, … (re-exports for import * as tynd) |
Short example:
// backend/main.ts
import { app, createEmitter } from "@tynd/core"
export const events = createEmitter<{ ready: { message: string } }>()
export async function greet(name: string): Promise<string> { return `Hello, ${name}!` }
app.start({
frontendDir: import.meta.dir + "/../dist",
window: { title: "My App", width: 1200, height: 800, center: true },
})// src/App.tsx
import { createBackend, fs, process, terminal } from "@tynd/core/client"
import type * as backend from "../backend/main"
const api = createBackend<typeof backend>()
const msg = await api.greet("Alice") // typed string
await fs.writeText("data.json", JSON.stringify(state))
const { stdout } = await process.exec("git", { args: ["status"] })Full reference: API.md — every method, signature, and example.
import type { TyndConfig } from "@tynd/cli"
export default {
runtime: "full", // "full" | "lite"
backend: "backend/main.ts", // backend entry file
frontendDir: "dist", // built frontend assets (relative to project root)
icon: "public/favicon.svg", // optional — auto-detected; SVG recommended
window: {
title: "My App",
width: 1200,
height: 800,
center: true,
},
} satisfies TyndConfig| Field | Default | Description |
|---|---|---|
runtime |
"full" |
"full" or "lite" — see RUNTIMES.md |
backend |
"backend/main.ts" |
Backend entry file |
frontendDir |
"frontend" |
Built frontend output directory |
frontendEntry |
— | Simple TS/JS entry (no framework) — auto-bundled by tynd |
devUrl |
auto | Dev server URL override |
devCommand |
auto | Dev server start command override |
icon |
auto | App icon path — auto-detected from public/favicon.{ico,png,svg} |
binaryArgs |
— | Extra args passed to the tynd-full / tynd-lite binary |
window |
— | Default window options (title, width, height, center) |
Icon auto-detection order (SVG first — single source of truth renders pixel-perfect at every size):
public/{favicon,icon,logo}.svg -> public/{favicon,icon,logo}.{ico,png} -> assets/icon.{svg,png,ico} -> icon.{svg,png,ico}. One source feeds every output — each build produces a multi-size ICO (16/32/48/256) for Windows, a multi-entry ICNS (32/128/256/512/1024) for macOS .app, and a full hicolor PNG tree (16..512) for .deb / .rpm / .AppImage. PNG sources degrade to single-size; .ico sources pass through to Windows bundles and are skipped (with a warning) for macOS/Linux. Set icon explicitly to override.
| OS | WebView | Pre-installed? |
|---|---|---|
| Windows 10/11 | WebView2 (Edge Chromium) | yes |
| macOS | WKWebView | yes |
| Linux | WebKitGTK 4.1 | no — sudo apt install libwebkit2gtk-4.1-0 |
App authors don't need this section — @tynd/host's postinstall downloads pre-built binaries automatically. If you want to build the native host yourself:
# Requirements
rustup install stable
# Linux only
sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev libsoup-3.0-dev \
libxdo-dev libxss-dev
# Build
cargo build --release -p tynd-full
cargo build --release -p tynd-litepackages/
├── host-rs/ ← native host library (window + IPC + OS APIs)
├── full/ ← tynd-full binary (packs Bun inside the host)
├── lite/ ← tynd-lite binary (embeds a lightweight JS engine)
├── host/ ← @tynd/host (npm: postinstall downloads pre-built binaries)
├── core/ ← @tynd/core (TypeScript: app, createEmitter, client API)
└── cli/ ← @tynd/cli (TypeScript: tynd create/dev/build/info)
-> tynd.kvnpetit.com/docs — live versioned docs site.
| Doc | When to read it |
|---|---|
| GETTING_STARTED.md | First project — scaffold, dev, build, ship in 5 min |
| API.md | Every backend / frontend / OS API with signatures + examples |
| RUNTIMES.md | lite vs full — what each exposes, when to pick which |
| FRAMEWORKS.md | Per-framework matrix (React, Vue, Svelte, Solid, Angular, Preact, Lit) |
| COMPARISON.md | Tynd vs Tauri / Wails / Electron across 39 categories |
| SIGNING.md | Code signing + notarization workflows per OS |
| TROUBLESHOOTING.md | Common errors: missing binary, WebView2, GTK deps, Gatekeeper, etc. |
| CONTRIBUTING.md | Dev loop, commit style, PR process |
| Per-package READMEs | @tynd/core · @tynd/cli · @tynd/host |
| Working examples | playground/full (LLM chatbot, full runtime) · playground/example (minimal demo, lite runtime) |
| docs/ | Next.js 16 + Nextra 4 docs site (landing + versioned docs). Static export, deploys to Cloudflare Pages. bun --cwd docs run dev |