DEV Community

Diiiii
Diiiii

Posted on

Designing an AI Ad Workspace with Versioned Copy and Creative Assets

An AI ad interface can appear to be one form followed by one Generate button. The operational domain is larger: a product brief produces a set of text components, those components feed image or video directions, each channel imposes constraints, and every revision can invalidate an earlier approval.

This is an interface-level design proposal based only on public product pages. It does not describe any vendor's source code, private architecture, models, performance, or production behavior.

Model the brief as a dependency

The brief should be a revisioned object, not a paragraph copied into several prompts.

type Approval = "missing" | "pending" | "approved" | "rejected";

type CampaignBrief = {
id: string;
revision: number;
audience: string;
buyerStage: "awareness" | "comparison" | "returning";
promise: string;
evidence: string[];
offer: { text: string; expiresAt: string | null };
forbiddenClaims: string[];
approval: Approval;
};

If the promise, offer, or evidence changes, descendants should become stale. Keeping approval on a mutable text area invites old decisions to appear current.

The public AI Ad Copy Generator page shows inputs such as product details, audience, promotion, platform, tone, and language, followed by generated headlines, body copy, descriptions, and CTAs. That visible workflow motivates a structured copy-set object without revealing how the product is implemented.

Treat copy as a coordinated set

A headline and CTA are not independent records when they are approved as one ad. Store them in a set linked to the brief revision.

type CopySet = {
id: string;
brief: { id: string; revision: number };
channel: "search" | "social" | "ecommerce";
locale: string;
headline: string[];
primaryText: string[];
descriptions: string[];
callsToAction: string[];
state: "draft" | "review" | "approved" | "stale";
};

Arrays are useful for platforms that combine assets dynamically, but the UI should still preview plausible combinations. A headline may be accurate alone and misleading beside a particular description. Validation therefore needs both component-level and combination-level rules.

Create immutable generation attempts

Asynchronous generation and live editing create race conditions. An attempt should capture the exact dependencies used when it starts.

type GenerationAttempt = {
id: string;
kind: "copy" | "image" | "video";
briefRevision: number;
copySetId: string | null;
inputSnapshotHash: string;
status: "queued" | "running" | "succeeded" | "failed" | "canceled";
outputIds: string[];
};

A late response must not overwrite outputs generated from a newer brief. A retry should either reuse the same snapshot or explicitly create an attempt from current inputs.

Connect creative assets without collapsing them

The public AI Ad Maker page presents image ads, short videos, ad copy, digital actors, voice or uploaded audio, gestures, and aspect-ratio choices. In a similar workspace, image and video variants should reference a copy set but keep their own delivery state.

type CreativeVariant = {
id: string;
copySetId: string;
medium: "image" | "video";
ratio: "1:1" | "9:16" | "16:9";
changedVariable: "hook" | "scene" | "actor" | "pace" | "ratio";
hypothesis: string;
review: {
claims: Approval;
brand: Approval;
rights: Approval;
delivery: Approval;
};
};

The text dependency should be visible. If an approved phrase changes, affected image overlays, voice tracks, captions, and exports should be marked stale rather than silently remaining approved.

Define state transitions around invalidation
stateDiagram-v2
[*] --> BriefDraft
BriefDraft --> BriefApproved: facts and offer approved
BriefApproved --> CopyDraft: create copy set
CopyDraft --> CopyApproved: component and combination review
CopyApproved --> CreativeDraft: create media variants
CreativeDraft --> FinalReview: outputs generated
FinalReview --> Ready: claims, brand, rights, delivery pass
Ready --> BriefDraft: dependency changes
FinalReview --> CreativeDraft: revise one variant

This is a proposal, not an observed implementation. The important transition is the path back to BriefDraft. Approval is conditional on a dependency graph, not a permanent badge.

Put constraints near the fields they govern

Channel limits and policy requirements should not live only in a final error dialog. Show them beside the relevant component and count the serialized value that will actually be submitted.

Useful validations include:

a required promise has at least one evidence item;
offer dates and locale-specific formatting are valid;
forbidden claims do not appear in any component;
every dynamic headline/description combination remains coherent;
captions and overlays match the approved copy revision;
required rights and disclosure confirmations are present;
crops preserve product and text safe zones for each ratio.

Do not label a generated variant as “high-performing” based on generation alone. Store it as a candidate until external campaign evidence is attached.

Preserve human review as data

A comment in a chat thread is difficult to audit. Store reviewer, timestamp, scope, decision, and the exact revision reviewed.

type ReviewDecision = {
targetType: "brief" | "copySet" | "creativeVariant";
targetId: string;
revision: number;
category: "claim" | "offer" | "brand" | "rights" | "delivery";
decision: "approved" | "rejected";
note: string;
};

This also avoids an “approve all” control that hides disagreements between legal accuracy, brand voice, and visual execution.

Test the failure paths

High-value tests focus on dependency changes:

Editing an approved offer marks every dependent copy set and creative stale.
Changing locale invalidates copy, pronunciation, and caption review without deleting history.
A failed generation attempt retains its input snapshot and can be retried.
A late response cannot attach itself to the newest revision.
Removing a product asset identifies every dependent creative.
Search components are previewed in more than one valid combination.
Every export can be traced to brief, copy, and asset revisions.
Keyboard and screen-reader users can identify blockers before generation.
Keep the observation boundary explicit

UGCVideo.ai is the public example used to frame the workflow. The types, transitions, and validation rules above are independent design proposals.

The larger lesson is simple: generation is an event inside a versioned system. When the brief, copy set, media asset, and approval are modeled separately, a team can produce many variations without losing the ability to explain what each one says, where it came from, and whether it is ready to use.

Top comments (0)