To build an AI chat portfolio, start with a normal server-rendered site, keep your profile and projects in one data source, and add a chat that sends visitor questions to an AI model along with a system prompt built from that data on the server. Stream the replies, cap and rate-limit the endpoint, and give every project its own indexable page so search engines never depend on the chat. That is how mohitgoyal.in works.
I built it to replace a static brochure portfolio. A visitor can ask whether I have worked with their stack and get an answer in first person, instead of reading every section to find out. Here is how it is put together and what I would tell anyone building one.
Why build a portfolio with an AI chat?
Because a brochure makes the visitor do the work. They have to read every section to learn whether you fit, and the content goes stale the moment a project changes. A chat flips that: the visitor asks their question, and the answer comes from the same data as the rest of the site.
It also doubled as a testing ground. Techniques I use for clients, such as structured data, llms.txt and AI features, run here first.
38
Project pages, each indexable
13
Service pages with FAQs
2,000
Max characters per chat message
10
Free tool runs per visitor per day
What is the tech stack?
| Layer | Choice | Why |
|---|---|---|
| Framework | TanStack Start and React, in TypeScript | Server rendering with type-safe routing, so pages are indexable and data loading is explicit |
| Styling | Tailwind CSS | One set of tokens across pages, tools and chat replies |
| Content store | Firebase Firestore | Profile and projects edited from an admin, with no custom backend to host |
| Long-form content | Markdown files in the repo | Case studies and posts reviewed and versioned like code |
| Auth | Firebase Auth | Protects the admin dashboard |
| AI | Anthropic Claude API | Chat replies and the free tools |
| Delivery | Cloudflare, plus an assets subdomain for images | Quick first byte wherever the visitor is |
How does one source of truth work?
Every surface reads from the same profile. When I edit a project in the admin, the change reaches the project page, its metadata, the sitemap, llms.txt and the chat's knowledge at once. Nothing has to be updated in three places.
How is the chat built?
The browser posts the conversation to a server route. The route builds a system prompt from the server-side profile, sends it to Claude with the messages, and streams the reply back as Server-Sent Events, one text chunk at a time. Streaming matters: the visitor starts reading within a moment instead of waiting for the whole answer.
Replies are not plain text. The chat can answer with the site's own rich blocks: stat tiles, charts, step lists, timelines, FAQs, project cards and Mermaid diagrams. Asking "what have you built with WooCommerce?" can return project cards rather than a paragraph.
Three rules keep the answers honest:
- The system prompt comes from my data only. It is a pure function of the profile document, never built from what the visitor types.
- Real numbers are supplied. The prompt includes project counts by category and technology, labelled as the only project numbers the model may chart. It never has to estimate.
- It stays on topic. Questions unrelated to my work, skills or experience are politely declined rather than answered with a guess.
How do you stop the chat being abused?
An open AI endpoint is a free proxy for anyone who finds it. The chat route has four guards:
- 1
Origin and token check
Only requests from the site's own pages, carrying the site's client token, are accepted. Everything else gets a 403.
- 2
Rate limit per visitor
Each IP address can send a limited number of messages in a ten-minute window, then gets a polite 429 with a retry time.
- 3
Length caps
Messages are capped at 2,000 characters, conversations at 16 messages and replies at a fixed output budget.
- 4
Validated input
The request body is checked against a schema, and the last message must come from the visitor.
The free tools follow the same pattern, with ten runs per tool per visitor per day.
How do you keep an AI portfolio indexable?
By treating the chat as an extra, not the site. Every project has a standalone page at /projects/<slug>, and case studies, posts and services have their own pages too, all server rendered. Each page carries its own JSON-LD, such as Person, CreativeWork, BreadcrumbList and ItemList. The site publishes a sitemap and an llms.txt file, and robots.txt allows the AI crawlers.
When I moved off my old WordPress portfolio, every legacy URL from Search Console got a 301 redirect, so old links and rankings landed on the right new page. For the AI search side of this, see how to get cited in AI Overviews.
What matters behind the scenes?
The editorial tooling, as much as the public pages. The admin has version history so I can roll back a bad edit, draft flags for projects, link health checks that flag dead client URLs, an SEO preview for each page and chat analytics that show what visitors actually ask. Those are what keep the content honest over time, and the analytics show which questions the pages themselves should answer better.
Should your site have an AI chat?
If visitors arrive with specific questions, such as "do you do X?", "have you worked with Y?" or "how much does Z involve?", a chat grounded in your own content answers them faster than navigation. If your site is a short brochure, a clear page will do more.
I build sites like this through my web and mobile apps and Next.js and React websites services. To see the framework decision behind it, read Next.js vs TanStack Start, or ask the chat on the home page how it works.



