<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: rorie devine</title>
    <description>The latest articles on DEV Community by rorie devine (@orrdee).</description>
    <link>https://dev.to/orrdee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F73156%2F398fed19-2175-4944-9f44-1fb7d9980ba5.jpg</url>
      <title>DEV Community: rorie devine</title>
      <link>https://dev.to/orrdee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orrdee"/>
    <language>en</language>
    <item>
      <title>I Added AI to Any Website With One Line of JavaScript — Here's How</title>
      <dc:creator>rorie devine</dc:creator>
      <pubDate>Sat, 21 Mar 2026 12:23:06 +0000</pubDate>
      <link>https://dev.to/orrdee/i-added-ai-to-any-website-with-one-line-of-javascript-heres-how-36dc</link>
      <guid>https://dev.to/orrdee/i-added-ai-to-any-website-with-one-line-of-javascript-heres-how-36dc</guid>
      <description>&lt;p&gt;Last year I got tired of watching businesses lose customers because their websites couldn't answer basic questions at 9pm.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://embedai.dev" rel="noopener noreferrer"&gt;EmbedAI&lt;/a&gt; — an embeddable AI assistant that works with one line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://embedai.dev/embed/v1/chat.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No API keys. No backend. No configuration. The AI reads your website content and starts answering customer questions immediately.&lt;/p&gt;

&lt;p&gt;Here's how it works under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every website has the same issue: customers have questions, but there's nobody there to answer them. Contact forms go unanswered. Phone lines close at 5pm. FAQ pages are buried three clicks deep.&lt;/p&gt;

&lt;p&gt;Traditional chatbots don't solve this — they follow scripted decision trees that frustrate users the moment they ask something unexpected.&lt;/p&gt;

&lt;p&gt;What businesses actually need is an AI that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reads their website&lt;/strong&gt; and understands their services, pricing, and FAQs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answers in natural language&lt;/strong&gt; — not "Press 1 for opening hours"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works immediately&lt;/strong&gt; — no training data, no prompt engineering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runs on any website&lt;/strong&gt; — WordPress, Wix, Squarespace, custom-built, anything&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The embed snippet loads a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Components" rel="noopener noreferrer"&gt;Web Component&lt;/a&gt; called &lt;code&gt;&amp;lt;embedai-chat&amp;gt;&lt;/code&gt;. Here's what happens when it hits a page:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Auto-Mount
&lt;/h3&gt;

&lt;p&gt;The script self-initialises — no &lt;code&gt;document.createElement&lt;/code&gt; or &lt;code&gt;ReactDOM.render&lt;/code&gt; needed. It registers a custom element and appends it to the body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;embedai-chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... register and auto-mount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means it works on literally any website. React, Vue, Angular, plain HTML, WordPress — if it has a &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag, it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Theme Detection
&lt;/h3&gt;

&lt;p&gt;The widget auto-detects whether the host site is light or dark themed and adapts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;THEMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0A0A0B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#7FFF00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userBubble&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#7FFF00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#16A34A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userBubble&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#16A34A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also pass custom theme colours if you want to match your brand exactly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. RAG Pipeline (the interesting bit)
&lt;/h3&gt;

&lt;p&gt;When a user asks a question, here's what happens server-side:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Expansion&lt;/strong&gt; — The original question gets expanded into 3 alternative phrasings using Groq/Llama. This dramatically improves retrieval recall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original: "Do you handle VAT returns?"
Expanded:
  → "VAT return services available"
  → "Tax filing and VAT support"
  → "Accounting services for VAT"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hybrid Retrieval&lt;/strong&gt; — All query variations hit a Supabase (pgvector) database in parallel. We use both vector similarity search AND keyword matching — hybrid search catches things that pure semantic search misses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM Reranking&lt;/strong&gt; — Retrieved chunks get reranked for relevance before being passed to the final completion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Streaming Response&lt;/strong&gt; — GPT-4o generates the answer using the retrieved context, streamed back to the widget in real-time.&lt;/p&gt;

&lt;p&gt;The entire pipeline runs in under 2 seconds for most queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Demo Mode
&lt;/h3&gt;

&lt;p&gt;Here's the clever bit for adoption: the widget works &lt;strong&gt;without any configuration&lt;/strong&gt;. No API key, no token, no signup.&lt;/p&gt;

&lt;p&gt;In demo mode, it uses Groq's &lt;code&gt;llama-3.1-8b-instant&lt;/code&gt; (the cheapest model available) and rate-limits to 5 messages per browser + 5 per IP per 24 hours. Enough to try it out, not enough to run up a bill.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_isDemo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;CFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;PLACEHOLDER_TOKENS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When someone adds a token, it switches to their own AI provider and removes the rate limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Web Components are underrated
&lt;/h3&gt;

&lt;p&gt;Everyone reaches for React or Vue, but for an embeddable widget, Web Components are perfect. They:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work everywhere with zero dependencies&lt;/li&gt;
&lt;li&gt;Don't conflict with the host page's framework&lt;/li&gt;
&lt;li&gt;Encapsulate styles via Shadow DOM&lt;/li&gt;
&lt;li&gt;Are natively supported in every modern browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building anything embeddable, seriously consider Web Components before reaching for a framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG beats fine-tuning for this use case
&lt;/h3&gt;

&lt;p&gt;I wrote about this in detail in &lt;a href="https://embedai.dev/rag-for-saas" rel="noopener noreferrer"&gt;RAG for SaaS&lt;/a&gt;, but the short version: fine-tuning is expensive, slow to update, and hallucinates when it doesn't know something. RAG retrieves real content and cites it — which is exactly what you want when answering questions about someone's business.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "no config" default matters enormously
&lt;/h3&gt;

&lt;p&gt;The biggest adoption unlock was making the widget work with zero configuration. Most developers (and especially non-developers) won't sign up, get an API key, and configure something just to try it. But they will paste one line of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Paste this into any HTML page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://embedai.dev/embed/v1/chat.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It'll mount a chat widget in the bottom-right corner, read the page content, and start answering questions about it.&lt;/p&gt;

&lt;p&gt;If you want to customise it — theme, title, position, your own AI provider — check out the &lt;a href="https://embedai.dev/embeddable-ai" rel="noopener noreferrer"&gt;full docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The code handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-theming&lt;/strong&gt; (light/dark detection)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming responses&lt;/strong&gt; (real-time typing effect)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile responsive&lt;/strong&gt; (full-screen on mobile)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting&lt;/strong&gt; (demo mode for free tier)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install tracking&lt;/strong&gt; (ping on load, usage analytics)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I'm working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Action triggers&lt;/strong&gt; — let the AI execute tasks, not just answer questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language support&lt;/strong&gt; — auto-detect and respond in the user's language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversation memory&lt;/strong&gt; — context that persists across sessions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building something similar, or have questions about the RAG pipeline, drop a comment — happy to go deeper on any of this.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Rorie, founder of &lt;a href="https://embedai.dev" rel="noopener noreferrer"&gt;EmbedAI&lt;/a&gt;. We build &lt;a href="https://embedai.dev/embeddable-ai" rel="noopener noreferrer"&gt;embeddable AI&lt;/a&gt; for businesses that want to add AI to their website without hiring a dev team.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
