Develop and Deploy a Chatbot in 20 minutes with Next.js and Vercel: A Step-By-Step Guide
In this walkthrough you’ll learn how to develop and deploy your own custom ChatGPT-like app from scratch using Next.js and Vercel. You won’t need any prior experience with AI in development but basic knowledge of React and Next.js will be helpful.
Setting up the project
If you’re already familiar with setting up a Next.js app, feel free to skip ahead.
- Open your terminal then navigate to the folder where you want to create your React app (e.g.
cd documents
will take you to thedocuments
folder)
For more information on simple terminal commands you can read my article Getting friendly with the terminal.
2. Once you’re in the relevant folder in the terminal, run the following command to create a Next.js app: npx create-next-app@latest
The first prompt asks you to choose a project name but for the rest of the prompts you can just use the default options (as shown above).
Great! And just like that we have a functioning Next.js app.
You can see how the app looks by running npm run dev
in the terminal (first make sure you’re in the app folder by running cd chat-app
) and then navigating to http://localhost:3000 in your browser. You should see the following:
Before we can proceed, we need to clean up some of the boilerplate code.
3. Open your newly created app in your IDE of choice. I am using Visual Studio Code. Your project should look similar to this:
4. Open the public
folder and delete both of the .svg
files (this folder should now be empty).
5. In src/app
delete the favicon.ico
.
6. Still in src/app
delete the the page.module.css
file, then open the globals.css
file and remove all the contents so you just have an empty file.
7. Finally, open the page.tsx
file, remove all the code, and add the following:
// src/app/page.tsx
export default function Home() {
return <h1>My Chatbot app</h1>;
}
Now, when you navigate back to http://localhost:3000 you should see:
And that’s the initial setup done! We can now start getting our hands dirty with AI…
Setting up OpenAI
In this tutorial, we’ll be using the OpenAI API and so you first need to make sure you have an account (if you’ve used ChatGPT then you will already have an account, if not you can easily set one up here).
Login to your account and then proceed to the API page. In the left sidebar click API keys
and you should see a page similar to this:
As you can see, I’ve already created an API key. If you don’t have one already you should create one by clicking Create new secret key.
Copy this key and then navigate back to your code. Open your terminal and export this key as an environment variable as follows:
Install the OpenAI Node.js library. To do this, run the following command in your terminal:npm install --save openai
Note: You’ll have to restart your server after this installation
Great! Now we’re all ready to use this API :)
Managing the OpenAI API
Now that we have access to the API, we next need to ensure that the requests we make and the responses we receive are handled securely.
To do this in Next.js, we use route handlers.
Next.js route handlers are responsible for handling requests and generating responses in a similar way to how server-side logic operates. By encapsulating sensitive operations within route handlers, we can securely handle confidential data before responding to client requests.
1. To create our route handler, navigate to src/app
and create a new folder called chat
and within this folder create a file called route.ts
.
2. Within this route.ts
file, import and initialise the OpenAI API:
// src/app/chat/route.ts
import OpenAI from "openai";
// Assign API key to variable
const apiKey = process.env.OPEN_AI_KEY;
// Initialise OpenAI API
const openai = new OpenAI({ apiKey: apiKey });
3. Finally, we add a POST request that will take user input (questions) from the frontend application and send these questions to the OpenAI API via our server, which will then return a response:
// src/app/chat/route.ts
export async function POST(req: Request) {
// The 'question' variable is the user's input from the frontend
const { question } = await req.json();
// Here is where we communicate with the OpenAI API to create our chatbot.
// We store the chatbot's response in the 'response' variable
const response = await openai.chat.completions.create({
messages: [
{
role: "system",
// We give the chatbot a role with some content to determine how it will behave
content:
"You are a helpful assistant who supports Liverpool FC",
},
{
// We ask the chatbot to generate an answer based on the user's question
// Remember, this question will come from the frontend
role: "user",
content: question,
},
],
// We choose the model we want to use for our chatbot
model: "gpt-3.5-turbo",
// We add a value for max_tokens to ensure the response won't exceed 300 tokens
// This is to make sure the responses aren't too long
max_tokens: 300,
});
// Then we return the response we receive from OpenAI
// Note: This will only work once we set up our frontend logic
return new Response(JSON.stringify(response));
}
Note: The code for the
response
variable above is almost a direct copy and paste from OpenAI’s quick start guide:
The function in the guide above sends a request to the OpenAI API with the prompt “You are a helpful assistant”. It then console logs the response from OpenAI.
Creating your Chatbot
So far, we’ve:
- Created a Next.js app from scratch.
- Gained access to the OpenAI API.
- Set up a route handler which sends a POST request to the OpenAI API.
The final step is to take all of this and make it into a functional app.
Before we get our hands dirty with the frontend code, we’ll need to install axios with the following command: npm install axios
— we’ll use this package to handle our HTTP requests.
Right now, we’re making a request to the OpenAI API but we don’t see any response. Let’s add our frontend functionality to see what the API can do:
// src/app/page.tsx
// In Next.js, we need to add this line to the top of our file to declare a
// boundary between Server and Client Component modules.
"use client";
// import useState so that we can update the response we get from the API
import { useState } from "react";
// import axios so we can easily send the user's input to our server
import axios from "axios";
import "./globals.css";
const App = () => {
// We store and update the responses we get from the API with this state
// I've added a default value to the 'response' state that we should see
// when the page initially loads
const [response, setResponse] = useState<string>("Hi there! How can I assist you?");
// We also store the input we get from the user in the 'value' state and
// update it everytime the user types into the input field we have added below
const [value, setValue] = useState<string>("");
// We use this function in the newly added 'input' in the return statement.
// Each time the user types into the input, this function ensures that the
// 'value' state is updated
// We also add a type to the event that we pass in
const onChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setValue(e.target.value);
// This function runs when the user presses the button we have added below
// This function takes the contents of 'value' (the input from the user)
// and then sends this value to our server, which then sends a new request
// to the API
// The function then waits for the new response and updates the 'response'
// value which we then display on the page
const handleSubmit = async () => {
const response = (await axios.post("/chat", { question: value })).data
.choices[0].message.content;
setResponse(response);
};
// In our return statement, we add an input field so that the user can ask
// questions to the API.
// We also add a button so that the user can submit their question which then
// updates the response from the API
// We show the updated response on our page
return (
<div className="container">
<div>
<input
type="text"
value={value}
onChange={onChange}
></input>
</div>
<div>
<button onClick={handleSubmit}>Click me for answers!</button>
</div>
<div>
<p>Chatbot: {response}</p>
</div>
</div>
);
};
export default App;
Now, when we navigate back to our browser, we should see a simple UI where we can ask a question:
Aaaand it works :) we essentially have our (pretty ugly) version of ChatGPT up and running, but that’s not even the coolest part.
We can customise our chatbot any way we want. I’m a huge Liverpool fan and so I’m going to customise my chatbot to be a fellow LFC fan who has a similar personality to one of my favourite players — Darwin Nunez.
This is where you can get creative and decide what type of ‘personality’ you want your chatbot to have. You can do this by editing the content
of the "system”
role in src/app/chat/route.ts
:
// src/app/chat/route.ts
// ...other code
const response = await openai.chat.completions.create({
messages: [
{
role: "system",
content:
"You love Liverpool FC. Your name is Darwizzy and you have a
personality similar to Darwin Nunez (a football player who currently plays
for Liverpool). You have latin and scouse humour.",
},
{
role: "user",
content: question,
},
],
model: "gpt-3.5-turbo",
max_tokens: 300,
});
// ... other code
So, how is it looking?
Haha. I love it.
Time to make Darwizzy look a bit nicer though.
Navigate to the globals.css
file and copy and paste the following code:
/* src/app/globals.css */
* {
box-sizing: border-box;
text-align: center;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: rgb(39, 40, 41);
}
input {
width: 100%;
padding: 1em;
margin-bottom: 1em;
border: 0.15em solid #ccc;
border-radius: 0.25em;
font-size: 1.2em;
}
button {
width: 100%;
padding: 1em;
background-color: #d60000;
color: #fff;
border: none;
border-radius: 0.25em;
cursor: pointer;
transition: background-color 0.3s ease-in-out;
font-size: 1.2em;
box-shadow: 0 0.25em 0.25em rgba(0, 0, 0, 0.1);
}
button:hover {
background-color: #b20000;
}
p {
margin-top: 1em;
padding: 1em;
background-color: #ffffff;
border-radius: 0.25em;
font-size: 1.2em;
box-shadow: 0 1em 0.25em rgba(0, 0, 0, 0.1);
}
.container {
max-width: 35em;
margin: auto;
margin-top: 1em;
margin-bottom: 2em;
padding: 2em;
border: 0.3em solid #b20000;
border-radius: 0.5em;
background-color: #f5f5f5;
}
You can see that I’m no UI/UX designer but it’s enough to get you started!
You did it! Well done! You’ve managed to integrate AI into a Next.js app.
And it’s just the beginning. Now you have this solid foundation, you can customise it even more and add even more functionality :)
Deploying your chatbot
Now you have your chatbot working locally, but why not share it with the world?
You can deploy your Next.js app for free using Vercel.
First of all, you’ll need to push your code to GitHub. If you know how to do this already feel free to skip ahead. Otherwise, navigate to your GitHub profile, then to Repositories, and then click the green New button.
Add the name of your repository and then click the green Create repository button.
Copy the highlighted code above and run it in your terminal to push your existing code. Now your code exists on GitHub, you can deploy and host it via Vercel.
Navigate to this link and create an account if you don’t already have one.
Once you’re all set up, you’ll need to add a new project:
If you haven’t already, you’ll have to give Vercel permission for either all or some of your repositories. I chose select repositories and then selected my chatbot repository.
Then click the green Install button.
Once you’ve allowed permissions for one or more repositories you’ll be able to import these. Click the import button for your chatbot repository.
You’ll be asked to choose a name for your project and you also need to add the OpenAI key as an environment variable here:
Note: You can see your OPEN_AI_KEY by running this command in your terminal:
echo $OPENAI_API_KEY
Then click Deploy.
Congratulations! You have successfully created and deployed a chatbot app! You can find the URL for your new app on your Vercel dashboard.
For example mine is https://chat-lfc.vercel.app/.
Now, every time you push code changes to your GitHub main
branch, Vercel will automatically redeploy your app with these changes! :)
I hope you found this walkthrough useful and I’d love to hear your feedback!
#YNWA