// server/api/generate-deck.ts
import { FastifyInstance } from "fastify";
import fs from "node:fs";
const HEADERS = {
Authorization: `Bearer ${process.env.MODA_API_KEY!}`,
"Moda-Version": "2026-05-01",
};
export default async function (app: FastifyInstance) {
app.post("/generate-deck", async (req, reply) => {
const { pdfPath, userId } = (await req.body) as { pdfPath: string; userId: string };
// 1. upload the brief
const form = new FormData();
form.set("file", new Blob([fs.readFileSync(pdfPath)]), "brief.pdf");
const uploadRes = await fetch("https://api.moda.app/v1/uploads", {
method: "POST",
headers: { Authorization: HEADERS.Authorization, "Moda-Version": HEADERS["Moda-Version"] },
body: form,
});
const brief = await uploadRes.json(); // { id: "file_...", ... }
// 2. find default brand kit
const kits = await fetch("https://api.moda.app/v1/brand-kits", { headers: HEADERS }).then(r => r.json());
const kit = kits.data.find((k: any) => k.is_default);
// 3. start the design task
const task = await fetch("https://api.moda.app/v1/tasks", {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({
prompt:
"Build a pitch deck from the attached brief. Use our brand styling. " +
"Prioritize real data and quotes from the brief; do not invent specifics.",
format: { category: "slides", width: 1920, height: 1080 },
number_of_slides: 10,
brand_kit_id: kit?.id,
attachments: [
{ file_id: brief.id, role: "source", label: "Brief" },
],
callback_url: "https://myapp.com/webhooks/moda",
idempotency_key: `deck:${userId}:${brief.id}`,
}),
}).then(r => r.json());
reply.send({
message: "Generating deck — takes 2–10 minutes. You'll get a notification when it's ready.",
task_id: task.id,
canvas_url: task.links?.canvas ?? null, // useful placeholder while it cooks
});
});
}