Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DecartAI/sdk/llms.txt
Use this file to discover all available pages before exploring further.
This example demonstrates how to use the Decart proxy middleware with Express to enable secure client-side SDK usage without exposing your API key to the browser.
What You’ll Build
An Express server that:
- Proxies Decart API requests from the browser
- Keeps your API key secure on the server
- Requires zero changes to client-side SDK code
- Serves a simple frontend demo
Architecture
Browser (SDK) → Express Server (Proxy) → api.decart.ai
(no API key) (API key attached) (API)
The client-side SDK makes requests to your Express server at /api/decart, which securely attaches your API key and forwards them to Decart’s API.
Prerequisites
- Node.js 18 or higher
- A Decart API key
Setup
Clone and navigate to the example
git clone https://github.com/decartai/sdk
cd sdk/examples/express-proxy
Configure your API key
Create a .env file:DECART_API_KEY=your-api-key-here
PORT=3000
Install dependencies
From the repository root:cd ../..
pnpm install
pnpm build
Server Code
The src/server.ts file sets up the proxy middleware:
import "dotenv/config";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { handler, route } from "@decartai/proxy/express";
import express from "express";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
// Serve static files (HTML, JS, CSS)
app.use(express.static("public"));
// Serve SDK from node_modules for the example
const sdkDistPath = join(__dirname, "../../../packages/sdk/dist");
app.use(
"/node_modules/@decartai/sdk",
express.static(sdkDistPath, {
setHeaders: (res, path) => {
if (path.endsWith(".js")) {
res.setHeader("Content-Type", "application/javascript");
}
},
})
);
// Mount the Decart proxy middleware
// All requests to /api/decart/* will be proxied to api.decart.ai
app.use(route, handler());
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
console.log(`Proxy endpoint: http://localhost:${port}${route}`);
});
Key Concepts
Proxy Middleware
The proxy middleware intercepts requests and forwards them with your API key:
import { handler, route } from "@decartai/proxy/express";
app.use(route, handler());
route is the path to mount the proxy (defaults to /api/decart)
handler() creates the middleware that forwards requests
By default, the handler reads DECART_API_KEY from process.env. You can also pass it explicitly:
app.use(route, handler({
apiKey: process.env.DECART_API_KEY,
}));
Client-Side Code
In your frontend, use the SDK with the proxy route:
<!DOCTYPE html>
<html>
<head>
<title>Decart Proxy Example</title>
</head>
<body>
<h1>Image Generation</h1>
<input id="prompt" type="text" placeholder="Enter a prompt" />
<button id="generate">Generate</button>
<div id="result"></div>
<script type="module">
import { createDecartClient, models } from '/node_modules/@decartai/sdk/index.js';
const client = createDecartClient({
proxy: '/api/decart', // Points to your Express proxy
});
document.getElementById('generate').addEventListener('click', async () => {
const prompt = document.getElementById('prompt').value;
const resultDiv = document.getElementById('result');
resultDiv.textContent = 'Generating...';
try {
const blob = await client.process({
model: models.image('lucy-pro-t2i'),
prompt,
});
const url = URL.createObjectURL(blob);
resultDiv.innerHTML = `<img src="${url}" alt="Generated image" />`;
} catch (error) {
resultDiv.textContent = `Error: ${error.message}`;
}
});
</script>
</body>
</html>
Security Benefits
- API Key Never Exposed - The key stays on the server
- No Client-Side Secrets - Browsers never see sensitive data
- Full Control - Add authentication, rate limiting, or logging
- Simple Migration - Works with existing SDK code
Using with ES Modules
The example uses native ES modules in the browser:
<script type="module">
import { createDecartClient, models } from '/node_modules/@decartai/sdk/index.js';
const client = createDecartClient({
proxy: '/api/decart',
});
// Use the SDK normally
</script>
No build step required!
Using with CDN
Alternatively, load the SDK from a CDN:
<script type="module">
import { createDecartClient, models } from 'https://esm.sh/@decartai/sdk';
const client = createDecartClient({
proxy: '/api/decart',
});
</script>
Adding Authentication
Add your own authentication layer:
import { handler, route } from "@decartai/proxy/express";
// Custom auth middleware
function requireAuth(req, res, next) {
const token = req.headers.authorization;
if (!token || !isValidToken(token)) {
return res.status(401).json({ error: "Unauthorized" });
}
next();
}
// Apply auth before proxy
app.use(route, requireAuth, handler());
Rate Limiting
Add rate limiting to prevent abuse:
import rateLimit from "express-rate-limit";
import { handler, route } from "@decartai/proxy/express";
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
});
app.use(route, limiter, handler());
Logging Requests
Log all proxy requests:
import { handler, route } from "@decartai/proxy/express";
app.use(route, (req, res, next) => {
console.log(`Proxy request: ${req.method} ${req.path}`);
next();
}, handler());
Custom Proxy Route
Change the proxy route path:
import { handler } from "@decartai/proxy/express";
app.use("/my-custom-proxy", handler());
Update client code:
const client = createDecartClient({
proxy: '/my-custom-proxy',
});
Production Deployment
Environment Variables
Set DECART_API_KEY in your production environment:
# Heroku
heroku config:set DECART_API_KEY=your-key
# Vercel
vercel env add DECART_API_KEY
# Docker
docker run -e DECART_API_KEY=your-key ...
CORS Configuration
For production, configure CORS properly:
import cors from "cors";
app.use(cors({
origin: ['https://your-frontend.com'],
methods: ['GET', 'POST'],
}));
HTTPS
Always use HTTPS in production to protect API requests.
Frontend Frameworks
React Example
import { createDecartClient, models } from "@decartai/sdk";
import { useState } from "react";
const client = createDecartClient({
proxy: '/api/decart',
});
export function ImageGenerator() {
const [prompt, setPrompt] = useState("");
const [imageUrl, setImageUrl] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const handleGenerate = async () => {
setLoading(true);
try {
const blob = await client.process({
model: models.image('lucy-pro-t2i'),
prompt,
});
const url = URL.createObjectURL(blob);
setImageUrl(url);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
return (
<div>
<input
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="Enter a prompt"
/>
<button onClick={handleGenerate} disabled={loading}>
{loading ? "Generating..." : "Generate"}
</button>
{imageUrl && <img src={imageUrl} alt="Generated" />}
</div>
);
}
Vue Example
<template>
<div>
<input v-model="prompt" placeholder="Enter a prompt" />
<button @click="generate" :disabled="loading">
{{ loading ? 'Generating...' : 'Generate' }}
</button>
<img v-if="imageUrl" :src="imageUrl" alt="Generated" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import { createDecartClient, models } from '@decartai/sdk';
const client = createDecartClient({
proxy: '/api/decart',
});
const prompt = ref('');
const imageUrl = ref(null);
const loading = ref(false);
const generate = async () => {
loading.value = true;
try {
const blob = await client.process({
model: models.image('lucy-pro-t2i'),
prompt: prompt.value,
});
imageUrl.value = URL.createObjectURL(blob);
} catch (error) {
console.error(error);
} finally {
loading.value = false;
}
};
</script>
Troubleshooting
CORS Errors
If you see CORS errors, ensure your Express app is properly configured:
import cors from "cors";
app.use(cors());
Module Not Found
If the SDK module isn’t found, ensure you’ve built the packages:
401 Unauthorized
Check that DECART_API_KEY is set in your .env file.