Skip to content

Vaynerov Technologies

We don't just develop — we conjure every line of code & pixel.

All articlesBuild stories

A concierge that read everything we ever published

Every agency site has a chat bubble. Most of them are a form wearing a costume. Ours had to know the work, the prices' whereabouts, the founder's boundaries, and all twenty-one essays in this Journal — so we built it the way we build everything else, and wrote down what it cost.

Edward AmirainFounder, Vaynerov Technologies
Published 7 min read
On this page
  1. Identity without an account
  2. Always 200
  3. The file we wrote for other robots
  4. Teaching it the Journal
  5. When someone wants to hire us
  6. Numbers we can print
  7. Limits, stated out loud

There is a small pill in the corner of this page that says ask the studio. Behind it is the thing every consultancy website has promised since 2016 and almost none has delivered: a chat box that actually knows the company it fronts. Ask it what a web platform engagement includes and it recites the real deliverables. Ask it what we think about generated code and it quotes the essay. Ask it where Edward lives and it politely declines, because we taught it manners along with facts.

We could have pasted a third-party widget above the footer and moved on. But we have printed we conjure every line of code & pixel under our own name, and a rented chat bubble streaming someone else's branding through our corner would have argued against every page it floated over. So the concierge is ours end to end: a Supabase Edge Function, an OpenAI model, a client the size of a business card, and a knowledge layer with a story we did not expect to tell.

Identity without an account

The first design decision was who the visitor is. Chat history should survive a page reload — losing the conversation because you checked the pricing page is amateur hour — but nobody wants to create an account to ask a question, and we did not want to run anonymous authentication for what is, structurally, a guestbook with opinions.

So identity is a token: the widget mints a random thread id and a secret in your browser's storage, and the server keeps only a hash of the secret. Present the pair and the conversation continues; lose them and you simply start fresh. The thread tables are locked to the service role — no public read policy exists at all, so there is nothing to misconfigure. It is the same shape as the share tokens our quote pages have used since day one, which is exactly why we trusted it.

Always 200

Replies stream token by token over server-sent events, and the transport has one rule inherited from the /blueprint generator: the answer is always an HTTP 200 event stream, even when it is bad news. Rate limited? That is an error event. Thread token invalid? An error event. The alternative — a bare 4xx after the CORS preflight has already succeeded — is a failure the browser can see but your JavaScript cannot read, which is the worst of both worlds.

The stream also carries more than text. When the model finishes, a done event delivers the stored reply's id, which is what makes the little thumbs under the answer work. When a lead is captured mid-conversation, a lead event tells the page so our analytics can count it. The protocol stays three verbs wide and we intend to keep it that way.

Abuse is bounded by arithmetic rather than optimism: ten requests a minute per address through the same durable rate limiter the contact forms use, two thousand characters a message, a twenty-message context window, a thousand tokens of reply. A bot that wants to spend our inference budget has to get in line behind everyone else's curl.

The file we wrote for other robots

The interesting problem was knowledge. A concierge that answers from a model's general training is a liability in a nice suit: it will invent services we do not sell and prices we never quoted. Everything it says about the studio has to come from the studio.

Here is the part we did not plan. Months ago we published /llms-full.txt — a machine-readable digest of the whole site, maintained automatically from the same content the pages render, so that other people's AI assistants would describe us accurately. When we went looking for a grounding corpus for our own concierge, it was already sitting there: current, complete, and tested by strangers' robots for half a year. The function fetches it, caches it briefly, and hands it to the model with every question. The file we wrote for other robots turned out to be the brain of ours.

Three tiers, one reply: the fixed canon, the live site digest, and whatever the Journal has to say about your question.

On top of the digest sit two more tiers. A short, hand-written canon carries the rules that must never drift: the brand's banned words, the refusal to invent numbers, and a founder profile with an explicit boundary — everything the concierge may say about Edward personally fits in six bullet points, and it is instructed to refuse the seventh. Not because the model would otherwise gossip, but because a public bot's limits should be a design decision, written down, not an emergent property.

Teaching it the Journal

The third tier is this Journal. Twenty-one essays about how we build things is exactly the material a visitor's hardest questions want — how did you make Safari fast, what broke in the museum, why publish prices at all — but at some sixty thousand words it cannot ride along in every request.

So the essays are cut into passages and embedded into vectors, and every incoming question is embedded the same way and matched against them. The four closest passages, above a similarity floor, travel with the prompt; the model is told to quote freely and link the source. Ask how we made Mobile Safari fast and the concierge answers with the actual numbers from /articles/making-mobile-safari-fast — the 250-to-950-millisecond TTFB that became single digits, the 91 kilobytes of JavaScript that left the initial bundle — because it is reading the same paragraphs you would.

The index rebuilds automatically on deploy. Which produces a sentence we enjoy typing: by the time you read this, the concierge has read it too. Articles about the machine become part of the machine — ask it how it works and it will cite this very page at you.

When someone wants to hire us

A studio chat box has one commercial job: notice when a conversation stops being curiosity and starts being a project. The model carries a single tool for this — it can file a lead with a name, an email, and a one-line brief, and it is instructed to use it at most once, only with details the visitor actually typed, and never to ask twice. The lead lands in the same table as the contact form's, the studio gets pinged, and the visitor gets one sentence of confirmation instead of a follow-up sequence.

Mechanically this is the least glamorous part of the build and the most instructive: mid-stream, the model pauses its own reply, calls the tool, receives the result, and continues talking — two upstream requests stitched over one connection to the browser, invisible unless you are watching the wire. The visitor experiences a sentence. That asymmetry is most of what engineering is.

Numbers we can print

~5,800
prompt tokens riding with every question
130
Journal passages in the vector index
6
locales the concierge greets you in
10/min
requests per visitor before the limiter objects

Measured on ship day, not estimated — the reply that produced the token count said, in full, "OK".

Every reply writes its own token receipts into the database, so the monthly cost of the concierge is a query, not a guess. We can also see which answers earn the thumbs-up under them and which do not — the ratings land next to the receipts. A feature you cannot measure is a feature you cannot defend; this one ships with its own ledger.

Limits, stated out loud

  • The Journal index is English-only for now. Cross-language matching works more often than it should, but a Russian question meets English passages; embedding the translated essays is the honest fix and it is on the list.
  • The model sees the last twenty messages of a thread. A long conversation's opening eventually falls out of view; a rolling summary is designed but not built.
  • Rate limiting is per address, so an office behind one router shares an allowance. Nobody has hit it yet; the day someone does, the key gets smarter.
  • The concierge speaks for the studio but it is still a language model. It is grounded, bounded, and measured — and if it ever says something the site does not, the site wins.

Whether a chat box belongs on a studio site at all is a fair question — we wrote a whole essay about tools that respect you, and a bad concierge is the opposite of that. Our answer was to hold it to the same bar as everything else here: it streams because waiting is rude, it refuses because boundaries are content, it cites because it read the sources, and it leaves when you are on a page that has its own furniture. The museum keeps its own chat; ours stays out of the frame.