Chainbox

The Infinite Interface

"The SDK isn't a library. It's a lens. It lets your frontend see your backend as a set of infinite local powers."

The "Library-First" Myth

"What if your backend wasn't across the network, but right there in your browser? What if the network was just a transparent pipe? That is the Chainbox reality."

The Big Picture

When you trigger a backend call from the browser, Chainbox handles the heavy lifting automatically:

HTML
cb-call="Sum"
Transport
Signed POST
Logic
Executing Capability
Result
Success DOM Update

Full "Hello World" Tutorial

Let's build a simple "Add Numbers" feature from scratch using the CDN library.

1. Define the Backend (Capability)

Create a file at src/_chain/Math.Add.ts. This is pure backend code.

export default async function Add(ctx, input) {
  // input.a and input.b come from the browser
  return input.a + input.b;
}

2. Create the HTML Page

No build tools required. Just plain HTML.

<!DOCTYPE html>
<html>
<head>
  <!-- Configure the library -->
  <meta name="chainbox:url" content="http://localhost:4000/execute">
  <script src="https://unpkg.com/@sddion/chainbox/dist/chainbox.min.js"></script>
</head>
<body>
  <!-- The magic button -->
  <button 
    cb-call="Math.Add" 
    cb-input='{"a": 10, "b": 20}' 
    cb-on-success="showResult">
    Calculate
  </button>

  <div id="output"></div>

  <script>
    function showResult(sum) {
      document.getElementById('output').innerText = "The sum is: " + sum;
    }
  </script>
</body>
</html>

Isomorphic Design

The SDK automatically adapts its transport mechanism based on the execution environment:

Server-Side

Next.js SSR / API

Uses Local transport to execute functions directly in-process for maximum speed and zero network latency.

Client-Side

Browser

Uses Http transport to POST requests to the backend securely.

Key Dependencies

The Client SDK relies on a minimal set of high-performance libraries:

  • @supabase/supabase-js
    Primary Database & Auth Used as the primary provider for database interactions and authentication state management.
  • undici
    High-performance HTTP Used for the Mesh transport layer to ensure fast and reliable network requests.
  • jiti
    Runtime Compilation Handles runtime TypeScript compilation to load user functions dynamically without a build step.
  • jose
    JWT Handling Provides secure JSON Web Token signing, verification, and management.

Zero-Config (CDN)

For plain HTML/CSS projects, use the lightweight CDN bundle (dist/chainbox.min.js). It features zero-config auto-discovery and professional-grade security.

<!-- Auto-configure via meta tags -->
<meta name="chainbox:url" content="https://api.yourproject.com/execute">
<script src="https://cdn.yourproject.com/chainbox.min.js"></script>

Scoped Environment Variables

Chainbox automatically fetches .env files from your server and syncs them to both JavaScript (Chainbox.env.get()) and CSS (--cb-env-*).

Security Enforcement:

By default, **only** variables starting with PUBLIC_ are exposed to the browser. This prevents your database keys or private secrets from leaking to users.

SAFE (Exposed)
PUBLIC_SITE_NAME="My Project"
Accessible via JS and CSS.
UNSAFE (Hidden)
STRIPE_SECRET_KEY="sk_test..."
Stays on the server only.

Attribute-Driven Calls

Chainbox allows you to trigger backend logic directly from your HTML elements. This is the fastest way to build interactive features.

<button 
  cb-call="User.Update" 
  cb-input="#profile-form" 
  cb-on-success="notify">
  Save Profile
</button>
Attribute Description
cb-call Required. The name of the backend function to run.
cb-input Optional. Can be a CSS selector (like #my-form) or raw JSON data.
cb-on-success Optional. The name of a JavaScript function to run after success.

Chainbox Inspector

In development mode (localhost) or when enabled via CHAINBOX_INSPECTOR=true, a floating visual overlay allows you to inspect the logical trace of every backend call in real-time.

Click the "C" bubble in the corner to see exactly what happened under the hood. It's like having "X-Ray vision" for your backend.

JavaScript API Reference

If you prefer writing code over attributes, use the global Chainbox object.

Chainbox.Call(name, input)

Triggers a backend capability and returns the result.

const result = await Chainbox.Call("Sum", { a: 1, b: 2 });
console.log(result); // 3

Chainbox.env.get(key)

Gets a public environment variable.

const name = Chainbox.env.get("PUBLIC_APP_NAME");

Lifecycle Events

Listen to results globally or on specific elements.

document.addEventListener('cb-success', (e) => {
  const { detail } = e;
  alert("Execution finished: " + JSON.stringify(detail));
});