Documentation
Frameworks & Languages
The SDK is TypeScript/JavaScript because it ships the CLI and web widgets. Duct itself is language-agnostic: your backend and agents talk to it over HTTP.
The rule of thumb
Use the SDK when you are building a JavaScript or TypeScript web app. Use REST when you are building in Python, Go, Ruby, Java, PHP, .NET, shell scripts, or an agent runtime.Supported Integration Styles
Next.js / React
Use @duct-sdk/sdk/next (or /react) for the widget and token helpers. Use @duct-sdk/sdk/server in API routes.
Vite + Express
Use @duct-sdk/sdk/vite for the frontend widget. Use @duct-sdk/sdk/server in the Express backend.
Remix
Use @duct-sdk/sdk/remix for the widget. Use @duct-sdk/sdk/server in loaders and action handlers.
SvelteKit
Use @duct-sdk/sdk/sveltekit. Server hooks use @duct-sdk/sdk/server.
Plain JavaScript
Embed the iframe and implement the postMessage token bridge manually.
Python
Call /v1/shell-token and /v1/shells/:id/invoke with httpx, requests, FastAPI, Django, or any HTTP client.
Go / Ruby / Java / PHP / .NET
Same REST API. You provide token issuance and endpoint auth in your stack.
CLI / scripts
Use curl for token generation, action invocation, smoke tests, or CI checks.
JavaScript REST Example
js
const auth = await fetch('https://auth.ductai.vercel.app/v1/shell-token', {
Python REST Example
python
import oscurl Example
bash
TOKEN=$(curl -s -X POST https://auth.ductai.vercel.app/v1/shell-token \
Vite + Express Guide
Vite serves the frontend; Express (or any Node.js server) handles the backend. They are separate processes with separate environment files. Keep secrets out of Vite.
Environment layout
bash
# /.env (or /backend/.env) — loaded by Express, never bundled by Vite DUCT_SECRET_KEY=sk_duct_... DUCT_SHELL_ID=shell_acme_prod # /frontend/.env — public vars, safe to expose in the browser bundle VITE_DUCT_SHELL_ID=shell_acme_prod VITE_DUCT_SHELL_HOST=https://shell.ductai.vercel.app
Never put DUCT_SECRET_KEY in a VITE_* var
Vite inlines allVITE_* variables into the browser bundle. Your signing secret must live only in the Express process environment, not the Vite build.Express token route
ts
import express from 'express';
Express auth middleware — Duct delegated token fallback
ts
import { verifyDuctToken } from '@duct-sdk/sdk/server';
Express webhook endpoint (optional)
Webhook payloads are HMAC-SHA256 signed. Verify before trusting the body. Webhooks require raw body access — mount the express.raw() parser on this route, not express.json().
ts
import crypto from 'crypto';
Webhooks are configured in the dashboard
Webhook URLs (deeplink callback, event stream) and the signing secret are not part ofduct.config.ts and are not pushed via duct push. Configure them in the Duct dashboard → Shell → Settings → Webhooks. They are optional for the core shell + widget + action flow.Vite frontend embed
tsx
import { DuctShell } from '@duct-sdk/sdk/vite';
If your language can make HTTPS requests, it can call Duct. The typed SDK is a convenience layer, not a platform requirement.