An AI video form can look simple: add a product, choose a presenter, generate, and download. The engineering problem is larger. A useful production interface must preserve what the user intended, show which inputs produced each result, and stop a completed render from being mistaken for an approved ad.
This is an interface-level design exercise based on public pages. It does not describe private code, APIs, models, queues, or measured performance. The types and transitions are proposals for discussing a similar system.
Model the brief before the media
Treating a brief as one text field makes downstream review difficult. Product facts, audience assumptions, creative direction, and distribution constraints change at different times and have different owners. A structured record makes those dependencies visible.
type EvidenceStatus = "unreviewed" | "approved" | "rejected";
type AdBrief = {
id: string;
revision: number;
product: {
name: string;
sourceUrl?: string;
images: string[];
facts: Array<{ text: string; status: EvidenceStatus }>;
};
audience: { description: string; situation: string };
objective: "explain" | "demonstrate" | "recommend" | "announce";
channel: "tiktok" | "instagram" | "youtube" | "other";
locale: string;
ratios: Array<"9:16" | "1:1" | "16:9">;
};
The revision matters. If a fact changes while a video renders, the returned asset belongs to the old snapshot. Keep it for traceability, but do not silently place it under the newest brief.
Separate two creative contracts
Presenter-led UGC and product-led demonstration share components, but their acceptance criteria differ. One benefits from a coherent speaker perspective; the other depends on product visibility and fidelity.
type CreativeContract =
| { kind: "ugc"; perspective: string; presenterRef: string; voiceRef: string }
| { kind: "product"; requiredShots: string[]; preservePackaging: boolean };
The distinction is visible in public examples. The UGC Ad Generator page centers a product-to-script-to-presenter flow and exposes choices such as avatar, voice, language, format, and direction. It does not reveal implementation details, but it suggests a contract where the speaker and script are first-class review targets.
The AI Product Ad Generator page emphasizes product images and selling points, unboxing or demonstration scenes, scripts, presenters, and multi-format output. That suggests a different contract: the item, its appearance, and the sequence of evidence need explicit checks.
Store immutable generation attempts
A mutable “current output” loses useful history. Prefer an attempt record that captures an input snapshot and never changes after submission.
type GenerationAttempt = {
id: string;
brief: { id: string; revision: number };
contract: CreativeContract;
scriptRevision: number;
state: "queued" | "running" | "succeeded" | "failed" | "cancelled";
outputIds: string[];
failure?: { stage: string; retryable: boolean; publicMessage: string };
};
“Retry” should be explicit. Retrying the same snapshot diagnoses execution failure. Starting from current inputs creates a new creative attempt. Combining both actions under one button makes comparisons unreliable.
Protect against stale responses as well. When asynchronous work returns, associate it by attempt ID rather than writing it into whichever brief is open.
Make review a state, not a checkbox
Rendering success answers only whether the system produced a file. Publication requires independent approvals.
type ReviewArea = "facts" | "product" | "visuals" | "audio" | "captions" | "rights" | "channel";
type ReviewRecord = {
outputId: string;
areas: Record;
notes: Array<{ timecode?: number; area: ReviewArea; text: string }>;
decision: "pending" | "revise" | "approved";
};
Do not set approved when the technical job succeeds. Labels can drift, hands can obscure an object, a voice can mispronounce a name, captions can conflict with speech, and an accurate creative can still use an unapproved claim.
Design variants before generation
Variant tools invite users to change many controls at once. The outputs look different, but the team cannot explain what was tested. Add a hypothesis and one controlled dimension.
type Variant = {
id: string;
attemptId: string;
hypothesis: string;
changed: "hook" | "presenter" | "shot-order" | "voice" | "ratio" | "cta";
parentId?: string;
};
Keep product facts, presenter, voice, and sequence fixed while changing the hook. A ratio adaptation can inherit from the selected creative but remain a distinct output because cropping and safe areas require review.
Test failure and revision paths
The happy path is the least revealing part of the interface. A useful test plan includes:
Edit an approved fact and confirm dependent scripts and outputs become stale.
Submit generation, change the brief, and prevent the old response from overwriting the new revision.
Retry a failed snapshot while preserving both attempt records.
Start from current inputs and label it differently from a retry.
Switch from UGC to demonstration and require the new contract's review areas.
Change locale and reopen script, pronunciation, caption, and disclosure checks.
Change from 16:9 to 9:16 and require a safe-area review.
Reject one claim while preserving unrelated approved facts.
Keep download permission separate from publication approval.
Keep the boundary visible
UGCVideo.ai is the public product family used to frame this exercise. A real implementation needs direct requirements, observed editor behavior, accessibility work, security review, retention decisions, and policy checks.
The reusable principle is provenance. A reviewer should know which brief revision, facts, script, presenter, assets, and settings produced a video, then see what changed afterward. When that chain is visible, AI output becomes reviewable work. When it is hidden, a polished preview can conceal an outdated assumption.
Top comments (0)