{"slug": "building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to", "title": "Building Picturesque AI: one studio, 50+ models, and the plumbing nobody wants to maintain", "summary": "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.", "body_md": "One creative studio for images, video, music, audio, editing, upscaling, and motion control. 50+ models, one credit balance.\n\nThis is mostly about how we built it and what went wrong along the way.\n\nThe problem (from a dev perspective)\n\nThe models are good now. That's not really the issue anymore.\n\nThe 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.\n\nWe wanted one place where you could actually finish something.\n\nWhat the product is\n\nPicturesque has a few main pieces:\n\nStudio - tabs for image, video, audio, edit, motion control\n\nProjects + Explore - save your work, browse what other people made\n\nWorkflows - node canvas where you chain models together and run the pipeline in one go\n\nDirector - an agent that plans multi-step creative work, quotes credits, and runs generations for you\n\nThe 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.\n\nStack (kept boring on purpose)\n\nFrontend 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.\n\nFor 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.\n\nNothing fancy. When you're wiring up dozens of models with different schemas and pricing rules, you don't want your infra adding more chaos.\n\nWe also refactored the backend out of a single 7,700-line server.js into routes + services. Painful refactor. Would do it again immediately.\n\nThe unglamorous part: 50 models, one UI\n\nEvery model has opinions.\n\nKling 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.\n\nWhat we ended up with:\n\nOne frontend config (models.ts and friends) for capabilities, slugs, SEO, pricing display\n\nOne backend pricing layer that calculates credit cost before deducting\n\nOne generation flow per modality with model-specific validation shoved into the service layer\n\nOne history table so everything shows up in the same grid\n\nThe mapping layer is boring work. It's also the product. Without it you're just linking people to other people's tools.\n\nReal-time updates\n\nGenerations take anywhere from a few seconds to a few minutes. Browser polling felt wrong.\n\nRough flow:\n\nUser clicks generate\n\nBackend creates the task, deducts credits, writes a pending history row\n\nA background workflow polls the provider until it's done\n\nOutput gets uploaded to S3, DB gets updated, webhook fires\n\nBackend pushes a generation-update over Socket.IO\n\nFrontend updates the card in place\n\nWorks 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.\n\nDirector\n\nAt 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.\n\nDirector 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.\n\nThree modes:\n\nauto - just go\n\nplan - show me the credit breakdown first\n\nask - approve each generation\n\nThere's also brand memory, specialist agents, social connectors, scheduled posting. Still iterating on all of it.\n\nBuilding 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.\n\nWorkflows\n\nFor people who want pipelines but don't want to click through tabs manually.\n\nNode editor on an infinite canvas. Wire image → video → audio nodes together, run the whole thing. Built with XYFlow.\n\nStudio tabs = \"I know what I want\" Workflows = \"I want to chain this\" Director = \"just do it for me\"\n\nSame backend, three entry points.\n\nStuff we learned the hard way\n\nPeople 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.\n\nFree 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.\n\nRefund 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.\n\nNew models never stop shipping. Keeping the config layer up to date is basically a permanent side job now.\n\nStill working on\n\nBetter team collaboration on projects\n\nDirector social posting integrations\n\nMore workflow templates\n\nNot falling behind on model releases (lol)\n\nIf you're building something similar\n\nAbstract providers early. Model IDs, pricing, input schemas. Even if you only have one provider today.\n\nAsync delivery should be first-class. Webhooks + background workers beat client polling.\n\nOne wallet, one history. Users shouldn't have to think about where their stuff lives.\n\nBuild for different skill levels. Manual controls, pipelines, and agent automation are different users.\n\nRefund on failure. Seriously.\n\nTry it\n\nLive at aipicturesque.com. 15 free credits a day, all models.\n\nIf you're working on something in this space, curious how other people are handling the model sprawl problem. Drop a comment.\n\nReact, Node, Supabase, Socket.IO, and not enough documentation", "url": "https://wpnews.pro/news/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to", "canonical_source": "https://dev.to/picturesque_ai/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to-maintain-3goo", "published_at": "2026-07-09 21:20:36+00:00", "updated_at": "2026-07-09 22:05:44.601662+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-products", "ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Picturesque AI", "ElevenLabs", "Topaz", "Suno", "Kling", "Veo", "Supabase", "Socket.IO"], "alternates": {"html": "https://wpnews.pro/news/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to", "markdown": "https://wpnews.pro/news/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to.md", "text": "https://wpnews.pro/news/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to.txt", "jsonld": "https://wpnews.pro/news/building-picturesque-ai-one-studio-50-models-and-the-plumbing-nobody-wants-to.jsonld"}}