Skip to the case study

Conversational UX • Systems Design • Built and Shipped

I Put a Bot on My Portfolio. Someone Told Me It Made My Work Look Generic.

Live on this page right now. Three versions, no API, every answer written by hand.

Meet her on the homepage
Vivi

Vivi

Portfolio guide · live on marauderofux.com

Role
Product Designer, designer and builder
Team
Solo. Designed, built and still running it.
Timeline
Live and ongoing
What I owned
  • Designed and coded it end to end
  • Still shipping fixes to it

Vivi in motion

She moves with the page, changes side and pose, and says something different in each section.

Problem

A portfolio only answers the questions it thought to ask itself.

Recruiters arrive with specific questions. A portfolio guesses at them in advance, and everyone whose question it missed leaves without saying so. Vivi was the fix. V1 opened a worse problem: it never said what it was.

“If you're not the one answering, and it's an AI chatbot, your work reads as very generic.”
Visitor comment, left publicly on the first version

Process + Evidence

Three versions

  1. V1

    Ran on Claude's API

    Answered anything, in my voice, with nothing saying what it was.

  2. The critique

    Called out in public

    A visitor said a bot answering made the work look generic. Fair. The fix belonged in the product.

  3. V2, current

    Scripted, disclosed, on the page

    No API. Every answer handwritten. She moves with the page and says what she is.

Decision

A guide, not a chat boxShe comes to you

Live
Vivi greeting a visitor and reacting as they scroll.

An empty text box asks the visitor to do the work. Vivi moves with the page instead and offers what is worth doing in that section.

Decision

Not a person, not an AIDisclosure is the first thing she says

Live
Visitor
Are you an AI?
Vivi
No. I'm Vivi, a scripted guide Vrishika built. Not her, and not an AI chatbot either. Every answer here is written by her directly. If something is outside what I know, I'll route you to leave her a question.
Live answer, verbatim.

Saying the answers are handwritten is what answers the criticism. Generic is what a model sounds like.

Decision

Five buttons, not fiftyAround 40 scripted answers behind 5 visible chips

Live
Visitor
Where should I start?
Vivi
This is one of her best pieces of work, CodSphere. Want to take a look? I can walk you through it, or give you the whole portfolio in order if you'd rather.
One recommendation with a reason.

Forty buttons is a menu, and a menu is the problem. Typing reaches the rest.

Decision

No match captures the questionA miss becomes a contact, not a dead end

Live
Visitor
What's her notice period?
Vivi
I don't have a scripted answer for that one. You can leave a question below and Vrishika personally reads every one and will get back to you directly.
The fallback is the conversion point.

It says plainly that it has no answer, then takes the question. Name and email optional, question required.

Decision

Killed the APINo running cost, nothing it can invent

Live

V1 could answer anything, including things about my work that were not true. Handwritten answers cannot hallucinate.

How a question resolves

  1. Greetings first. A bare hi used to hit the failure state and read as broken.
  2. Then the specific bank. Case studies, trust breaks, the hard interview questions.
  3. Then the five chips. Experience, projects, skills, process, contact.
  4. No match, take the question. Logged, and a person replies.

What shipping it taught me

  • The greeting vanished before anyone could answer it. A stale closure, plus a dismiss-on-scroll rule that fired while people were just reading.
  • Typing moved the whole panel on Android. The keyboard shrinks the viewport and fires resize. Position now freezes while the chat is open.
  • The greeting never fired twice. Browser storage survived reloads. It is an in-memory flag now, and tracks nobody.
  • Two Vivis in one corner on mobile. The hide rule covered chatting but not the prompt state.
  • iOS zoomed the page on focus. Any input under 16px triggers it. Not a layout bug.
  • IntersectionObserver was unreliable in Framer. Replaced with scroll maths and retries while layout settles.

Learning + Trade-off