Building Picturesque AI: one studio, 50+ models, and the plumbing nobody wants to maintain Picturesque AI built a creative studio that integrates over 50 models for images, video, audio, editing, and motion control into a single interface with unified billing. The engineering team developed a service layer to normalize diverse provider APIs, a real-time update system using Socket.IO, and an agent called Director that plans multi-step creative workflows. The project involved refactoring a monolithic backend and implementing a credit-based pricing system. One creative studio for images, video, music, audio, editing, upscaling, and motion control. 50+ models, one credit balance. This is mostly about how we built it and what went wrong along the way. The problem from a dev perspective The models are good now. That's not really the issue anymore. The issue is everything around them. Different providers, different UIs, different billing. No shared history across modalities. No easy way to go from "generate image" to "animate it" to "add music" to "upscale" without opening four tabs. We wanted one place where you could actually finish something. What the product is Picturesque has a few main pieces: Studio - tabs for image, video, audio, edit, motion control Projects + Explore - save your work, browse what other people made Workflows - node canvas where you chain models together and run the pipeline in one go Director - an agent that plans multi-step creative work, quotes credits, and runs generations for you The studio covers a lot on its own. 4K images, cinematic video with audio, Suno music, ElevenLabs TTS, Topaz upscaling, motion control, talking avatars. The annoying engineering showed up once we tried to make all of that feel like one product instead of a folder of integrations. Stack kept boring on purpose Frontend is React, TypeScript, Vite, React Router. Backend is Node + Express. Socket.IO for real-time updates. Supabase for Postgres and auth. S3-compatible storage for outputs and uploads. For the actual model calls we built a service layer that normalizes inputs, maps our internal model IDs to provider APIs, and handles retries/errors in one place. Media stuff runs through FFmpeg and Sharp. Nothing fancy. When you're wiring up dozens of models with different schemas and pricing rules, you don't want your infra adding more chaos. We also refactored the backend out of a single 7,700-line server.js into routes + services. Painful refactor. Would do it again immediately. The unglamorous part: 50 models, one UI Every model has opinions. Kling wants duration, aspect ratio, sometimes start/end frames. Veo has quality tiers. Suno has like five different modes. Topaz pricing changes based on resolution and scale. What we ended up with: One frontend config models.ts and friends for capabilities, slugs, SEO, pricing display One backend pricing layer that calculates credit cost before deducting One generation flow per modality with model-specific validation shoved into the service layer One history table so everything shows up in the same grid The mapping layer is boring work. It's also the product. Without it you're just linking people to other people's tools. Real-time updates Generations take anywhere from a few seconds to a few minutes. Browser polling felt wrong. Rough flow: User clicks generate Backend creates the task, deducts credits, writes a pending history row A background workflow polls the provider until it's done Output gets uploaded to S3, DB gets updated, webhook fires Backend pushes a generation-update over Socket.IO Frontend updates the card in place Works fine until it doesn't. Reconnects, duplicate events, socket firing before the DB write lands. We ended up doing silent history refetches after completion to paper over the race conditions. Not elegant. Works. Director At some point we realized a generation UI isn't enough for a chunk of our users. Marketers don't care about picking Kling vs Veo. They want a TikTok ad. Director is the agent layer. You say what you want "5-slide carousel for my skincare brand" and it breaks it into steps, estimates credits, runs the generations. Three modes: auto - just go plan - show me the credit breakdown first ask - approve each generation There's also brand memory, specialist agents, social connectors, scheduled posting. Still iterating on all of it. Building an agent on top of an existing studio is weird. It needs to know what models exist, what they cost, what inputs they take, what's already in your history. The agent and the studio share the same generation code. That coupling is intentional. Workflows For people who want pipelines but don't want to click through tabs manually. Node editor on an infinite canvas. Wire image → video → audio nodes together, run the whole thing. Built with XYFlow. Studio tabs = "I know what I want" Workflows = "I want to chain this" Director = "just do it for me" Same backend, three entry points. Stuff we learned the hard way People compare credits, not just output quality. "How many Kling videos do I get for $30?" is a real question. We added a billing comparison table with approximate outputs per plan. People actually use it. Free tier is a product decision. 15 credits/day across all models, no card. Lets people try Nano Banana Pro or Kling before paying. Costs us compute. Seems worth it. Refund on failure or you lose trust immediately. If credits get deducted and the provider fails, that's it, user's gone. We had a bug early on where credits would deduct and the API would throw after. Added emergency refund logic in every catch block. New models never stop shipping. Keeping the config layer up to date is basically a permanent side job now. Still working on Better team collaboration on projects Director social posting integrations More workflow templates Not falling behind on model releases lol If you're building something similar Abstract providers early. Model IDs, pricing, input schemas. Even if you only have one provider today. Async delivery should be first-class. Webhooks + background workers beat client polling. One wallet, one history. Users shouldn't have to think about where their stuff lives. Build for different skill levels. Manual controls, pipelines, and agent automation are different users. Refund on failure. Seriously. Try it Live at aipicturesque.com. 15 free credits a day, all models. If you're working on something in this space, curious how other people are handling the model sprawl problem. Drop a comment. React, Node, Supabase, Socket.IO, and not enough documentation