Below is how much tries I had to perform until I finally deployed Recite, my Node.js/Express app on Vercel successfully.

Let’s see what all steps I performed.
You can deploy mostly, any Node.js/Express app on Vercel with this method.
Pre-requisites
Node.js/Express app, a GitHub repository, and a Vercel account.
Initial State of the App
This is the initial project file structure of my Express app.

And the index.js
file:
const express = require("express");
const dotenv = require("dotenv");
const quoteRoute = require("./routes/QuoteRoute");
const cors = require("cors");
const connectDb = require("./utils/connectDb");
const errorHandler = require("./middlewares/errorHandler");
const notFound = require("./middlewares/notFound");
const apiRequestLimiter = require("./middlewares/rateLimit");
const app = express();
dotenv.config();
connectDb();
app.use(express.json());
app.use(cors({ origin: "*" }));
app.use(apiRequestLimiter);
app.use("/api/v1", quoteRoute);
app.use(notFound);
app.use(errorHandler);
const port = process.env.PORT;
app.listen(port, () => {
console.log(`listening on http://localhost:${port} `);
});
Every route of my app is through “/api/v1”.
Steps to Deploy to Vercel
1. Export “index.js” app as a handler
On Vercel, we can’t “listen” like in a normal express server.
app.listen(port, () => {
console.log(`listening on http://localhost:${port} `);
});
We need to export the app as a handler.
module.exports = app;
Final index.js
code looks like this:
const express = require("express");
const dotenv = require("dotenv");
const quoteRoute = require("../routes/QuoteRoute");
const cors = require("cors");
const connectDb = require("../utils/connectDb");
const errorHandler = require("../middlewares/errorHandler");
const notFound = require("../middlewares/notFound");
const apiRequestLimiter = require("../middlewares/rateLimit");
const app = express();
dotenv.config();
connectDb();
app.use(express.json());
app.use(cors({ origin: "*" }));
app.use(apiRequestLimiter);
app.use("/api/v1", quoteRoute);
app.use(notFound);
app.use(errorHandler);
const port = process.env.PORT;
module.exports = app;
2. Create “Vercel.json” file in the root directory

And copy paste the code below:
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "index.js"
}
]
}
This vercel.json
file tells us if we want to use a custom build for our app.
Breakdown
1. Specifying the version of our app:
"version": 2
2. Telling Vercel to build index.js as a Node.js serverless function using Vercel’s Node runtime.
"builds": [
{
"src": "index.js",
"use": "@vercel/node"
}
]
3. The below code tells Vercel that any request that comes to “/” endpoint, should be handled by the Express app at index.js
.
"routes": [
{
"src": "/(.*)",
"dest": "index.js"
}
]
But right now, there’s a mistake in our project.
If we don’t create an “api” folder on the root directory, and don’t paste the index.js
file there, Vercel wouldn’t treat it as a serverless function and none of the routes in our app will work.
So we need to make 2 changes:
1. Locate index.js
inside the “api” folder in root directory:

2. Update vercel.json
to reflect the new “api” folder change:
{
"version": 2,
"builds": [
{
"src": "api/index.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "api/index.js"
}
]
}
3. Deploy the app to Vercel
You must have a GitHub repo for this.
Login to vercel.com and import the GitHub repo, then simply deploy it. You will see the below status.

And if we go to the URL, we will see the below page.

Why 404?
Because of notFound
handler that we have in our code on index.js
file.
app.use(notFound);
Because if you see the index.js file, we don’t have any route for the home endpoint (“/”), so the Express app points us to the notFound
handler, which has this code:
const notFound = (req, res, next) => {
const error = new Error("Resource not found");
error.status = 404;
return next(error);
};
module.exports = notFound;
Fix
On index.js
file, I can simply create a new route for the home endpoint.
app.get("/", (req, res) => {
res.json({ success: true, message: "Recite - Quotes API is running..." });
});
Now if you hit this URL: https://recite-flax.vercel.app/api/v1/random
You will see that the app is working!

You can use this Recite REST API in your application to get any random quote!
Errors:
1. Misconfiguration in your ‘vercel.json
’ file
Sometimes, you may get this error on your Vercel log:

Because most likely, vercel.json
would have some incorrect configuration.
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "index.js"
}
]
}
We need to include “@” on the use
property’s value:
{
"version": 2,
"builds": [
{
"src": "index.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "index.js"
}
]
}
Verdict
Hope you learnt how to deploy a Node.js/Express app to Vercel using the above steps.
Thankfully, Vercel’s serverless concept is quite faster than Render’s free tier.

Hence, I moved my REST API to Vercel.
I am also using this API on Vocabsaga, a vocabulary learning platform where you can learn new words through passages and sentences, not random single words.
Contact me on X (Twitter) or LinkedIn for any queries.