Abstrakcyjna grafika prezentująca AI i szewca bez butów
Home/Blog/The Cobbler's Children Have No Shoes — Building an AI Assistant for appcrates.pl

The Cobbler's Children Have No Shoes — Building an AI Assistant for appcrates.pl

Arkadiusz Wawrzyniak

Arkadiusz Wawrzyniak

May 6, 2026 - 47 views - 5 min read

Share

You know how it goes. The cobbler's children have no shoes. The doctor neglects his own health. The hairdresser with the messy hair.

For a while, I was exactly that cobbler.

AppCrates offers AI implementations, RAG, chatbots, assistants built on company data. I build it, explain how it works, ship it for clients. But on my own landing page? Nothing. Zero. A contact form and an FAQ.

Classic.

I decided to fix that — and show you exactly what it looks like from the inside.

Why I Did It At All

It's not just about appearances, though that's an argument too. It's about the fact that if you don't use what you sell, that's a red flag. For a potential client who lands on your site and wants to ask something at 11PM — there's nobody there. The form sits waiting. Nobody reads emails at that hour.

An AI assistant solves exactly that problem. It answers questions about services, the collaboration process, technologies — based on real data from the site, without confabulation, without hallucinations.

And yes, I know — "without hallucinations" is a bold claim. I'll explain how I achieved that in a moment.

Architecture — RAG in a Nutshell

The catch with building LLM-based chatbots is that the model knows nothing about your company by default. It knows the world up to its training cutoff, but it doesn't know your services, your projects, or your pricing.

That's where RAG comes in — Retrieval Augmented Generation. In short: before the model responds, we first pull the relevant context from a database and inject it into the query. The model doesn't guess — it answers based on real data.

In my case, the context is built from:

  • Content from Sanity CMS (services, projects, blog posts, the "about me" section)
  • FAQ
  • Privacy policy
  • Company description

All of this lands in the system prompt as structured context. The model gets concrete facts and answers based on them. No making things up.

1 / 3
chat bot 1

Click to zoom

Security — No Cutting Corners Here

This is the part clients often don't see, but which is absolutely CRITICAL in any chatbot implementation that has access to data.

The problem is simple: if a chatbot has access to a CMS and someone types "delete all posts" or "change the pricing" — what happens?

With bad architecture: exactly what you asked for.

That's why I built 8 layers of protection, from the client side all the way down to the Sanity client architecture itself.

Read-Only Client

The Sanity client used by the chatbot has no write token. Literally — it cannot modify anything, even if it receives such an instruction. This is the foundation. Everything else is additional safety netting.

Middleware and HTTP Guards

The /api/chat endpoint accepts only POST and OPTIONS methods. GET, PUT, PATCH, DELETE — rejected at the middleware level, before they ever reach the application logic. Additional guards exist at the route handler level too — defense in depth, as they say.

Destructive Request Detection

A keyword list — in both Polish and English — that immediately blocks a request before it ever reaches the model. "Delete", "remove", "edit", "publish", "reset"... and their Polish equivalents. The user gets a refusal with an explanation. The model never even sees the request.

Prompt Engineering

The system prompt has clear rules baked in: don't perform mutating actions, answer only based on the provided context, don't agree to any attempts to bypass the rules. This is the last line of defense — if something slips through the previous layers, the model rejects the request on its own.

The result? A grep through the code won't find a single call to create(), patch(), delete(), or commit() in the chatbot route file. The architecture physically prevents writes.

Bilingual Support — PL and EN

The site handles two languages, so the chatbot had to as well. I implemented language detection at multiple levels.

On the client side — language from the application context. On the server side — fallback to content analysis: Polish diacritic characters, Polish stop words. Defaults to Polish if uncertain.

The entire RAG context is built separately for each language — separate section headers, separate descriptions, separate FAQ content. The cache operates per-language, so we don't pay double in Sanity queries.

The widget UI is fully localized too — every system message, placeholder, aria-label, title. Zero hardcoded Polish text in the code.

Rate Limiting — So Nobody Abuses It

10 requests per minute per IP on the server side. 15 requests per hour per browser on the client side. When the limit is exceeded — a localized error message, no crash, no 500.

A honeypot field in the form as additional bot protection.

How It Turned Out

The widget runs on the homepage, project detail pages, FAQ, and the privacy policy. On mobile it's full screen with 100dvh, on desktop a floating window. The open button hides on mobile when the chat is open — the X in the header takes over instead.

Build passed. TypeScript passed. It works.

But more important than the technical details is what a visitor can now do: ask about any service, about the collaboration process, about specific technologies — and get an answer instantly. No waiting for an email. No digging through FAQ.

What This Means for You

If you have a business and a website — an AI assistant built on your own data isn't a gimmick. It's a concrete sales tool that works 24/7, doesn't get sick, and never forgets what you offer.

The catch is that you do it once and do it right — with a well-thought-out security architecture, because a chatbot plugged into a CMS without proper safeguards is asking for trouble.

I went through all of this myself while building it for my own site and for the marketplace artovnia.com. I know what works, I know what can go wrong.

If you want a similar solution for your business — reach out. Happy to talk.

FAQ

Frequently asked questions

RAG (Retrieval Augmented Generation) is an architecture where the AI model receives relevant context from your own data before generating a response. Instead of relying on its training data, the model answers based on real, up-to-date content from your CMS — services, projects, FAQ, and company description. This eliminates confabulation because the model is explicitly instructed to answer only from the provided context, not from general knowledge.

No. The Sanity client used by the chatbot is configured with a read-only token — it has no write permissions at the API level. On top of that, there are multiple additional layers: HTTP method guards, destructive keyword detection, and prompt engineering rules that instruct the model to refuse any mutating requests. The architecture physically prevents writes.

Language detection happens at two levels. On the client side, the language is read from the application context. On the server side, there is a fallback that analyzes the message content — looking for Polish diacritic characters and stop words. The RAG context is built separately for each language, and the entire widget UI is fully localized. The system defaults to Polish when uncertain.

There are two independent rate limiting layers: 10 requests per minute per IP address on the server side, and 15 requests per hour per browser session on the client side. When a limit is exceeded, the user receives a localized error message — no crash, no 500 error. A honeypot field provides additional protection against automated bots.

The assistant's context is built from content stored in Sanity CMS: service descriptions, project case studies, blog posts, the about me section, FAQ entries, the privacy policy, and the company description. All of this is injected into the system prompt as structured context before each response.

Yes. AppCrates builds custom AI assistants grounded in your own business data — with a proper security architecture, bilingual support, and CMS integration. The implementation is done once and done right. Reach out via the contact form to discuss your use case.

Running costs depend on the LLM provider you choose (e.g. OpenAI, Anthropic) and the volume of conversations. With rate limiting in place, costs are predictable and controllable. For most small-to-medium business websites, monthly LLM API costs are modest — typically a few dollars to tens of dollars depending on traffic.