← Back

How This Was Built

Ask Limor is an AI-powered career agent designed to answer the questions recruiters would normally ask in an initial screening conversation. This page explains the product decisions, architecture choices, and tradeoffs behind the project. I built it to showcase both my product management experience and my ability to ship AI-powered products end to end.

Product Decisions

The core decision was what this product should replace: not a chatbot demo, but a better version of the conversation a recruiter would have with me directly. That framing drove most of the scope calls below.

Conversation instead of navigation. Traditional portfolio sites require visitors to decide where to click and what to read. I wanted recruiters to be able to ask the exact question they had in mind and get a direct answer. The chat is the product, not just a feature, so the entire experience is designed around that interaction.

"How This Was Built" placed above the chat, not buried. Its placement is a product decision. Rather than treating the implementation story as secondary content, I made it visible from the start. Understanding how the product was built is as important as using it. The chat shows what the product does. This page explains how and why it was built.

No admin page. I review every conversation in Supabase's table editor. Building a second UI just for my own use would have added code and time with zero value to the person actually using the product. If I ever outgrow the dashboard, I can add one later.

No RAG, no embeddings, no vector database. My entire career history fits comfortably inside a model's context window. Adding a retrieval layer would have meant more infrastructure, more failure points, and more time spent, to solve a scale problem I don't have. This was the easiest place to over-engineer, so it's the one I was most deliberate about skipping.

No personal data collection. I wanted honest usage data, not names and emails. A visible privacy notice next to the chat explains exactly what's collected and why. Since I had no business need for personal information, collecting it would have added unnecessary privacy and compliance considerations.

Content lives in markdown files. Since this is a solo project, I prioritized the simplest possible content workflow. Editing a markdown file and redeploying is fast, reliable, and requires no additional tooling.

Every scope decision went through the same filter: would it create meaningful value for a recruiter, and was it worth the additional complexity? If not, it went to the backlog.

Architecture Decisions

Click a component to see details

Frontend

API Routes

Content and Configuration

live requestloaded once at deploy

Context engineering, not just prompt engineering. Most of the tuning work on this project wasn't about wording instructions better, it was about deciding what the model gets to see and how. Profile data sits apart from career knowledge, marked for exact reproduction so contact details never get paraphrased or guessed. Career knowledge is marked the opposite way, open for the model to connect and summarize across files. File order isn't accidental either, it's set so the model reads career history the way I'd want a person to read it. That structural thinking had a bigger impact on answer quality than any single instruction tweak.

Server-side, not client-side. Every chat message goes through a serverless API route, which builds the prompt, calls the model, and logs the exchange. This keeps the API key secure and provides a single place to control what gets sent, logged, and returned.

Knowledge base loaded once, not per request. All career content lives in markdown files and is loaded once at deploy rather than re-read on every message. There's no retrieval step or database lookup. The entire knowledge base fits within the model's context window, so treating it as static configuration instead of a live data source kept things simple and fast. Prompt caching means it is processed once and reused at low cost across conversations.

Session model kept minimal. Each visit gets a session, and a conversation is created before any messages or page visits are logged against it. Logging runs asynchronously after the response is sent, so a slow database write never delays the answer a visitor sees.

Content and configuration are separated from logic. Career knowledge, profile content, suggested questions, and agent instructions all live as files, not hardcoded in the API route. That means updating what the agent says or knows is a content edit and a redeploy, not a code change.

Together these choices reflect the same principle used throughout the project: choose the simplest architecture that meets the requirements, avoid unnecessary complexity, and keep content separate from application logic.

Technology Stack

Next.js (App Router, TypeScript). One codebase for both the frontend and the backend API routes.

Vercel for hosting. Auto-deploys on every git push, generous free tier, tight integration with Next.js (no extra setup).

Claude Sonnet 5 via the Anthropic API. I initially used Haiku because of its lower cost, but testing showed inconsistent answer quality and formatting compliance. Sonnet produced more reliable responses and followed the agent instructions more consistently. Reasoning effort is set to low to keep responses concise and fast for recruiter-style Q&A rather than deep reasoning tasks. Prompt caching keeps costs low across conversations.

Supabase (Postgres) for storage. Database with an out-of-the-box table viewer and SQL editor, on a free tier.

Markdown files for content. Career content, agent instructions, and profile information all live as files I can edit directly and redeploy. Fast, simple, and nothing to maintain for a solo project.

Tailwind CSS for styling. Fast to build with, and keeps the UI clean without custom design work.

Each technology was chosen for the same reason: simplicity, low maintenance, and speed of execution. The goal wasn't to build the most sophisticated stack, but to build something useful, maintainable, and easy to operate as a solo project.