crossbind
GitHub
GUIDE · GETTING STARTED · QUICK START

Quick start

Two paths lead to the same place: scaffold a fresh project, or add crossbind to an app you already have. Either way you end up with a bundler plugin, a crossbind.config.js, and a header you can import from JavaScript.

Prerequisites

The web, WASI and Android toolchains ship as Docker images, so crossbind needs very little installed on your machine:

  • Docker - runs the web image for WebAssembly and WASI and the android image for Android. Both are pulled automatically on the first build.
  • Node.js 24+.
  • CMake 3.28+ - mobile only.
  • Xcode and CocoaPods - iOS only, macOS only.
  • A Rust toolchain (cargo plus the platform targets) - only when you bind Rust. See Rust.
  • wasmtime - only to run platform: 'wasi' output and the prebuilt -bin-wasi tools.
shell
docker --version
node --version
docker pull ghcr.io/crossbind/web:1.0.8 # optional: the first build pulls it anyway
iOS
Xcode looks for Node.js in the system environment. If it is not there, link it once: ln -s $(which node) /usr/local/bin/node.

Set it up with a coding agent

Using Claude Code, Cursor, Copilot or similar? Install the skill once - your agent then carries the project inspector, the current port catalog and the per-framework playbooks, and you can ask it to add crossbind without pasting anything.

shell
npx skills add https://github.com/crossbind/crossbind/tree/main/agents/skills --global --yes

Drop --global to install it into this project only. Without the skill, hand over this prompt instead - it sends the agent to the Markdown docs, inspects the repo, installs the right packages, writes the config and wires your bundler or build script:

prompt
Add crossbind to this project so I can call C++ or Rust from JavaScript/TypeScript. Inspect the repository, implement the integration, and verify it.
 
Start with the crossbind documentation index at https://crossbind.dev/llms.txt and follow the links relevant to this project. If the crossbind skill is already available, use it.
 
1. Identify the package manager, framework or bundler, target runtimes, existing native sources, and any crossbind configuration.
2. Choose the integration, compatible package versions, release channel, and platform variants from the documentation. Prefer supported prebuilt ports and generated bindings. Install every crossbind package, ports included, from the npm `beta` tag; the default tag is older.
3. Reuse existing native code. If none exists, add a minimal C++ example and call it from the application.
4. Configure the build and runtime initialization for the detected targets. Reuse existing configuration and dependency entries, preserve unrelated behavior, and apply platform requirements where relevant.
5. Run the relevant build and verify at least one JavaScript-to-native call. Report the changes, commands run, results, and anything you could not verify. Include the Wasm artifact size when one is produced.
 
Follow the repository's conventions and make the smallest complete integration. Ask for clarification only when missing information prevents a correct implementation.

Prefer to do it yourself? Keep going.

A new project

The scaffolder wires the bundler, its plugin and a starter crossbind.config.js for you. Answer the prompts - if you are unsure, pick Web, React and Vite.

shell
npm create crossbind@beta
shell
? Project name › my-app
? Where should we create your project? › ./my-app
? What kind of project? › Web
? Choose framework / variant › React
? Choose bundler / ecosystem › Vite

Every prompt can be preselected positionally, which is how CI and scripted setups create a project:

shell
npm create crossbind@beta my-app Web React Vite

Then install and start the dev server - and skip to your first call.

shell
cd my-app
npm install
npm run dev

An existing project

Already have an app? Install the plugin for your bundler and register it. Vite is shown here; Webpack, Rspack, Rollup and Metro follow the same shape with their own plugin - see Bundlers.

shell
npm install -D @crossbind/plugin-vite@beta
Versions on this page
Every install command here follows the npm beta tag. When this page was built it resolved to [email protected] (changelog), @crossbind/[email protected] (which requires crossbind ^2.0.0-beta.62) and [email protected]. Each package keeps its own version; for a setup you can reproduce later, pin those exact ones:
shell
npm create crossbind@2.0.0-beta.62 my-app Web React Vite
npm install -D @crossbind/plugin-vite@2.0.0-beta.62 crossbind@2.0.0-beta.62
vite.config.js
import { defineConfig } from 'vite';
import viteCrossbindPlugin from '@crossbind/plugin-vite';
 
export default defineConfig({
plugins: [viteCrossbindPlugin()],
});

The plugin reads a crossbind.config.js from your project root. The minimal one is two lines - paths.config anchors every other path to this file, so it is never optional:

crossbind.config.js
export default {
paths: {
config: import.meta.url,
},
};

Everything else this file can carry is in Configuration.

Your first call

C++ lives under src/native. Declare the class in a header - the public surface has to be in the header, because that is what the binder reads.

src/native/MySampleClass.h
#pragma once
#include <string>
 
class MySampleClass {
public:
static std::string sample() {
return "Hello World!";
}
};

Now import that header from your app code and call it. initNative() is exported by the header module itself; one call boots every native module you imported.

src/main.js
import { initNative, MySampleClass } from './native/MySampleClass.h';
 
await initNative();
console.log(MySampleClass.sample());
First build
The first npm run dev compiles the wasm inside Docker and can take a while. After that the cache makes rebuilds incremental, and editing the header hot-reloads the page.

Build for production

Nothing special: your bundler build triggers the release compile through the plugin.

shell
npm run build

Targeting Node, Cloudflare Workers, React Native or WASI instead? Each one is a crossbind build flag combination - see Runtimes.

Where to next

  • C++ bindings - what the auto-binder accepts, and the C++ ↔ JS type table.
  • Libraries - use a prebuilt library instead of compiling one.
  • Filesystem - where files live in the browser, Node and on edge.
  • Troubleshooting - when the first build does not go to plan.
Type to search every guide page and section.
↑↓ navigate↵ openesc close