Skip to content

lott-ai/tauribun

Repository files navigation

tauribun logo

Tauribun

Build lightweight, blazing-fast desktop apps with Tauri + Bun

FeaturesHow It WorksInstallationUsageFAQ


What is Tauribun?

Tauribun is a Tauri plugin and template for building Tauri desktop applications with Bun running as a sidecar. If you love how light and fast Tauri is, but prefer writing backend logic in TypeScript instead of Rust, this is for you.

Tauribun connects your frontend to your Bun backend via oRPC over stdio, giving you full-stack TypeScript with native performance.

🤩 Want to see it in action? Check out the example app for a complete working implementation with React, TanStack Query, and shadcn/ui.

Features

  • 🚀 Native performance — Bun compiles to a single executable
  • 📦 Tiny bundle size — Tauri's minimal footprint + Bun's efficient runtime
  • 🔒 Type safety — End-to-end TypeScript with oRPC
  • 🎨 Full-stack TypeScript — No context switching between languages
  • Fast startup — ~10ms sidecar startup time
  • 🔌 Simple integration — Tauri plugin handles sidecar lifecycle

How It Works

┌─────────────────────────────────────────────────────────────┐
│                     Tauri Application                       │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────┐     ┌─────────────────────────┐   │
│  │   React Frontend    │◄───►│   Bun Sidecar Binary    │   │
│  │   (Webview)         │     │   (TypeScript backend)  │   │
│  │                     │     │                         │   │
│  │   • React UI        │     │   • oRPC Router         │   │
│  │   • TanStack Query  │     │   • Business Logic      │   │
│  │   • shadcn/ui       │     │   • File System Access  │   │
│  │                     │     │   • Native APIs         │   │
│  └─────────────────────┘     └─────────────────────────┘   │
│            │                           │                    │
│            └───────── stdio ───────────┘                    │
│                   (oRPC messages)                           │
└─────────────────────────────────────────────────────────────┘

The communication flow:

  1. Frontend uses TanStack Query to call oRPC procedures
  2. oRPC serializes the call and sends it via Tauri's shell plugin to the sidecar's stdin
  3. Bun sidecar processes the request and writes the response to stdout
  4. Frontend receives the response and updates the UI

This architecture keeps your Rust code minimal (just the Tauri plugin) while allowing you to write all your business logic in TypeScript.

Installation

Prerequisites

Quick Start

Install the plugin:

# Add the Rust plugin to your Tauri app
cargo add tauri-plugin-tauribun

# Add the TypeScript package
bun add tauri-plugin-tauribun

Register the plugin in your Tauri app (src-tauri/src/lib.rs):

pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_tauribun::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Include the plugin capabilities in your Tauri config (src-tauri/capabilities/default.json):

{
  "permissions": [
    "tauribun:default"
  ]
}

Usage

Add Bun binary in Tauri config

Compile your Bun backend to an executable binary and add it to your Tauri config (src-tauri/tauri.conf.json):

{
  "build": {
    "additionalWatchFolders": ["binaries"],
    "beforeDevCommand": "bun build --compile --watch ./src-bun/main.ts",
    "beforeBuildCommand": "bun build --compile ./src-bun/main.ts",
    "frontendDist": "../dist",
    "devUrl": "http://localhost:3000"
  },
  "bundle": {
    "externalBin": ["binaries/bun-server"]
  }
}

You can also extract the build command to a script (see examples/tauribun/scripts/build.ts).

Create the Backend server

Create your oRPC server in your Bun backend (src-bun/main.ts):

import { createServer } from "tauri-plugin-tauribun";
import { router } from "./router";

createServer("bun-server", router);

Define Backend Procedures

Create your oRPC router in your Bun backend (src-bun/router.ts):

import { os } from "@orpc/server";
import * as z from "zod";

export const router = {
  greet: os
    .route({
      method: "POST",
      path: "/greet",
      summary: "Greet the user",
    })
    .input(z.object({ name: z.string() }))
    .output(z.object({ greeting: z.string() }))
    .handler(async ({ input }) => {
      return { greeting: `Hello, ${input.name}!` };
    }),
    
  // Add more procedures here
  getSystemInfo: os
    .route({
      method: "GET",
      path: "/system-info",
    })
    .output(z.object({ 
      platform: z.string(),
      arch: z.string(),
    }))
    .handler(async () => {
      return { 
        platform: process.platform,
        arch: process.arch,
      };
    }),
};

export type Router = typeof router;

Call Procedures from the Frontend

Use TanStack Query (or call directly with the oRPC client) for type-safe calls:

import { useMutation, useQuery } from "@tanstack/react-query";
import { createClient } from "tauri-plugin-tauribun";
import type { Router } from "src-bun/router.ts";

// Create a typed client that spawns and connects to the Bun server
// Replace "bun-server" with the name of the binary you added to tauri.conf.json
const client = createClient<Router>("bun-server");

// You can call the oRPC client directly:
const response = await client.orpc.greet({ name: "World" });
console.log(response.greeting); // "Hello, World!"

// And you can use TanStack Query with the oRPC client:
const orpc = createTanstackQueryUtils(client.orpc);

function App() {
  // Query example
  const { data: systemInfo } = useQuery(
    orpc.getSystemInfo.queryOptions()
  );

  // Mutation example
  const { mutate: greet } = useMutation(
    orpc.greet.mutationOptions({
      onSuccess: (data) => console.log(data.greeting),
    })
  );

  return (
    <div>
      <p>Platform: {systemInfo?.platform}</p>
      <button onClick={() => greet({ name: "World" })}>
        Say Hello
      </button>
    </div>
  );
}

Examples

See the examples for more complete working implementations.

FAQ

Why Bun as a Sidecar?

Bun can compile TypeScript directly to a single executable binary. This means:

  • No Node.js runtime needed on the user's machine
  • Fast startup time (~10ms)
  • Small binary size (~50MB)
  • Full access to Bun's APIs (file system, SQLite, HTTP, etc.)

Why oRPC over stdio?

Tauri's sidecar communication is limited to stdio. Tauribun uses orpc-adapter-stdio to adapt messages for oRPC, providing end-to-end type safety between your frontend and backend.

What can I do in the Bun sidecar?

Anything you can do in Node.js/Bun:

  • File system operations
  • SQLite database (Bun has built-in SQLite)
  • HTTP requests to external APIs
  • Spawn child processes
  • Access environment variables
  • And more...

Contributing

We welcome contributions! Please see our Contributing Guide for details on:

  • Setting up the development environment
  • Understanding the project structure
  • Running tests and linting
  • Submitting pull requests

License

This project is open source and available under the MIT License.


Created by ShipWorthy ⛵️

About

Tauri + Bun powered desktop applications

Resources

Contributing

Stars

Watchers

Forks

Contributors