diff --git a/kits/interview-coach/.gitignore b/kits/interview-coach/.gitignore new file mode 100644 index 00000000..123a6220 --- /dev/null +++ b/kits/interview-coach/.gitignore @@ -0,0 +1,31 @@ +# dependencies +node_modules +.pnp +.pnp.js + +# testing +coverage + +# next.js +.next/ +out/ + +# production +build + +# env files β€” NEVER commit secrets! +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# misc +.DS_Store +*.pem +.vercel diff --git a/kits/interview-coach/README.md b/kits/interview-coach/README.md new file mode 100644 index 00000000..2a41f557 --- /dev/null +++ b/kits/interview-coach/README.md @@ -0,0 +1,171 @@ +# 🎯 AI Interview Coach β€” Lamatic AgentKit + +> Get a **fully personalized interview prep kit** in seconds. Paste your target role, +> company, and background β€” and get tailored technical questions, behavioral Q&A, +> company insights, and a 30-60-90 day plan. + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/Lamatic/AgentKit/tree/main/kits/interview-coach) + +--- + +## 🧩 What Problem Does This Solve? + +As a student and developer who went through campus placements and interviews myself, +I noticed a gap: generic interview prep tools give the same questions to everyone. +They don't care whether you're applying as a fresher to a startup or a mid-level +engineer at Google. + +**AI Interview Coach** solves this by: +- Tailoring questions to your **specific role + company + background** +- Giving STAR-method answer frameworks based on your actual experience +- Sharing company-specific culture and tech stack insights +- Providing a realistic 30-60-90 day onboarding plan if you get hired + +--- + +## ✨ Features + +| Feature | Description | +|---|---| +| πŸ’» Technical Questions | 8-10 role-specific questions based on your target company | +| 🧠 Behavioral Questions | 5-6 behavioral Qs + what the interviewer is actually testing | +| πŸ’‘ Answer Tips | STAR-method frameworks tailored to your background | +| 🏒 Company Insights | Culture, values, tech stack, and what they look for | +| πŸ—“οΈ 30-60-90 Day Plan | Personalized onboarding roadmap if you land the job | + +--- + +## πŸ› οΈ Tech Stack + +- **Frontend:** Next.js 14, React, Tailwind CSS, TypeScript +- **AI Orchestration:** Lamatic Studio (LLM Flow) +- **Deployment:** Vercel + +--- + +## βš™οΈ Setup Instructions + +### Prerequisites +- Node.js 18+ +- npm 9+ +- [Lamatic.ai](https://lamatic.ai) account (free) +- [Vercel](https://vercel.com) account (for deployment) + +### Step 1 β€” Set Up the Lamatic Flow + +1. Go to [studio.lamatic.ai](https://studio.lamatic.ai) and sign in +2. Create a new Project β†’ Create a new Flow +3. Add an **API Trigger** node with these inputs: + - `jobRole` (string) + - `company` (string) + - `background` (string) + - `experienceLevel` (string) +4. Add an **LLM Node** β€” copy system and user prompts from `prompts/interview-coach-flow_system.md` and `prompts/interview-coach-flow_user.md` +5. Add an **API Response** node connected to the LLM output +6. Click **Deploy** and wait for green status +7. Copy the **Flow ID** from the three-dot menu + +### Step 2 β€” Get Your API Keys + +Navigate to **Settings** in Lamatic Studio: + +| Variable | Where to find it | +|---|---| +| `LAMATIC_PROJECT_API_KEY` | Settings β†’ API Keys β†’ Copy | +| `LAMATIC_PROJECT_ID` | Settings β†’ Project β†’ Project ID | +| `LAMATIC_PROJECT_ENDPOINT` | Settings β†’ API Docs β†’ App Frameworks β†’ Endpoint | +| `LAMATIC_FLOW_ID` | Flow Editor β†’ three-dot menu β†’ Copy Flow ID | + +### Step 3 β€” Run Locally + +```bash +# Clone the AgentKit repo +git clone https://github.com/YOUR-USERNAME/AgentKit.git +cd AgentKit/kits/interview-coach/apps + +# Install dependencies +npm install + +# Set up environment variables +cp .env.example .env +# Edit .env and fill in your keys + +# Run the development server +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) to see the app. + +### Step 4 β€” Deploy to Vercel + +1. Push your branch to GitHub +2. Go to [vercel.com](https://vercel.com) β†’ Import project +3. Set **Root Directory** to `kits/interview-coach/apps` +4. Add all environment variables from your `.env` file +5. Click **Deploy** + +--- + +## πŸ§ͺ Example Usage + +**Input:** +- Role: `Frontend Developer` +- Company: `Lamatic.ai` +- Level: `Fresher` +- Background: `B.Tech IT, 1 year React + Node.js, built MediQueue (healthcare app), GSSoC Top 50 Rank 32, Oracle AI certified` + +**Output includes:** +- Technical questions on React, TypeScript, REST APIs, system design basics +- Behavioral questions around teamwork, open source contributions +- Tips: How to frame GSSoC experience using STAR method +- Company insight: Lamatic values AI-native thinking and open source culture +- 90-day plan: week 1 codebase exploration β†’ week 4 first PR β†’ day 60 owning a feature + +--- + +## πŸ“ Folder Structure + +``` +interview-coach/ +β”œβ”€β”€ constitutions/ +β”‚ └── default.md # Guardrails / safety rules for the flow +β”œβ”€β”€ flows/ +β”‚ └── interview-coach-flow.ts # Lamatic flow layout definition +β”œβ”€β”€ model-configs/ +β”‚ └── interview-coach-flow_llm.ts # Model settings +β”œβ”€β”€ prompts/ +β”‚ β”œβ”€β”€ interview-coach-flow_system.md # LLM system prompt +β”‚ └── interview-coach-flow_user.md # LLM user prompt +β”œβ”€β”€ scripts/ +β”‚ └── interview-coach-flow_parse-json.ts # Parser script for LLM output +β”œβ”€β”€ lamatic.config.ts # Project metadata +β”œβ”€β”€ README.md +└── apps/ # Next.js UI Application + β”œβ”€β”€ actions/ + β”‚ └── orchestrate.ts # Server action β€” calls Lamatic flow + β”œβ”€β”€ app/ + β”‚ β”œβ”€β”€ layout.tsx + β”‚ β”œβ”€β”€ page.tsx + β”‚ └── globals.css + β”œβ”€β”€ components/ + β”‚ └── InterviewCoach.tsx # UI component + β”œβ”€β”€ lib/ + β”‚ └── lamatic-client.ts # Lamatic client configuration + β”œβ”€β”€ package.json + └── tsconfig.json +``` + +--- + +## 🀝 Author + +Built by **Piyush Kumar Singh** for the Lamatic AgentKit Challenge. + +- GitHub: [@piyushkumar0707](https://github.com/piyushkumar0707) +- Portfolio: [piyush-singh.dev](https://piyush-singh.dev) + +--- + +## πŸ“„ License + +MIT β€” feel free to use and extend. diff --git a/kits/interview-coach/agent.md b/kits/interview-coach/agent.md new file mode 100644 index 00000000..d90a73da --- /dev/null +++ b/kits/interview-coach/agent.md @@ -0,0 +1,87 @@ +# AI Interview Prep Coach + +## Overview +This project solves the problem of helping candidates prepare for interviews by generating personalized interview preparation kits based on the target role, company, background, and experience level. It uses Lamatic.ai's LLM orchestration flow to produce tailored technical and behavioral questions, answer tips, company insights, and a structured 30-60-90 day onboarding plan. The frontend application is built in Next.js and communicates with the Lamatic API. + +--- + +## Purpose +The goal of this agent system is to provide targeted, contextual interview coaching. Instead of generic question lists, this coach analyzes the candidate's exact background (skills, past experience, projects) alongside details of the target company and role to provide highly relevant prep materials. It helps candidates structure their answers using frameworks like the STAR method and provides clear guidelines for their first 90 days if hired. + +--- + +## Flows + +### `Interview Coach Flow` + +- **Flow ID / Env key mapping:** `interview-coach-flow` (configured via `LAMATIC_FLOW_ID`) + +#### Trigger +- **Invocation type:** API request via a GraphQL trigger node (`API Request`). +- **Expected input shape:** + - `jobRole` (string): The target job title/role. + - `company` (string): The target company name. + - `background` (string): The candidate's skills, experience, and projects. + - `experienceLevel` (string): fresh / junior / mid / senior. + +#### What it does +1. `API Request` (triggerNode): Receives the inputs from the Next.js app. +2. `LLM Node` (LLMNode_1): Calls the text LLM to generate the prep kit based on the system and user prompts. +3. `Parse JSON` (codeNode_parse_json): Parses the LLM's raw text response into a structured JSON object, stripping markdown code fences if present. +4. `API Response` (graphqlResponseNode_1): Returns the parsed JSON payload to the caller in realtime. + +#### When to use this flow +- Use when a candidate inputs their career profile and needs a structured, company-specific preparation kit. +- Use when you need structured, multi-part preparation advice (questions + answer tips + insights + onboarding roadmap). + +#### Output +A JSON object with the following fields: +- `quickSummary` (string): Candidates fit overview. +- `technicalQuestions` (array of strings): 8-10 role-specific technical questions. +- `behavioralQuestions` (array of strings): 5-6 behavioral questions. +- `answerTips` (array of strings): 4-5 STAR-method and role-specific tips. +- `companyInsights` (array of strings): 5-6 insights about company culture, values, or tech stack. +- `ninetyDayPlan` (object): Onboarding roadmap containing: + - `first30` (array of strings) + - `next30` (array of strings) + - `final30` (array of strings) + +#### Dependencies +- Lamatic Project credentials (endpoint, projectId, apiKey). +- Deployed flow ID for the interview prep flow. + +--- + +## Guardrails +- **Safety Guidelines**: Must not generate harmful, discriminatory, or inappropriate coaching content. +- **Input validation**: Inputs should be validated on the client side before triggering the flow. +- **Output constraints**: The flow must return valid JSON structure matching the schema. + +--- + +## Integration Reference + +| Integration Type | Purpose | Config Key / Env Var | +|---|---|---| +| Lamatic Flow Execution | Trigger the interview prep generation flow | `LAMATIC_FLOW_ID` | +| Lamatic SDK Client | Initialize communication with Lamatic API | `LAMATIC_PROJECT_ENDPOINT`, `LAMATIC_PROJECT_ID`, `LAMATIC_PROJECT_API_KEY` | + +--- + +## Environment Setup +Make sure the following variables are configured in `apps/.env`: +- `LAMATIC_FLOW_ID` +- `LAMATIC_PROJECT_ENDPOINT` +- `LAMATIC_PROJECT_ID` +- `LAMATIC_PROJECT_API_KEY` + +--- + +## Quickstart +1. Set up the flow in Lamatic Studio and deploy. +2. Configure the env variables in `apps/.env`. +3. In `apps/`, run: + ```bash + npm install + npm run dev + ``` diff --git a/kits/interview-coach/apps/.env.example b/kits/interview-coach/apps/.env.example new file mode 100644 index 00000000..849760b0 --- /dev/null +++ b/kits/interview-coach/apps/.env.example @@ -0,0 +1,19 @@ +# ───────────────────────────────────────────── +# Lamatic Flow Configuration +# ───────────────────────────────────────────── + +# Your Lamatic project endpoint (GraphQL API URL) +# Find it: Lamatic Studio β†’ Settings β†’ API Docs β†’ App Frameworks β†’ Endpoint +LAMATIC_PROJECT_ENDPOINT="YOUR_PROJECT_ENDPOINT" + +# Your Lamatic Flow ID +# Find it: Flow Editor β†’ three-dot menu β†’ Copy Flow ID +LAMATIC_FLOW_ID="YOUR_FLOW_ID" + +# Your Lamatic Project ID +# Find it: Lamatic Studio β†’ Settings β†’ Project β†’ Project ID +LAMATIC_PROJECT_ID="YOUR_PROJECT_ID" + +# Your Lamatic API Key +# Find it: Lamatic Studio β†’ Settings β†’ API Keys β†’ Copy +LAMATIC_PROJECT_API_KEY="YOUR_API_KEY" \ No newline at end of file diff --git a/kits/interview-coach/apps/actions/orchestrate.ts b/kits/interview-coach/apps/actions/orchestrate.ts new file mode 100644 index 00000000..ca60aeed --- /dev/null +++ b/kits/interview-coach/apps/actions/orchestrate.ts @@ -0,0 +1,73 @@ +'use server' + +import { lamaticClient } from '@/lib/lamatic-client' + +export interface InterviewCoachInput { + jobRole: string + company: string + background: string + experienceLevel: string +} + +export interface InterviewCoachResult { + technicalQuestions: string[] + behavioralQuestions: string[] + answerTips: string[] + companyInsights: string[] + ninetyDayPlan: { + first30: string[] + next30: string[] + final30: string[] + } + quickSummary: string +} + +export interface ActionResult { + success: boolean + data?: InterviewCoachResult + error?: string +} + +export async function runInterviewCoach( + input: InterviewCoachInput +): Promise { + let raw: Record + + try { + raw = await lamaticClient.executeFlow( + process.env.LAMATIC_FLOW_ID!, + { + jobRole: input.jobRole, + company: input.company, + background: input.background, + experienceLevel: input.experienceLevel, + } + ) as Record + } catch (e) { + return { success: false, error: `Lamatic flow error: ${e}` } + } + + const resultData = + (raw?.result as Record)?.output ?? + raw?.result ?? + raw?.output ?? + raw + + const safe = (resultData ?? {}) as Partial + + return { + success: true, + data: { + quickSummary: safe.quickSummary ?? '', + technicalQuestions: safe.technicalQuestions ?? [], + behavioralQuestions: safe.behavioralQuestions ?? [], + answerTips: safe.answerTips ?? [], + companyInsights: safe.companyInsights ?? [], + ninetyDayPlan: { + first30: safe.ninetyDayPlan?.first30 ?? [], + next30: safe.ninetyDayPlan?.next30 ?? [], + final30: safe.ninetyDayPlan?.final30 ?? [], + } + } + } +} \ No newline at end of file diff --git a/kits/interview-coach/apps/app/globals.css b/kits/interview-coach/apps/app/globals.css new file mode 100644 index 00000000..52adedc5 --- /dev/null +++ b/kits/interview-coach/apps/app/globals.css @@ -0,0 +1,31 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground-rgb: 15, 23, 42; + --background-start-rgb: 248, 250, 252; + --background-end-rgb: 241, 245, 249; +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + rgb(var(--background-start-rgb)), + rgb(var(--background-end-rgb)) + ) + fixed; + min-height: 100vh; +} + +@layer utilities { + .text-balance { text-wrap: balance; } +} + +/* Smooth fade-in for result sections */ +@keyframes fadeIn { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} +.animate-fade-in { animation: fadeIn 0.4s ease forwards; } diff --git a/kits/interview-coach/apps/app/layout.tsx b/kits/interview-coach/apps/app/layout.tsx new file mode 100644 index 00000000..b3e419a7 --- /dev/null +++ b/kits/interview-coach/apps/app/layout.tsx @@ -0,0 +1,23 @@ +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import './globals.css' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata: Metadata = { + title: 'AI Interview Coach β€” Lamatic AgentKit', + description: + 'Get tailored interview questions, answer frameworks, and a 90-day plan powered by Lamatic AI flows.', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/kits/interview-coach/apps/app/page.tsx b/kits/interview-coach/apps/app/page.tsx new file mode 100644 index 00000000..769b9c5b --- /dev/null +++ b/kits/interview-coach/apps/app/page.tsx @@ -0,0 +1,9 @@ +import InterviewCoach from '@/components/InterviewCoach' + +export default function Home() { + return ( +
+ +
+ ) +} diff --git a/kits/interview-coach/apps/components/InterviewCoach.tsx b/kits/interview-coach/apps/components/InterviewCoach.tsx new file mode 100644 index 00000000..4df6eb64 --- /dev/null +++ b/kits/interview-coach/apps/components/InterviewCoach.tsx @@ -0,0 +1,323 @@ +'use client' + +import { useState } from 'react' +import { runInterviewCoach, type InterviewCoachResult } from '@/actions/orchestrate' + +type Tab = 'technical' | 'behavioral' | 'company' | 'plan' + +const TABS: { id: Tab; label: string; emoji: string }[] = [ + { id: 'technical', label: 'Technical Questions', emoji: 'πŸ’»' }, + { id: 'behavioral', label: 'Behavioral Questions', emoji: '🧠' }, + { id: 'company', label: 'Company Insights', emoji: '🏒' }, + { id: 'plan', label: '30-60-90 Day Plan', emoji: 'πŸ—“οΈ' }, +] + +const EXP_LEVELS = [ + { value: 'fresher', label: 'Fresher / Intern' }, + { value: 'junior', label: 'Junior (0–2 yrs)' }, + { value: 'mid', label: 'Mid-level (2–5 yrs)' }, + { value: 'senior', label: 'Senior (5+ yrs)' }, +] + +function BulletList({ items }: { items: string[] }) { + if (!items || items.length === 0) + return

No data available.

+ + return ( +
    + {items.map((item, i) => ( +
  • + + {i + 1} + + {item} +
  • + ))} +
+ ) +} + +function PlanSection({ title, emoji, items }: { title: string; emoji: string; items: string[] }) { + return ( +
+

+ {emoji} {title} +

+ +
+ ) +} + +export default function InterviewCoach() { + const [jobRole, setJobRole] = useState('') + const [company, setCompany] = useState('') + const [background, setBackground] = useState('') + const [experienceLevel, setExperienceLevel] = useState('fresher') + const [loading, setLoading] = useState(false) + const [error, setError] = useState('') + const [result, setResult] = useState(null) + const [activeTab, setActiveTab] = useState('technical') + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + if (!jobRole.trim() || !company.trim() || !background.trim()) { + setError('Please fill in all fields.') + return + } + setError('') + setLoading(true) + setResult(null) + + const res = await runInterviewCoach({ jobRole, company, background, experienceLevel }) + + setLoading(false) + if (!res.success || !res.data) { + setError(res.error ?? 'Something went wrong. Please try again.') + return + } + setResult(res.data) + setActiveTab('technical') + } + + return ( +
+ + {/* ── Header ── */} +
+
+ πŸ€– Powered by Lamatic AgentKit +
+

+ AI Interview Coach +

+

+ Tell us the role, company, and your background β€” and get a fully personalized + interview prep kit in seconds. +

+
+ + {/* ── Form ── */} +
+
+ {/* Job Role */} +
+ + setJobRole(e.target.value)} + placeholder="e.g. Frontend Developer" + className="w-full px-3 py-2.5 rounded-lg border border-slate-300 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-transparent" + /> +
+ + {/* Company */} +
+ + setCompany(e.target.value)} + placeholder="e.g. Google, Lamatic.ai" + className="w-full px-3 py-2.5 rounded-lg border border-slate-300 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-transparent" + /> +
+
+ + {/* Experience Level */} +
+ +
+ {EXP_LEVELS.map(lvl => ( + + ))} +
+
+ + {/* Background */} +
+ +