Implementing Secure Signed Cloudinary Media Uploads in Next.js App Router
How to upload high-resolution project screenshots and 100 MB walkthrough videos directly from the browser to Cloudinary using server-issued SHA-1 signatures.
Abdul Malek
Full-Stack Developer (MERN & Next.js)
The Serverless Payload Bottleneck
When deploying a Next.js application on serverless infrastructure like Vercel, routing a 50 MB project video or a batch of high-resolution screenshots through a Node.js API route will quickly hit request body size limits and increase function execution time.
At the same time, enabling unsigned public uploads on your Cloudinary account is dangerous because anyone could upload arbitrary files to your media bucket.
How Server-Signed Direct Uploads Work
The clean solution is a 3-step signed upload pipeline: first, an authenticated user requests a short-lived upload signature from a Next.js API route; second, the browser uploads the binary file directly to `https://api.cloudinary.com/v1_1/<cloud_name>/image/upload`; third, the client sends the resulting `secure_url` and `public_id` back to your API to save in MongoDB.
Generating the signature on the server requires zero external SDK bloat—Node’s built-in `node:crypto` module handles canonical parameter signing cleanly:
import { createHash } from 'node:crypto';
export function signCloudinaryParams(params, apiSecret) {
const canonical = Object.entries(params)
.filter(([, value]) => value !== undefined && value !== null && value !== '')
.sort(([left], [right]) => left.localeCompare(right))
.map(([key, value]) => `${key}=${value}`)
.join('&');
return createHash('sha1').update(`${canonical}${apiSecret}`).digest('hex');
}Extracting Video Poster Frames in the Browser
For project walkthrough videos, rendering an `<video preload="none">` element with a lightweight static `poster` image dramatically improves Core Web Vitals and saves mobile bandwidth.
Before uploading a video from the admin dashboard, we load the selected file into an offscreen `<video>` element, seek to a representative frame, draw it onto an HTML5 `<canvas>`, and export a compressed JPEG blob (`createVideoThumbnail` in `lib/projectVideos.js`). Both the video and its poster frame are then uploaded with signed parameters.
Validating URLs Before Saving to MongoDB
Even after a direct upload succeeds, the API route that saves metadata to MongoDB must verify that `secureUrl` uses the `https:` protocol, matches `res.cloudinary.com`, and contains the expected folder prefix (`publicId`). This prevents an attacker from injecting external tracking URLs into your database.
Real-World Implementation
See how these patterns were applied in production by reading the related project case study.
Related Technical Articles
Architecting a Multi-Admin E-Commerce & CMS Platform with Next.js and MongoDB
A practical engineering breakdown of server-verified order pricing, role-based access control, and schema design for a production Next.js and MongoDB commerce platform.
Read article Frontend Engineering · 5 min readHandling Unicode Graphemes and Real-Time WPM in a Bengali-English Typing Engine
Lessons learned building a dual-language (বাংলা & English) typing benchmark in React and Next.js without Unicode splitting bugs or keystroke lag.
Read article