Embeddable Web Widget Made With React
Last updated
Last updated
©2024 by Gooey.AI / Dara.network Inc / support@gooey.ai
At Gooey.AI, we have an awesome tool - Copilot Builder. It lets users create and use an AI-powered chatbot on many different platforms, such as WhatsApp, Facebook, and Slack. Alternatively, they can use the API provided by Gooey.AI to use the chatbot in any application.
However, we wanted to take things a little further to help people/organizations build and deploy AI chatbots faster without relying on any code!
So, we made our own Web Widget Integration which enables our users to deploy a AI-powered chatbot without any code and make it available to use as a standalone Web App.
Here is a high-level understanding of how we wanted the widget to work, let's break it down into 3 major milestones:
Copilot Integration: Create and use the Gooey Copilot integration settings
Widget Code: React Components, State Handling, Customization Support, Support integration settings
Injection: Process of building and loading the widget on any existing website
Let's dive deeper into how we managed to approach this scenario considering our existing architecture and fit the new code with it to achive a seamles AI-powered chatbot experience.
Our CTO @devxpy came up with this simple and seamless solution to configure the widget to support the customized widget configurations:
To embed the widget we have to paste this code inside the <body>
tag of client website:
The value of src
attribute in the above copied code is another JS script which loads the actual widget configuration made by the user using Copilot integrations UI.
Here, the integration_id (XXXXX) is the primary identifier which is fed to the Gooey Copilot's streaming API and the server then runs the associated Copilot bot with it.
All the other fields in the config object are loaded in the SystemContext which makes sure all the components mutate themselves accordingly.
This allowed us to keep the "code to be copied" very short and encapsulate the implementation of how we are feeding the configuration to the React app which also makes it cleaner.
We created this UX which users can access on /copilot page of their bot and easily give the look and feel they want their users to see. You get the "code to be copied" below here in the UI
We have our own gooey-gui python UI library which uses React with Remix.js to render the Gooey components. We wanted to:
Add a nice UI/UX for our chat window
Make the new components reusable so they can be used ultimately in the future inside gooey-gui
Create an open-source example repository showcasing how to leverage Gooey.AI API services in a production grade application framework which is popular around frontend devs these days.
We chose React with Vite.js for our implementation, leveraging Vite.js powerful module bundling and TypeScript support. We wanted to keep things modular component wise as these components would also benefit our core UI application.
The core of our widget revolves around two primary React Contexts:
SystemContext - see code
Manages widget-level interactions such as:
Minimizing widget
Toggling sidebar visibility
Activating/deactivating focus mode
Supplying copilot integration config to all components
MessagesContext - see code
Handles chat-related functionalities:
Managing message history
Sending and receiving messages
Integrating with the Gooey Copilot Streaming API
LLM Output Showcase
To render the output by the LLM we used some npm packages:
html-react-parser
- https://www.npmjs.com/package/html-react-parser
marked
- https://www.npmjs.com/package/marked
Keeping it short and optimized!
As it is a widget and has to be downloaded on the clients' site each time the page loads, we had to make sure that the bundle size should be optimized. We are currently at ~520kb unzipped. To achieve this:
Introduced a custom CSS framework imitating Bootstrap classes, reduced to only required ones
For Icons, we kept SVG code from FontAwesome to avoid downloading entire library.
To embed the React App into any other website we came up with this code.
Our widget's injection process leverages Shadow DOM to create an isolated, encapsulated rendering environment.
Dynamic target element selection.
Configuration validation.
Seamless widget embedding.
Clean unmounting support.
Completely isolate widget styles and DOM.
Prevent style conflicts with host website.
Ensure widget's CSS doesn't leak or get overridden.
Create a secure, independent rendering context.
We are completely open source, so at any point if you may have any suggestions we would appreciate a "Happy" Pull Request from you.
Our Github - https://github.com/GooeyAI
Web Widget Repository - https://github.com/GooeyAI/gooey-web-widget
Written by Anish Saxena, Software Engineer, Gooey.AI