Next.js + Transloadit
Use Uppy in a Client Component and a small App Router endpoint that signs a fixed Transloadit Template without exposing the Auth Secret.
Executable recipe
Build the integration
The server route signs a fixed Template, and the Client Component gives Uppy the signed params before each upload.
- Create a Transloadit Template and put its ID, Auth Key, and Auth Secret in server environment variables.
- Add the Route Handler and protect it with the same authorization checks as the rest of your application.
- Render the UploadForm Client Component on a page and select a file to run the Template.
Install
yarn add @uppy/core @uppy/dashboard @uppy/react @uppy/transloadit transloaditapp/api/transloadit/route.ts
import { NextResponse } from 'next/server'
import { Transloadit } from 'transloadit'
export async function POST() {
const authKey = process.env.TRANSLOADIT_KEY
const authSecret = process.env.TRANSLOADIT_SECRET
const templateId = process.env.TRANSLOADIT_TEMPLATE_ID
if (!authKey || !authSecret || !templateId) {
return NextResponse.json({ error: 'Server configuration is incomplete' }, { status: 500 })
}
const transloadit = new Transloadit({ authKey, authSecret })
const { params, signature } = transloadit.calcSignature({ template_id: templateId })
return NextResponse.json(
{ params, signature },
{ headers: { 'Cache-Control': 'private, no-store' } },
)
}app/UploadForm.tsx
'use client'
import Uppy from '@uppy/core'
import TransloaditPlugin from '@uppy/transloadit'
import { Dashboard } from '@uppy/react'
import { useEffect, useState } from 'react'
import '@uppy/core/css/style.min.css'
import '@uppy/dashboard/css/style.min.css'
export function UploadForm() {
const [uppy] = useState(() =>
new Uppy().use(TransloaditPlugin, {
waitForEncoding: true,
async assemblyOptions() {
const response = await fetch('/api/transloadit', { method: 'POST' })
if (!response.ok) throw new Error('Could not authorize upload')
return response.json()
},
}),
)
useEffect(() => () => uppy.destroy(), [uppy])
return <Dashboard uppy={uppy} />
}Authentication
- Keep TRANSLOADIT_SECRET in an unprefixed server environment variable. Next.js exposes variables prefixed with NEXT_PUBLIC_ to browser bundles.
- The Route Handler uses the official Node SDK to sign the fixed Template ID and returns only short-lived params and a signature to the browser.
- Require the user authorization your product needs before returning a signature, and do not accept arbitrary Template IDs or Steps from the browser.
Limitations and operational notes
- The browser cannot protect an Auth Secret. Signature generation and authorization checks must remain in server-only code.
- waitForEncoding keeps the upload UI waiting for processing. For long jobs, use Assembly notifications or retrieve the Assembly later.
- The example authorizes one fixed Template. Dynamic fields still need server-side validation before they are included in signed params.
More integrations