Theo's Typesafe CultTTC
Theo's Typesafe Cult3y ago
5 replies
Mocha

How to deploy API to Vercel

What's the easiest way to deploy a basic API endpoint to Vercel?

I made an Express app structured like:
api
 |--- index.js
package.json
pnpm-lock.yaml
vercel.json


api/index.js:
import express from 'express'
import cors from 'cors'

const app = express()

// Disable CORS rules
app.use(cors())

app.get('/', (req, res) => {
    res.send('It works!')
})

const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
    console.log(`API listening on PORT ${PORT} `)
})

export default app


vercel.json:
{
  "version": 2,
  "builds": [
    {
      "src": "index.js",
      "use": "@now/node"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "index.js"
    }
  ]
}


The API just uploads files to S3 or GCS, so I'm open to using any other language or framework. It will mainly be used in my T3 app, but I found Next.js really confusing with handling files (tried to use HTML form, formidable, multer, ...)

Docs I followed:
* https://vercel.com/docs/concepts/functions/serverless-functions/runtimes/node-js
* https://vercel.com/guides/using-express-with-vercel#standalone-express
Vercel Documentation
Learn how to use the Node.js runtime to compile Node.js Serverless Functions on Vercel.
Using the Node.js Runtime with Serverless Functions
Vercel Documentation
Learn how to deploy an Express.js application to Vercel using Serverless Functions.
How to Deploy an Express.js Application to Vercel
Solution
solved (solution is specific for my needs)
import { type File, type Files, IncomingForm } from 'formidable'

const form = new IncomingForm({ multiples: false })

async function parseForm(req: NextApiRequest) {
    const { file } = await new Promise<Files>((resolve, reject) =>
        form.parse(req, (err, _, files) => (err ? reject('Error parsing form') : resolve(files)))
    )

    return Array.isArray(file) ? file[0] : (file as File | undefined)
}

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse<{ url?: string; err?: string }>
) {
    const file = await parseForm(req).catch(() => undefined)

    if (!file) {
        res.status(400).json({ err: 'No file found' })
        return
    }
    // use the file...
}    
Was this page helpful?