DEV Community

Cover image for Stop Writing Glue Code: One Rust Core for Python & Node.js πŸ¦€
KOLOG B Josias Yannick
KOLOG B Josias Yannick

Posted on • Originally published at kologojosias.com

Stop Writing Glue Code: One Rust Core for Python & Node.js πŸ¦€

Note: This post was originally published on My Blog.

As developers, we often face a difficult choice when building high-performance libraries:

  1. Write in a high-level language (JS/Python) for ease of use but sacrifice raw performance.
  2. Write in a low-level language (Rust/C++) and deal with the nightmare of maintaining bindings for multiple languages.

If you've ever chosen the latter, you know the struggle. You end up juggling pyo3 for Python and napi-rs for Node.js. You have snippets of "glue code" scattered everywhere, inconsistent APIs across languages, and a CI pipeline that breaks if you look at it wrong.

I built BridgeRust to change that.

What is BridgeRust?

BridgeRust is a unified framework that lets you write your library once in Rust and automatically deploy native, high-performance bindings to both Python and Node.js (with more languages coming).

It's not just a binding generator; it's a complete toolkit that handles the boring stuff:

  • Project Scaffold: Set up a multi-language project in seconds.
  • Unified Macro System: One #[export] macro for all languages.
  • Type Conversions: Automatic mapping of Vec, Option, Result, and more.
  • Building & Publishing: Integrated CLI to build wheels and npm packages.

The "Write Once" Magic πŸͺ„

Here is how it actually looks to expose Rust code to the world using BridgeRust.

1. Initialize

cargo install bridge
bridge init my-awesome-lib
cd my-awesome-lib
Enter fullscreen mode Exit fullscreen mode

2. Write Rust

In src/lib.rs, you simply tag your functions and structs with #[export]. You don't need to know the internals of the Python C-API or V8.

use bridgerust::export;

#[export]
pub fn greet(name: String) -> String {
    format!("Hello, {}! This is logic from Rust.", name)
}

#[export]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

#[export]
pub fn fast_math(points: Vec) -> f64 {
    // Heavy computation here...
    points.iter().map(|p| p.x + p.y).sum()
}
Enter fullscreen mode Exit fullscreen mode

3. Build

bridge build --all
Enter fullscreen mode Exit fullscreen mode

That's it. BridgeRust generates:

  • A Python wheel (pip install ...)
  • A Node.js native addon (npm install ...)

Consuming the Library

The best part is that the generated bindings feel native in every language. We handle idiomatic naming conventions automatically (snake_case for Python, camelCase for JS).

Python:

import my_awesome_lib

print(my_awesome_lib.greet("Pythoneer"))

p1 = my_awesome_lib.Point(1.0, 2.0)
result = my_awesome_lib.fast_math([p1])
Enter fullscreen mode Exit fullscreen mode

Node.js:

const lib = require("my-awesome-lib");

console.log(lib.greet("JavaScripter"));

const p1 = new lib.Point(1.0, 2.0);
// Notice fast_math became fastMath automatically!
const result = lib.fastMath([p1]);
Enter fullscreen mode Exit fullscreen mode

Real-World Example: Embex

This isn't just a toy project. We built Embex, a universal vector database client, using BridgeRust. It connects to Pinecone, Qdrant, LanceDB, and more.

By using BridgeRust, we maintained a single codebase for the core logic (connection pooling, retry strategies, SIMD operations) while offering native packages for both Python (pip install embex) and Node.js (npm install @bridgerust/embex).

Why I Built This

  • Zero Boilerplate: I was tired of writing manual PyModule or napi_register_module definitions.
  • Performance: I wanted zero-cost abstractions where possible.
  • Consistency: I needed to ensure Python and JS users got exactly the same features and bug fixes at the same time.

Try it out!

BridgeRust is open source and I'd love to hear your feedback on the API design.

Stop writing glue code. Start building bridges. πŸ¦€πŸŒ‰


Have you tried maintaining cross-language bindings before? Let me know in the comments what your biggest pain point was!

Top comments (0)