{
  "id": 18958643,
  "title": "Designing a Reliable Two-Photo Upload Flow for AI Video Apps",
  "url": "https://urgent.news/2026/11/08/designing-a-reliable-two-photo-upload-flow-for-ai-video-apps",
  "topic": "ai",
  "section": "AI",
  "published": "2026-11-08T15:12:26.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/bxb_koala_2c0b40f042ca6e8/designing-a-reliable-two-photo-upload-flow-for-ai-video-apps-43k5"
  },
  "original_language": "en",
  "account": "Two-image upload for AI video apps may seem like a straightforward UI issue, but it actually involves numerous potential failure modes. Users might inadvertently select the same file twice, upload files in unsupported formats, leave one slot empty, or replace a file after a preview URL has already been generated. This workflow can be applied to creating short music videos from portraits, comparison tools, before-and-after editors, and paired image generators.\n\nTo manage this workflow effectively, it's important to represent the two required inputs directly. A commonly used approach is to create a state object with variables for left and right slots, along with an errors object to store any validation issues. Using a generic array to represent these inputs can make ordering and replacement more complex to manage. Instead, named slots for the left and right images can make error messages clearer, such as \"Choose the second photo\" instead of \"Two files are required.\"\n\nBefore creating previews, it's crucial to run cheap checks first. This involves verifying the file type and size. Allowed file types include image/jpeg, image/png, and image/webp. The maximum file size should be limited to 10 MB. These checks can be performed on the client-side using JavaScript. The server should also carry out these same validations to ensure data integrity.\n\nWhen a file is replaced, it's important to clean up any previous object URLs to prevent memory leaks. The replacePreview function can be used to revoke previous object URLs and update the current file and preview URL. Additionally, object URLs should be revoked when the component unmounts or when the upload finishes.\n\nTo detect accidental duplicates, comparing file names alone is not enough. Two different files can have the same name, and the same file can be renamed. A lightweight comparison can be made by checking the file size and lastModified date. For a more robust check, the bytes of the file can be hashed using crypto.subtle.digest. This lightweight comparison can help avoid using the same file twice. However, hashing very large files on the main thread can be slow, so there should be a reasonable upload limit and progress indication if the check takes noticeable time.\n\nThe Generate button should only be enabled when both slots are valid and no request is currently running. This ensures that users have the opportunity to correct any validation errors before proceeding. Replacement controls should be disabled during the final request to prevent accidental changes to the preview. Additionally, each slot should have its own label, keyboard-accessible remove button, and a live error region to improve accessibility.\n\nAssistive technology, such as screen readers, should be able to interact with each slot independently. The native file input should remain available to ensure compatibility with assistive devices, even if the visible interface uses a styled drop zone. The feedback provided to users should not rely solely on color to indicate success or failure. This ensures that users with visual impairments can still understand the outcome of their actions.\n\nTesting should cover various awkward paths to thoroughly validate the implementation. Some scenarios to consider include: only the first slot filled, selecting the same file twice, replacing an accepted file with an invalid one, removing a file while validation is running, and handling object URL revocation after replacement and cleanup. By treating the pair of images as a small state machine, the implementation can effectively manage the various states and transitions, leading to a more robust and user-friendly experience.",
  "summary": "A two-image upload sounds like a small UI problem, but it has a surprising number of failure modes. Users can select the same file twice, mix unsupported formats, leave one slot empty, or replace a file after a preview URL has already been created. This is the approach I use for a workflow where two portraits become a short music video. The same pattern works for comparison tools,…",
  "key_points": [
    "Design two distinct image slots with named variables for clarity",
    "Perform client-side checks on file type, size before previews",
    "Clean up object URLs on file replacement to prevent memory leaks"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}