POST /api/chat includes a system prompt built from the live portfolio data. That prompt is generated by generatePortfolioContext() in data/portfolio-context.ts.
How It Works
generatePortfolioContext() is a plain TypeScript function that:
- Imports the four portfolio data arrays (
skills,experiences,educations,projects,socialLinks). - Formats each array into a human-readable text block.
- Returns a single string that is passed directly to
streamTextas thesystemparameter.
Function Signature
getPortfolioContext() helper, which caches the result for 5 minutes.
Data Sources
The function pulls from five data files underdata/:
| Import | File | What it contributes to the prompt |
|---|---|---|
skills | data/skills.ts | Skill categories and the technologies in each (skill.title, skill.techs) |
experiences | data/experience.ts | Work experience entries (title, sub_title, years, details) |
educations | data/experience.ts | Education entries (same shape as experience) |
projects | data/projects.ts | Project name, description, tech tags, and demo URL |
socialLinks | data/socials.ts | Social/contact links (label, href) |
How Each Source Is Formatted
System Prompt Structure
The returned string is divided into four sections:- Persona — The assistant is introduced as Roger’s personal assistant. The tone is described: professional, natural, with occasional emojis.
- About Roger — Static biographical information (name, location, stack, values, personal interests) that is hardcoded directly in the template literal.
- Dynamic data — The five formatted text blocks from the data files are interpolated here: skills, experience, education, projects, and social links.
- Assistant role instructions — Rules for how to respond: response length (150–200 words), emoji usage (max 3), formatting, handling unknown information, and what not to invent.
Keeping the Context Up to Date
BecausegeneratePortfolioContext() reads directly from the same data files that drive the rest of the portfolio, updating the AI’s knowledge is the same as updating the portfolio itself:
- New project → add an entry to
data/projects.ts. The AI will mention it on the next context refresh (within 5 minutes). - New job → add an entry to the
experiencesarray indata/experience.ts. - New skill → add an entry to
data/skills.ts. - New social link → add an entry to
data/socials.ts.
During development you can set
CONTEXT_CACHE_DURATION to 0 in app/api/chat/route.ts so context changes take effect immediately without waiting for the cache to expire.Customisation Guide
Updating the AI’s Personality and Tone
The personality is defined in two places inside the template literal inportfolio-context.ts:
Opening description (controls the overall persona):
Adding Static Information That Doesn’t Fit in Data Files
For facts that aren’t naturally structured as a list — a personal statement, an explanation of a career change, a preferred contact method — add them directly to the template literal in the SOBRE ROGER section:Adding Custom Q&A Pairs
You can guide the AI to answer specific questions in a specific way by appending an FAQ block to the system prompt:Best Practices for Writing Effective Context
- Be concrete. The model responds better to specific facts (“5 years of React experience”) than vague claims (“extensive experience”).
- Use consistent formatting. The current prompt uses
- label: valuelists. Stick to this pattern so the model can reliably parse the data. - Set clear limits. The “Límites” section explicitly tells the model not to invent projects or share unlisted personal information. Always include a similar guardrail section.
- Keep it focused. Every sentence in the system prompt consumes tokens on every request. Remove sections that are not useful.
- Test iteratively. After any change, ask the chatbot questions that probe the updated section to verify it responds as expected.
- Separate persona from data. Keep the personality instructions and the data blocks distinct so you can update one without accidentally breaking the other.
