Deploying frontend applications quickly and reliably is essential for fast iteration and consistent user experience. While Vercel is known for its seamless integration with Git-based workflows, setting up a custom CI/CD pipeline using GitHub Actions gives you more control over how and when deployments are triggered.
In this article, you'll learn how to deploy a frontend application to Vercel using GitHub Actions. This setup allows you to define your own deployment logic, automate builds, and push updates without relying on Vercel’s default Git integrations.
We’ll walk through everything from cloning the project to configuring GitHub Actions to deploy changes automatically. By the end of this guide, you'll have a custom, production-ready CI/CD pipeline tailored to your frontend application's needs.
Why Not Just Use Vercel’s Default Git Integration?
While Vercel's built-in Git integration is convenient, it lacks the flexibility needed for more complex workflows. Using GitHub Actions gives you full control over your CI/CD pipeline—ideal for monorepos, multi-step build/test logic, or when you need conditional deployment rules that Vercel's default setup doesn't support.
Prerequisites
Before diving into the deployment setup, make sure you meet the following requirements:
- A TypeScript-based frontend application that is production-ready. If you don’t already have one, you can clone the example project used in this guide and follow along.
- A GitHub repository where your frontend code resides. If you're cloning the example repo, push it to a new GitHub repository of your own.
- A Vercel account with a project already created. You’ll need your Vercel Project ID and a Vercel Personal Access Token, which we’ll use later when configuring the GitHub Actions workflow.
- Node.js and npm installed in your development environment, primarily for local testing. The deployment workflow will handle installation in the CI environment.
Table of Contents
- Cloning the Repository
- Understanding the Frontend Application
- GitHub Actions Workflow for Deploying to Vercel
- Obtaining Your Vercel Token
- Adding the Vercel Token to GitHub Secrets
- Deploying and Testing the Application
- Conclusion
Cloning the Repository
To follow along with this guide, you can use the sample project hosted at the GitHub repository below. The frontend application is located in the frontend
directory.
git clone https://github.com/EphraimX/blbjzl-ai-accountability-application-github-actions.git
cd blbjzl-ai-accountability-application-github-actions/frontend
The frontend is a TypeScript-based application designed to interact with an AI-powered backend for user accountability.
Understanding the Frontend Application
The core of the frontend application is located in the Chat.tsx
file under the /frontend/src/Component/
directory. This component handles the interactive chat interface between the user and the AI accountability bot. Here’s a breakdown of the key sections in the code:
1. State Management:
The messages
state holds an array of chat messages between the user and the bot. Initially, the bot sends a welcome message to start the conversation.
const [messages, setMessages] = useState<IMessage[]>([
{ sender: 'bot', content: 'Hey there! I’m BLBJZL, your personal accountability partner AI. I’m here to keep you on track, motivated, and moving toward your goals—no judgment, just solid support. Ready to tackle your to-do list together? Let’s do this. What’s first on the agenda?' },
]);
The input
state holds the current value of the user’s message input.
const [input, setInput] = useState('');
2. Message Structure:
The chat messages are structured as an array of objects, each containing a sender
(either 'user' or 'bot') and the content
of the message. The IMessage
interface is defined as follows:
interface IMessage {
sender: 'user' | 'bot';
content: string;
}
3. Sending Messages:
When the user types a message and presses send, the sendMessage
function is triggered. This function sends the user’s input to the backend via a POST request to the /chat
endpoint.
const sendMessage = async () => {
if (input.trim()) {
const newUserMessage: IMessage = { sender: 'user', content: input };
setMessages((prevMessages) => [...prevMessages, newUserMessage]);
try {
const response = await fetch('https://blbjzl-accountability-application-backend.fly.dev/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ user_input: input }),
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
const newBotMessage: IMessage = { sender: 'bot', content: data.reply };
setMessages((prevMessages) => [...prevMessages, newBotMessage]);
} catch (error) {
console.error('Error sending message:', error);
setMessages((prevMessages) => [...prevMessages, { sender: 'bot', content: 'Uh-oh, looks like the server’s not responding right now. No stress—we’ve got this. Give it another try, and if it still doesn’t work, we’ll troubleshoot it together. One step at a time!' }]);
}
setInput('');
}
};
4. Rendering the UI:
The component maps over the messages
array and displays each message in the chat window. Depending on the message sender, different icons (user or bot) are displayed alongside the message content.
<div className="chat-container">
{messages.map((message, index) => (
<div key={index} className={`message ${message.sender}`}>
{message.sender === 'user' ? (
<FontAwesomeIcon icon={faUser} className="icon" />
) : (
<FontAwesomeIcon icon={faRobot} className="icon" />
)}
<div className="message-content">{message.content}</div>
</div>
))}
</div>
The ChatInput
component is used for the user to type their messages. Here's how the input section is rendered:
<ChatInput value={input} onChange={(e) => setInput(e.target.value)} onSend={sendMessage} />
The ChatInput
component itself is defined as follows:
const ChatInput: React.FC<ChatInputProps> = ({ value, onChange, onSend }) => {
return (
<div className="send-container">
<input
type="text"
value={value}
onChange={onChange}
placeholder="Typing"
onKeyPress={(e) => e.key === 'Enter' && onSend()}
/>
<button type="button" onClick={onSend}>I’m Listening</button>
</div>
);
};
This component provides an input field for the user to type their messages and a button to send them. The user can either click the button or press "Enter" to trigger the onSend
function, which initiates the process of sending the user's message and receiving a response from the backend.
GitHub Actions Workflow for Deploying to Vercel
To automate deployments to Vercel whenever updates are pushed to the frontend/
directory on the main
branch, create a workflow file at:
.github/workflows/frontend-vercel-deploy.yml
The following workflow uses Node.js to install dependencies, build the project, and then deploy it to Vercel using the Vercel CLI:
GitHub Actions Workflow File:
name: Github Actions Client Deployment To Vercel
on:
push:
paths:
- 'frontend/**'
branches:
- main
jobs:
deploy-client-to-vercel:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Setup NodeJS
uses: actions/setup-node@v2
with:
node-version: '23'
- name: Install Dependencies
working-directory: ./frontend
run: npm install
- name: Build Project
working-directory: ./frontend
run: npm run build
- name: Deploy to Vercel
env:
VERCEL_TOKEN: ${{secrets.VERCEL_TOKEN}}
run: npx vercel --prod --token $VERCEL_TOKEN --yes --cwd frontend
Explanation of the Workflow Steps:
-
on.push
: This specifies that the workflow will trigger whenever there are changes pushed to thefrontend/
directory on themain
branch. This ensures that only changes related to the frontend app will trigger the deployment. -
jobs.deploy-client-to-vercel
: This defines a job calleddeploy-client-to-vercel
, which runs on theubuntu-latest
environment. It contains several steps to install dependencies, build the project, and deploy it to Vercel. -
Checkout Repository
:- This step uses
actions/checkout@v2
to clone the repository into the GitHub Actions runner, making all files available for the subsequent steps.
- This step uses
-
Setup NodeJS
:- This step ensures that the Node.js environment is set up using
actions/setup-node@v2
, specifying Node version 23. This is needed for building the frontend app using npm.
- This step ensures that the Node.js environment is set up using
-
Install Dependencies
:- This step navigates to the
frontend
directory (working-directory: ./frontend
) and runsnpm install
to install the project’s dependencies defined inpackage.json
.
- This step navigates to the
-
Build Project
:- This step builds the project by running
npm run build
in thefrontend
directory. This step will prepare the frontend application for deployment by compiling the TypeScript code and optimizing it for production.
- This step builds the project by running
-
Deploy to Vercel
:- In this final step, the application is deployed to Vercel using the
npx vercel
command. TheVERCEL_TOKEN
is passed as an environment variable, which allows GitHub Actions to authenticate with Vercel and trigger the deployment. The--prod
flag ensures that the deployment is pushed to the production environment. The--yes
flag automatically confirms the deployment without requiring any further input. -
Important: The
VERCEL_TOKEN
is stored in GitHub Secrets to ensure that your deployment credentials are kept secure. You will need to generate and store this token in your repository's settings.
- In this final step, the application is deployed to Vercel using the
Obtaining Your Vercel Token
To deploy your frontend application using GitHub Actions, you'll need a personal access token from Vercel. Follow these steps to generate one:
- Sign in to your Vercel dashboard.
- Click on your profile image at the top-right corner of the screen.
- From the dropdown menu, select Account Settings.
- In the left sidebar, navigate to Tokens and click it.
- On the Tokens page:
- Enter a token name.
- Choose the scope — either assign it to a specific project (recommended for security) or your entire account.
- Set an expiry date.
- Click Create to generate the token.
Once created, copy the token immediately — you won't be able to view it again.
You’ll add this token to your GitHub repository as a secret in the next step.
Adding the Vercel Token to GitHub Secrets
Once you’ve generated your Vercel token, you’ll need to store it securely in your GitHub repository to allow the GitHub Actions workflow to access it during deployment. Here’s how to do that:
- Go to your repository on GitHub.
- Click on the Settings tab (you must have admin access to see this).
- In the left sidebar, select Secrets and variables > Actions.
- Click the New repository secret button.
- Set the Name as
VERCEL_TOKEN
— this must match the name referenced in your workflow file. - Paste your token into the Secret field.
- Click Add secret.
Once saved, GitHub Actions will be able to access this token securely during workflow execution.
Deploying and Testing the Application
With your GitHub Actions workflow in place and your Vercel token securely stored in GitHub Secrets, deployment is triggered automatically on every push to the main
branch affecting files in the frontend/
directory.
To deploy:
- Make your changes locally and push them to GitHub:
git add .
git commit -m "Trigger deployment to Vercel"
git push origin main
- Visit your repository on GitHub and click the Actions tab.
- A new workflow run will be listed under Github Actions Client Deployment To Vercel.
- Click into it to monitor each stage — from installing dependencies to building and deploying your project to Vercel.
Once the job completes successfully, your frontend app will be available live on the web via the Vercel-provided domain.
What to Expect on Vercel
After deployment, navigate to your Vercel Dashboard. Select your project from the list to access:
- Production Deployment Preview: A preview link for your live app.
- Deployment Status: Confirmation that your GitHub Actions workflow deployed the app successfully.
- Activity Logs: Timestamped logs of recent deployments and their sources (e.g., GitHub push).
- Environment Settings: A place to review or update your deployment tokens, domains, and build configuration.
This dashboard serves as your central place for monitoring the health, deployment history, and performance of your frontend application.
Conclusion
Deploying a TypeScript-based frontend application to Vercel using GitHub Actions allows for efficient, automated releases directly from your repository. By structuring the GitHub workflow correctly and managing deployment tokens securely, you eliminate the need for manual deployments and reduce the chances of human error.
This guide walked through the project structure, explained key parts of the application, and set up a CI/CD pipeline that ensures your changes are live as soon as they hit the main branch. It’s a clean, repeatable process that works well for both solo projects and team workflows.
If you found this guide helpful, consider liking the article, connecting with me on LinkedIn, or checking out some of my other projects and writings on my portfolio site.
Top comments (0)