Skip to content

Image Upload Handling

Images in the dashboard (article thumbnails and editor-inserted images) are uploaded directly to S3. The backend generates a short-lived signed URL, and the browser uploads directly to it.

  1. User selects or drops an image file.

  2. Client-side validationsrc/lib/s3-upload.ts checks file type and size before making any network request.

  3. Request a signed URL — the upload helper calls POST /api/v1/sign-s3 (set in VITE_UPLOAD_URL) with the filename and MIME type.

  4. Backend returns the signed URL — a pre-signed S3 PUT URL that expires in 5 minutes, plus the final public object URL.

  5. Upload directly to S3 — the helper sends a PUT request to the signed URL with the file as the body. The file goes straight to S3 — not through the Express server.

  6. Save the public URL — the returned public URL is stored in the article’s thumbnail field or inserted into the CKEditor body.

FilePurpose
src/lib/s3-upload.tsUpload helper with retry and progress tracking
src/lib/s3-config.tsS3 client configuration from Vite env vars
src/components/ui/ckeditor.tsxCKEditor with built-in S3 upload adapter

When you drop or paste an image into the CKEditor, the upload adapter inside ckeditor.tsx runs the same flow automatically. The image is uploaded and the public URL is inserted as an <img> tag in the article body.