Contact assistant
A conversation instead of a form from 2005, on a site that talks about AI.
The decision
- The problem
Every call to action on the site led to a contact form that could have been from 2005, on a site that talks about AI.
- What I chose
A scripted conversation in the contact panel: the question first, then the email, then the name. Same result, an email to me; a different way of getting there.
- Ruled out
A language model behind it: it could make things up in my name. An assistant grounded in my own writing (the posts, the cases, the CV, this system) was designed and parked for later.
- What it cost
A script has to anticipate people, so it runs on rules: what to do when you ask instead of answering, and how to read an email hidden in a question.
The question first
Name, email, message is the order of a form. Nobody asks for your email before knowing what you want. The assistant asks what you want to ask me, then where to send the answer, then who to thank.
It keeps what you give it
- Ask something when it wants your email, and the question is added to your message as its own paragraph. The summary shows every question you asked, and you can edit any of them.
- An email inside a question is still an email: "can you reply to ada@…?" fills in the address and keeps the question. I found that hole by trying it.
- Its reply changes each time, so it never sounds like a wall; at the fourth question it offers the direct address, because that is when people leave.
Tested with people
Without a step counter, one tester answered the first question and believed the message had gone. "Step 2 of 3" came back. Close the panel half way and the conversation is kept: it picks up where you left it. Nothing unfinished is ever sent.
Anatomy
or write straight to hello@mveiga.com
Bubbles. One shape, two materials: the assistant takes the surface colour with a hairline border, the visitor takes the brand blue with white on it at 5.52:1. Both take the 14px radius, with the corner nearest their own side dropped to 6px: a tail, not a fourth radius. Max width 84%, so a reply never reaches the far edge and the side it came from reads at a glance. Each one arrives 10px up the expo curve; under reduced motion it simply appears. The three dots use the assistant's material, so the wait is the bubble it will become.
Composer. 27px of radius, and the number is not a taste: at one line the composer is 54px tall, so 27 is exactly half of it. As it grows the sides go straight and the corners hold at 27, the send button's 20 plus its 7px inset, so the two curves stay parallel. It is 16px exactly, because below that iOS zooms on focus, and it grows to a ceiling of six lines. The send button stays dim until there is something to send.
Step marker. Top left, announced to screen readers.
Review card. Nothing is sent until it has been shown back. The card is a bubble that grew up, and every row is a button: click one and that single field goes back into the composer with its text already there. Before that, a mistyped email meant starting over.
Two actions, one of them destructive. The site's own button, on two columns of equal width: with automatic widths, reset came out wider than send, which is the wrong thing to make prominent. Send is filled and reset carries the circular arrow, because it goes back. Meanwhile the composer dims to 35% and its border goes dashed: it is waiting for a decision, and shouldn't compete with the two things that make it.
Where it broke the rules. It was built with fresh classes, so it reached for nothing: the input shipped at 15.2px under the 16px floor, and the bubbles and labels sat outside the type scale. All of it is on the scale now. The lesson stays: this is coverage drift.
Accessibility
Screen reader users get a way out: a link to the classic form, hidden until you tab to it from close, and then in blue. The composer carries its own label, not just a placeholder. On a phone the panel closes with a swipe to the right, like iOS.
The classic form
Labels in lowercase monospace, fields at 16px so iOS never zooms. It lives at /contact/: one request, no JavaScript required.
Measured
The whole funnel is tracked: opened, each step, the summary, sent, reset, resumed and errors. It is the one place on the site where intent is highest, so it is the one worth measuring closely.