diff --git a/__tests__/ai/tool-responses.test.ts b/__tests__/ai/tool-responses.test.ts index 2868fd2..f1506c0 100644 --- a/__tests__/ai/tool-responses.test.ts +++ b/__tests__/ai/tool-responses.test.ts @@ -143,9 +143,11 @@ describe("Project questions", () => { }); it("filters projects by technology", async () => { - const result = await exec("get_projects", { technology: "wagmi" }) as Array<{ technologies: string[] }>; + const tech = "Anthropic API"; + const result = await exec("get_projects", { technology: tech }) as Array<{ technologies: string[] }>; + expect(result.length).toBeGreaterThan(0); for (const project of result) { - expect(project.technologies.map((t) => t.toLowerCase())).toContain("wagmi"); + expect(project.technologies.map((t) => t.toLowerCase())).toContain(tech.toLowerCase()); } }); }); diff --git a/data/config.json b/data/config.json index 5ae7c42..a48602f 100644 --- a/data/config.json +++ b/data/config.json @@ -14,6 +14,7 @@ "Can Fran own backend work too, or is he frontend-only?", "What's Fran's leadership experience?", "What AI features has Fran shipped to production?", + "What open source projects has Fran built?", "Tell me about Fran's Web3 background", "Is Fran available, and what's he looking for?", "What does Fran's ideal next role look like?" diff --git a/data/cv-data.json b/data/cv-data.json index a0d800e..61166d2 100644 --- a/data/cv-data.json +++ b/data/cv-data.json @@ -3,7 +3,7 @@ "name": "Fran Rom", "title": "Senior / Lead Frontend Engineer | Web3 & AI", "location": "Madrid, Spain (UTC+1)", - "summary": "Senior Frontend Engineer with 8+ years of experience building production Web3 products, leading engineering teams, and integrating AI into real applications. Comfortable owning the full stack when needed: from onchain dapp architecture to backend services and deployments. Experienced shipping AI-powered features including LLM interfaces, autonomous agents, and agentic workflows in production. Web3 is my background, but the problems I want to solve are not limited to it.", + "summary": "Senior Frontend Engineer with 8+ years of experience, nearly 6 in Web3. Led the frontend team at GAME7, shipping a multi-tenant SaaS platform and production AI features: autonomous agents, LLM interfaces, and agentic workflows. I build across EVM and Solana, take full-stack ownership when needed, and ship real AI tooling beyond the prototype stage. My background is Web3, but the problems I want to solve are not limited to it.", "avatar": "/avatar.jpg", "links": { "github": "https://github.com/FranRom", @@ -160,6 +160,7 @@ { "name": "Express", "level": "intermediate" }, { "name": "REST APIs", "level": "advanced" }, { "name": "Apollo Client", "level": "advanced" }, + { "name": "WebSockets", "level": "advanced" }, { "name": "Docker", "level": "intermediate" } ], "tools": [ @@ -180,43 +181,33 @@ }, "projects": [ { - "name": "CV Bot", - "description": "AI chatbot that showcases developer experience via LLM tool-calling. Open source and forkable.", + "name": "Pupila", + "description": "Local-first job aggregator with AI-powered per-job review, swipe-to-apply triage, and an MCP server for AI clients.", "role": "Creator", "highlights": [ - "Built with React + TypeScript + Vercel AI SDK", - "Configurable LLM provider and tone", - "Tool-calling architecture for structured data retrieval" + "Local-first architecture — aggregated jobs and data stay on the user's machine", + "AI-powered per-job review using Claude to assess fit against the user's profile", + "Swipe-to-apply triage UI for fast decisions across aggregated listings", + "Built-in MCP server exposes jobs and reviews to any MCP-compatible AI client", + "Built end to end with Claude Code" ], - "technologies": ["React", "TypeScript", "Vercel AI SDK", "Tailwind CSS"], + "technologies": ["Next.js", "TypeScript", "Anthropic API", "Claude Code", "MCP"], "url": "", - "repo": "https://github.com/FranRom/cv-bot" - }, - { - "name": "Ballena.io DeFi Platform", - "description": "Two Yield DeFi projects built for a DAO, based on Beefy and Pancakeswap standards. Successfully deployed to mainnet.", - "role": "Frontend Lead", - "highlights": [ - "Led frontend development for two DeFi yield projects", - "Used coding standards from Pancakeswap and Beefy", - "Successfully deployed to mainnet" - ], - "technologies": ["React", "TypeScript", "Web3", "DeFi", "Solidity"], - "url": "https://ballena.io", - "repo": "" + "repo": "https://github.com/FranRom/pupila" }, { - "name": "Game7 Questing Platform", - "description": "Multitenant questing platform with NFTs and progression system, evolved from PaaS to SaaS.", - "role": "Frontend Lead", + "name": "CV Bot", + "description": "AI-powered chatbot that presents a CV through natural conversation. Deployed and live. Open source and forkable.", + "role": "Creator", "highlights": [ - "Built auth layer, billing integration, and tenant isolation", - "Led team of 3 frontend engineers", - "Integrated AI-powered features including natural language interfaces and agents" + "Tool-calling architecture: the LLM queries structured CV data via Zod-typed tools", + "Composable markdown prompts with prompt caching for cost efficiency", + "Configurable LLM provider, tone, and welcome flow via JSON config", + "Deployed live and forkable — anyone can adapt it to their own CV" ], - "technologies": ["Next.js", "TypeScript", "wagmi", "viem", "AI Agents"], - "url": "", - "repo": "" + "technologies": ["React", "TypeScript", "Vite", "Anthropic API", "Vercel AI SDK", "Tailwind CSS"], + "url": "https://cv-bot-five.vercel.app", + "repo": "https://github.com/FranRom/cv-bot" } ], "education": [ diff --git a/e2e/cv-bot.spec.ts b/e2e/cv-bot.spec.ts index c7fd06c..168e37d 100644 --- a/e2e/cv-bot.spec.ts +++ b/e2e/cv-bot.spec.ts @@ -13,9 +13,9 @@ test.describe("Welcome screen", () => { page.getByText("I'm Fran's AI assistant") ).toBeVisible(); - // All 7 suggested question buttons + // All 8 suggested question buttons const buttons = page.getByRole("button").filter({ hasText: /\?|Tell me|Show me|How was/ }); - await expect(buttons).toHaveCount(7); + await expect(buttons).toHaveCount(8); }); }); @@ -47,21 +47,22 @@ test.describe("Send a message", () => { test.describe("Suggested question", () => { test("clicking a suggested question sends it and shows response", async ({ page }) => { + const question = "What AI features has Fran shipped to production?"; await mockChatAPI(page, { - text: "Fran's tech stack includes React, TypeScript, and Vite.", + text: "Fran has shipped AI agents, LLM interfaces, and agentic workflows at GAME7.", }); await page.goto("/"); // Click a suggested question - await page.getByRole("button", { name: "What's Fran's tech stack?" }).click(); + await page.getByRole("button", { name: question }).click(); // User message appears with the question text - await expect(page.getByText("What's Fran's tech stack?")).toHaveCount(2); // button + user bubble + await expect(page.getByText(question)).toHaveCount(2); // button + user bubble // Assistant response appears await expect( - page.getByText("Fran's tech stack includes React") + page.getByText("Fran has shipped AI agents") ).toBeVisible(); }); });