π Table of Contents
- π€ Introduction
- βοΈ Tech Stack
- π Features
- π€Έ Quick Start
- πΈοΈ Snippets (Code to Copy)
- π Assets
- π More
Built with Next.js for the user interface and backend logic, Firebase for authentication and data storage, styled with TailwindCSS and using Vapi's voice agents, PrepSmart is a website project designed to help you learn integrating AI models with your apps. The platform offers a sleek and modern experience for job interview preparation.
- Next.js
- Firebase
- Tailwind CSS
- Vapi AI
- shadcn/ui
- Google Gemeni
- Zod
app-ai-interviews/ βββ app/ # Next.js app directory β βββ (auth)/ # Authentication routes β βββ (dashboard)/ # After Authentication β βββ (root)/ # Main application routes β βββ api/ # API routes β βββ layout.tsx # Root layout βββ components/ # React components β βββ auth/ # Authentication components β βββ ui/ # UI components β βββ ... # Other components βββ constants/ # Application constants βββ firebase/ # Firebase configuration βββ lib/ # Utility functions and server actions β βββ actions/ # Server actions β βββ utils.ts # Helper functions βββ public/ # Static assets βββ types/ # TypeScript type definitions
π Authentication: Sign Up and Sign In using Google or password/email authentication handled by Firebase.
π Create Interviews: Easily generate job interviews with help of Vapi voice assistants and Google Gemini.
π Get feedback from AI: Take the interview with AI voice agent, and receive instant feedback based on your conversation.
π Modern UI/UX: A sleek and user-friendly interface designed for a great experience.
π Interview Page: Conduct AI-driven interviews with real-time feedback and detailed transcripts.
π Dashboard: Manage and track all your interviews with easy navigation.
π Responsiveness: Fully responsive design that works seamlessly across devices.
and many more, including code architecture and reusability
Follow these steps to set up the project locally on your machine.
Prerequisites
Make sure you have the following installed on your machine:
Cloning the Repository
git clone
cd prepmasterInstallation
Install the project dependencies using npm:
npm installSet Up Environment Variables
Create a new file named .env.local in the root of your project and add the following content:
NEXT_PUBLIC_VAPI_WEB_TOKEN=
NEXT_PUBLIC_VAPI_WORKFLOW_ID=
GOOGLE_GENERATIVE_AI_API_KEY=
NEXT_PUBLIC_BASE_URL=
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
FIREBASE_PROJECT_ID=
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY=Replace the placeholder values with your actual Firebase, [Vapi](https://vapi.ai/ credentials.
Running the Project
npm run devOpen http://localhost:3000 in your browser to view the project.
Generate feedback prompt (lib/actions/general.action.ts):
prompt: `
You are an AI interviewer analyzing a mock interview. Your task is to evaluate the candidate based on structured categories. Be thorough and detailed in your analysis. Don't be lenient with the candidate. If there are mistakes or areas for improvement, point them out.
Transcript:
${formattedTranscript}
Please score the candidate from 0 to 100 in the following areas. Do not add categories other than the ones provided:
- **Communication Skills**: Clarity, articulation, structured responses.
- **Technical Knowledge**: Understanding of key concepts for the role.
- **Problem-Solving**: Ability to analyze problems and propose solutions.
- **Cultural & Role Fit**: Alignment with company values and job role.
- **Confidence & Clarity**: Confidence in responses, engagement, and clarity.
`,
system:
"You are a professional interviewer analyzing a mock interview. Your task is to evaluate the candidate based on structured categories",Display feedback (app/(root)/interview/[id]/feedback/page.tsx):
<section className="section-feedback">
<div className="flex flex-row justify-center">
<h1 className="text-4xl font-semibold">
Feedback on the Interview -{" "}
<span className="capitalize">{interview.role}</span> Interview
</h1>
</div>
<div className="flex flex-row justify-center">
<div className="flex flex-row gap-5">
<div className="flex flex-row gap-2 items-center">
<Image src="/star.svg" width={22} height={22} alt="star" />
<p>
Overall Impression:{" "}
<span className="text-primary-200 font-bold">
{feedback?.totalScore}
</span>
/100
</p>
</div>
<div className="flex flex-row gap-2">
<Image src="/calendar.svg" width={22} height={22} alt="calendar" />
<p>
{feedback?.createdAt
? dayjs(feedback.createdAt).format("MMM D, YYYY h:mm A")
: "N/A"}
</p>
</div>
</div>
</div>
<hr />
<p>{feedback?.finalAssessment}</p>
<div className="flex flex-col gap-4">
<h2>Breakdown of the Interview:</h2>
{feedback?.categoryScores?.map((category, index) => (
<div key={index}>
<p className="font-bold">
{index + 1}. {category.name} ({category.score}/100)
</p>
<p>{category.comment}</p>
</div>
))}
</div>
<div className="flex flex-col gap-3">
<h3>Strengths</h3>
<ul>
{feedback?.strengths?.map((strength, index) => (
<li key={index}>{strength}</li>
))}
</ul>
</div>
<div className="flex flex-col gap-3">
<h3>Areas for Improvement</h3>
<ul>
{feedback?.areasForImprovement?.map((area, index) => (
<li key={index}>{area}</li>
))}
</ul>
</div>
<div className="buttons">
<Button className="btn-secondary flex-1">
<Link href="/" className="flex w-full justify-center">
<p className="text-sm font-semibold text-primary-200 text-center">
Back to dashboard
</p>
</Link>
</Button>
<Button className="btn-primary flex-1">
<Link href={`/interview/${id}`} className="flex w-full justify-center">
<p className="text-sm font-semibold text-black text-center">
Retake Interview
</p>
</Link>
</Button>
</div>
</section>