A lightweight, customizable chat widget built with React, TypeScript, and Vite. Easily embed real-time chat functionality into any website or web application.
- ⚡️ Fast and modern React + TypeScript codebase
- 🛠️ Easy to embed in any site with a single script tag or npm install
- 🎨 Customizable styles and behavior
Via npm:
npm install embeddable-chat-widget
Or via pnpm:
pnpm add embeddable-chat-widget
import "@itzfeltrin/embeddable-chat-widget/dist/style.css";
import { Widget } from "@itzfeltrin/embeddable-chat-widget";
function App() {
return <Widget openRouterKey="YOUR_API_KEY" />;
}
To customize the brand colors of the chat widget, you can define CSS variables in your stylesheet. Add variables ranging from --color-brand-50
to --color-brand-950
to override the default color palette. For example:
:root {
--color-brand-50: #f2f7fb;
--color-brand-100: #d8e9f4;
--color-brand-200: #b2d4ea;
--color-brand-300: #7fb8dc;
--color-brand-400: #4c9bce;
--color-brand-500: #0071ba;
--color-brand-600: #00609e;
--color-brand-700: #004f82;
--color-brand-800: #00385d;
--color-brand-900: #002137;
--color-brand-950: #00101b;
}
Place these variables in your global CSS to apply your custom brand colors to
Add this to your HTML:
<!-- React and ReactDOM (required for the widget) -->
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@itzfeltrin/embeddable-chat-widget@latest/dist/embeddable-chat-widget.css"
/>
<script src="https://cdn.jsdelivr.net/npm/@itzfeltrin/embeddable-chat-widget@latest/dist/embeddable-chat-widget.iife.js"></script>
<script>
ChatWidget.mount({
selector: "#root",
openRouterKey: "YOUR_API_KEY",
colorPalette: {
50: "#f2f7fb",
100: "#d8e9f4",
200: "#b2d4ea",
300: "#7fb8dc",
400: "#4c9bce",
500: "#0071ba",
600: "#00609e",
700: "#004f82",
800: "#00385d",
900: "#002137",
950: "#00101b",
},
});
</script>
Prop/Option | Type | Description |
---|---|---|
selector |
string | Element the widget is going to mount onto (required when using the script tag) |
openRouterKey |
string | Your API key (required) |
colorPalette |
object | Color palette (optional — available only via mount ) |
Clone the repo and install dependencies:
git clone [email protected]:itzfeltrin/embeddable-chat-widget.git
cd embeddable-chat-widget
pnpm install
Start the dev server:
pnpm dev
I think this was a really fun and different task — different in the sense that I’ve never done anything like it as part of an interview process before. It was fun most of the time… except when I couldn’t get the widget to build in external React projects.
One thing that caught my attention right away in the instructions was "Install and use the widget on a sample HTML page." So my first idea was to create the package and make it an IIFE available via a <script> tag — which I did. It was working great until I decided to also export it for EJS so I could use it in another React project. That’s when I ran into a ton of bugs, spent way too much time on them, and somehow broke the script tag version entirely. Right now, the <script> tag works fine if you target version 0.0.17 of the widget.
Regarding the actual code, I didn’t face too many issues to be honest. I used the stack I’m most comfortable with and had a great DX overall. The UI turned out pretty good in the end (IMHO), and I’m happy with it. A lot of the packages I pulled in definitely aren’t necessary for a project this small, but I figured this was the perfect time to show you the tools I like working with.
I ran out of time and wasn’t able to add tests (classic), so that would be the next thing I’d do. I’d also like to add some animations — probably using Framer Motion (yep, another library).
For the LLM, I went with OpenRouter. It’s not an actual LLM, but more like a wrapper around many of them, such as GPT-3.5, which is what I used here. If I had more time, I’d set up my own backend to connect with it so I wouldn’t have to put keys in the frontend. That backend could also handle extras like real authentication, user sessions, conversation history, maybe even a way to store context for returning users.