| import Fastify from "fastify"; |
| import { z } from "zod"; |
| import { renderPresentation } from "./render.js"; |
|
|
| const app = Fastify({ logger: true }); |
|
|
| const Slide = z.object({ |
| layout: z.enum(["title", "section", "bullets", "chart_and_insight", "image_reference"]).default("bullets"), |
| title: z.string(), |
| subtitle: z.string().optional(), |
| bullets: z.array(z.string()).default([]), |
| insights: z.array(z.string()).default([]), |
| notes: z.string().optional() |
| }); |
|
|
| const Presentation = z.object({ |
| title: z.string(), |
| theme: z.record(z.unknown()).default({}), |
| slides: z.array(Slide).default([]), |
| provenance: z.array(z.record(z.unknown())).default([]) |
| }); |
|
|
| app.get("/health", async () => ({ status: "ok" })); |
|
|
| app.post("/render", async (request, reply) => { |
| const spec = Presentation.parse(request.body); |
| const pptx = await renderPresentation(spec); |
| reply.header("content-type", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); |
| reply.header("content-disposition", "attachment; filename=\"visual-runtime-deck.pptx\""); |
| return reply.send(pptx); |
| }); |
|
|
| const port = Number(process.env.PORT ?? 8787); |
| await app.listen({ host: "0.0.0.0", port }); |
|
|