Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions __tests__/ai/tool-responses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
});
});
Expand Down
1 change: 1 addition & 0 deletions data/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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?"
Expand Down
51 changes: 21 additions & 30 deletions data/cv-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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": [
Expand All @@ -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": [
Expand Down
13 changes: 7 additions & 6 deletions e2e/cv-bot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});

Expand Down Expand Up @@ -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();
});
});
Expand Down
Loading