Demonstration ProjectBasic AISmall business / e-commerce

Pebble Chat

Answer the small questions, hand over the big ones.

Pebble Chat is a small chat widget for independent shops. It answers shipping, returns, workshop and care questions from a FAQ the owner writes, and when it is not sure it says so and offers to pass the question to the owner by email. I built it around a ceramics shop, Clayform Studio, to show a deliberately simple and well-bounded LLM integration.

  • React.js
  • Node.js
  • Express.js
  • LLM API
  • REST API
  • SQLite
Widget open on the shop page. Interface designed and built by Vikrant

Overview

Business problem
A small shop gets the same dozen questions every week: how long delivery takes, whether a mug can go in the dishwasher, how to book a workshop. The owner answers them by hand in the evenings, and a visitor who does not get a quick reply often leaves without buying or booking.
Product objective
Answer the repeated questions instantly and accurately from the shop's own policies, never invent a policy, and make sure anything the bot cannot answer reaches the owner with enough context to reply quickly.
Target users
Independent shop owners with a small website and no support team, and the visitors who browse their shop looking for a quick answer before ordering or booking.
Solution
A short system prompt plus the owner's FAQ text sent with every question to an LLM, a widget that streams the reply, a rule that anything outside the FAQ gets a hand-off instead of a guess, and an owner view that shows every conversation and every unanswered question.

Project classification

Project type
AI chat widget
Industry
Small business / e-commerce
Frontend
React.js widget loaded by a single script tag on the shop site
Backend
Express.js service that builds the prompt and makes one LLM call per message
Database
SQLite for the conversation log and FAQ entries (MySQL is a drop-in for a hosted setup)
Architecture
Widget, REST API, prompt builder and LLM API; no retrieval layer

User roles

  • Visitor (shop customer)
  • Shop owner

My role

  • Product scoping: kept it to a prompt, a FAQ and a hand-off instead of adding retrieval, accounts or analytics.
  • Backend design: Express.js endpoint, prompt assembly, message caps and the hand-off rule.
  • Prompt design: system prompt, grounding instructions, refusal wording and basic injection hardening.
  • Database design: a small SQLite schema for conversations, messages, FAQ entries and unanswered questions.
  • Frontend: the embeddable widget and the owner screens in React.js.
  • Integration: LLM API call with streaming, and the email hand-off.
  • This is a self-initiated concept; there is no client, live deployment or user base.

Key features

  • Widget open on the shop page. Interface designed and built by Vikrant

    A widget that lives on the shop page

    The widget opens over the shop's own pages and answers in the shop's voice. Replies stream in, stay short, and point to the relevant policy. If the question is outside the FAQ, the bot says it is not sure and offers to send the question to the owner instead of guessing.

  • Conversation log. Interface designed and built by Vikrant

    Every conversation, readable at a glance

    The owner sees each conversation with its first question, the outcome (answered or handed off) and a flag for answers that look wrong. Opening one shows the full exchange, so a bad answer can be traced to a missing or unclear FAQ entry.

  • FAQ editor. Interface designed and built by Vikrant

    A FAQ editor that is just text

    The shop's knowledge is a list of plain question-and-answer entries grouped by topic, such as shipping, returns, workshops and care. There is no model training involved: editing an entry changes the text sent with the next question, and a character counter shows how much of the context budget the FAQ uses.

  • Unanswered questions inbox. Interface designed and built by Vikrant

    Unanswered questions become FAQ entries

    Every question the bot could not answer lands in an inbox with the visitor's message and, if they left one, their email. The owner replies by email, then turns the question into a FAQ entry with one click so the next visitor gets an answer straight away.

  • Widget settings and embed. Interface designed and built by Vikrant

    Settings and a one-line embed

    The owner sets the greeting, the bot's tone, the hand-off email and the message limits, and copies a single script tag to paste into the shop's site. The limits keep cost predictable without needing a billing system.

Also in the product

  • Chat widget embedded with one script tag
  • Answers drawn only from the owner's FAQ and policy text
  • Honest fallback with a hand-off to the owner's email
  • Conversation log with a flag for answers that need a fix
  • Unanswered questions inbox that turns gaps into new FAQ entries
  • Per-visitor and per-day message caps
  • Basic prompt-injection hardening

User flow

  1. Owner writes the FAQ and sets the hand-off email and message limits
  2. Owner pastes one script tag into the shop's website
  3. Visitor opens the widget and asks a question
  4. Server checks the message caps and builds the prompt from instructions, FAQ and recent messages
  5. LLM reply streams back to the widget
  6. If the answer is not in the FAQ, the bot offers a hand-off and the visitor can leave an email address
  7. The conversation is saved; unanswered questions go to the inbox
  8. Owner reviews the log, replies by email and adds missing answers to the FAQ

Technical architecture

  1. Shop website with a single script tag
  2. React.js chat widget (streams replies)
  3. Express.js REST API: validation, message caps, hand-off
  4. Prompt builder: system instructions, FAQ text, last few messages
  5. LLM API (one call per visitor message)
  6. SQLite log: conversations, messages, FAQ entries, unanswered questions
  7. Owner dashboard (React.js) and email hand-off

Database and backend

Prompt and grounding

  • One system prompt states the shop's name, tone and the rule: answer only from the FAQ below, never invent prices, dates or policies.
  • The FAQ is plain text appended to the system prompt, small enough to fit in every request, so no retrieval or embeddings are needed at this size.
  • When the FAQ does not cover a question, the model is told to reply with a fixed marker and a short apology; the server swaps the marker for the hand-off prompt.
  • Only the last few messages of the conversation are sent, to keep each request short and cheap.

Hand-off and unanswered questions

  • A hand-off creates an unanswered-question row with the visitor's message, the conversation id and an optional email address.
  • The shop owner is emailed a short summary with a link to the conversation.
  • Hand-offs are rate limited per conversation so a visitor cannot trigger a flood of emails.

Cost control and basic hardening

  • Message caps per conversation and per visitor per day, plus a maximum visitor message length, enforced on the server.
  • A cap on output tokens and a request timeout, with a friendly fallback message if the LLM API fails.
  • Visitor text is passed as a user message and never concatenated into the system prompt; a short instruction tells the model to ignore requests to change its rules.
  • Basic checks for obvious injection phrases and for replies that quote the system prompt; these reduce the problem but do not make it impossible.
  • The API key stays on the server; the widget only talks to the shop's own endpoint.

Data model

  • Conversation, Message, FaqEntry, UnansweredQuestion, Setting.
  • Messages store role, text and a created timestamp; no payment or account data is collected.
  • Visitor email is stored only when the visitor chooses to leave one for a hand-off.

Challenges and solutions

  • Keeping answers inside the shop's real policies

    The prompt tells the model to answer only from the FAQ text, to quote policy wording where it can and to use a fixed fallback when the answer is not there. The conversation log makes wrong answers easy to spot, and the fix is usually a clearer FAQ entry rather than a longer prompt.

  • Deciding when to hand off instead of answering

    The model returns a marker when the FAQ does not cover the question, and the server turns that into an offer to email the owner. Questions about orders, refunds on a specific purchase or anything personal always hand off, because the bot has no access to order data.

  • Cost control on a small shop's budget

    Short context (instructions, FAQ and a few recent messages), an output token cap, a conversation message limit and a daily limit per visitor. A shop with a short FAQ pays for a small, predictable request every time.

  • Prompt-injection basics for a public widget

    Visitor text never goes into the system prompt, the instructions say to ignore attempts to override them, and replies are checked for leaked instructions. The bot has no tools and no private data beyond the public FAQ, so the worst case is a rude or off-topic reply.

  • A FAQ that stays current

    The unanswered inbox shows what visitors actually ask, and converting a question into an FAQ entry is one click. The FAQ editor shows how much of the context budget is used so the owner knows when to trim.

Results

  • A compact case study of a bounded LLM integration: one prompt, one FAQ, one call per message, with clear limits.
  • Shows honest scoping, where the bot says it does not know and hands the question to a person.
  • A small data model and API that a single developer can host and maintain for a small shop.
  • Illustrates cost and safety basics (message caps, hardening, no secrets in the widget) without overstating what they guarantee.

Qualitative outcomes only; no usage or revenue figures.

Visual identity

  • Primary #C65D3B
  • Secondary #2B2623
  • Accent #8FAE8B
  • Background #FBF7F3

Outfit for headings and the widget header, Inter for body text. A rounded pebble shape holding a speech-bubble tail. Warm, soft-cornered widget and a calm owner dashboard with a narrow sidebar and plain tables.

  • Demonstration ProjectAI / automation

    AgentForge

    Build, ground and monitor AI agents with RAG, tools, a testing playground and usage tracking.

    • Next.js
    • React.js
    • TypeScript
    • Node.js
    • Laravel
    • PostgreSQL
    • pgvector
    • RAG
    • LLM APIs
    • REST API
    • Webhooks
  • Portfolio ProjectFood / subscription commerce

    Cadence Kitchen

    Meal-plan subscription platform with skip, pause and nutrition tracking.

    • React.js
    • TypeScript
    • React Query
    • Node.js
    • Express.js
    • MongoDB
    • REST API