This black-box design memo uses public product pages, not source code, APIs, model behavior, or production architecture. The goal is to make a familiar UI problem discussable: a user can generate a visual identity, or configure a role-based presenter, and those outputs should not be reviewed as if they were identical.
Begin with two creative contracts
The AI Avatar Generator page publicly describes text- or photo-based avatar creation and visual styles. That suggests an identity-oriented contract: appearance, style, and reusable character direction are primary inputs.
The AI Digital Human Generator page publicly describes professional personas, camera angles, scenes, scripts, and multilingual delivery. That suggests a presentation-oriented contract: role, message, framing, and reviewable output context are primary inputs.
type Review = "missing" | "pending" | "approved" | "changes_requested";
type AvatarBrief = { mode: "identity"; style: "photorealistic" | "3d" | "anime"; appearancePrompt: string; likenessReview: Review };
type DigitalHumanBrief = { mode: "presenter"; role: "trainer" | "host" | "guide" | "custom"; scriptRevision: number; language: string; framing: "close" | "bust" | "full"; messageReview: Review };
type Brief = AvatarBrief | DigitalHumanBrief;
The discriminant controls required fields, stale-output logic, and reviewer responsibilities.
Snapshot inputs at generation time
The risk is not only failure. It is a successful response arriving after someone changes the script, language, or mode. If the interface renders the old output as current, a team can approve the wrong thing.
type Attempt = { id: string; brief: Brief; createdAt: string; status: "queued" | "running" | "succeeded" | "failed"; outputIds: string[] };
Persist a snapshot rather than a pointer to a mutable form. When a material field differs, show the result as stale. Keep it available for comparison, but do not let it silently inherit approval from a newer brief.
Make review state visible
stateDiagram-v2
[*] --> Draft
Draft --> BriefReady: required fields complete
BriefReady --> Generating: snapshot created
Generating --> OutputReady: generation succeeds
OutputReady --> Reviewing: facts, rights, language checked
Reviewing --> Approved: all required reviews pass
Reviewing --> Draft: brief revised
Approved --> Stale: upstream input changes
Stale --> Generating: new snapshot
OutputReady must not mean publishable. Identity work may need likeness, asset, and disclosure checks. Presenter work may need factual, pronunciation, localization, caption, and channel checks. Separating states prevents an export event from becoming an approval claim.
Test transitions, not imagined internals
- Changing a photo or appearance prompt marks identity outputs stale.
- Changing script, language, or framing marks presenter outputs stale.
- A late response cannot replace a newer snapshot.
- Switching modes keeps historical attempts but requires the new contract fields.
- A reviewer can see which brief revision produced an output.
- “Download available” and “approved for distribution” remain separate statuses.
The product lesson
A simple gallery makes both workflows look alike: choose inputs, generate a face, download a file. Yet identity creation asks whether a character is appropriate and consistent; presenter creation asks whether a role communicates a message faithfully. UI state should reflect that difference.
UGCVideo.ai is cited only as a public example of adjacent workflows. This model is a reusable proposal; a production implementation also needs retention rules, permission records, accessibility requirements, and platform-specific publication checks.
Preserve the brief that made an output, then make its route to approval explicit.
Add failure paths to the acceptance criteria
The happy path is simple: complete a form, start a request, receive an output, approve it. Most review defects happen outside that path. A browser tab can be reopened while an attempt is running. A collaborator can revise the script after a reviewer has opened a result. A network retry can create two visually similar attempts. A generated asset can be downloaded before the permissions record is complete.
The interface does not need to solve every policy question automatically. It does need to keep decisions legible. Show the snapshot revision beside the output. Show which checks are required for the current mode. Preserve a reason when an item is rejected. Avoid language such as “verified” when a reviewer has only opened a preview. If a warning requires a human decision, make that decision attributable rather than hiding it behind a dismissible toast.
type ApprovalRecord = {
attemptId: string;
requirement: "facts" | "rights" | "captions" | "localization" | "channel";
state: "not_started" | "approved" | "rejected";
reviewerId?: string;
note?: string;
};
This type is intentionally ordinary. The value is not clever workflow automation; it is the ability to answer a basic question later: what was checked, against which version, and by whom? That question becomes important when an output is adapted for a second format or market.
Keep generation and publication separate
One final UI rule is worth making explicit. “Generated,” “downloaded,” “scheduled,” and “published” are different events. A product can expose all four without treating them as a single linear success condition. A creator may download a draft for internal review, then revise the brief. A publisher may prepare a channel-specific version that needs its own caption or disclosure review. Treating publication as a separate action protects users from accidentally carrying approval forward.
For teams building similar interfaces, the acceptance test should be simple: after any change, a reviewer can tell what changed, which outputs are affected, and what must happen before distribution. That is a better design target than a gallery that merely makes results look finished.
Top comments (0)