neiki-assistant
v1.0.0
Published
Lightweight, framework-independent AI chatbot widget for websites and CMS systems
Maintainers
Readme
Live version: https://neikiri.dev/assistant
Overview
Neiki's Assistant is an embeddable AI chat widget written in plain JavaScript with zero dependencies. Attach the custom element anywhere on a page and it becomes a fully working chat surface — floating launcher, streaming replies, markdown rendering, and conversation history — all rendered inside an isolated Shadow DOM so it never clashes with the host page's styles.
<script src="https://cdn.neikiri.dev/neiki-assistant/neiki-assistant.min.js"></script>
<neiki-assistant api="/api/chat"></neiki-assistant>That snippet is a complete, working chat widget. The minified build bundles its own CSS, so a single <script> tag and one custom element are enough to get started. From there you can configure branding, theme, localization, and wire up your own backend through the api attribute.
Why Neiki's Assistant?
Most chat widgets either lock you into a specific AI provider or ship as a heavy, framework-dependent bundle. Neiki's Assistant avoids both.
One file, no dependencies. The widget ships as a single script. The minified build embeds its CSS, so there is nothing else to install, import, or bundle. Drop it into a static page, a PHP template, or a SPA component — it behaves the same way.
Provider agnostic by design. The widget never talks to an AI provider directly. It sends
{ messages, locale }to theapiendpoint you configure, and your backend decides whether that means OpenAI, OpenRouter, Ollama, Local AI, or any custom stack. Credentials never touch the browser.Shadow DOM isolation guaranteed. Host page CSS never leaks into the widget, and the widget's CSS never leaks into the host page. Ship it next to any design system without a specificity battle.
Zero-config by default, configurable when you need it.
<neiki-assistant api="/api/chat"></neiki-assistant>gives you a fully working chat window immediately. Every other attribute is optional.Real conversation UX, not just a message list. Streaming replies, markdown with syntax-highlighted code blocks and copy buttons, a typing indicator, and retry-on-error are all built in.
A real conversation history, not a single thread. Past conversations can be browsed, switched between, deleted individually, or cleared all at once — backed by
localStorage, no backend required for persistence.Built-in safety. All message content is escaped before markdown formatting, links are restricted to safe URL schemes, and the chat surface is fully isolated from the host page through Shadow DOM.
If you want a chat widget that talks to your own backend, ships from a single file, and drops into any page without CSS conflicts — that is the gap this project fills.
Features
- Vanilla JavaScript only — no frameworks, packages, bundlers or build tools.
- Web Components API — works as a native custom element.
- Shadow DOM — isolated styling with no global CSS leakage.
- Backend-ready — messages are sent to a developer-configured
apiendpoint; no provider is assumed. - One-script CDN usage — a single
<script>tag is all you need; no build step required for consumers. - Streaming replies — supports
text/event-stream,text/plain, or plain JSON responses. - Markdown rendering — fenced code blocks with syntax highlighting and copy buttons.
- Conversation history — browse, switch between, delete and clear past conversations.
- Persistence — conversations are saved to
localStorageper session. - Typing indicator — loading state, retry and error handling included.
- Light, dark and auto themes — with CSS variable customization.
- English and Czech UI — with an extensible i18n system.
- Keyboard friendly — Enter to send, Shift+Enter for newline, accessible controls.
Getting started
The recommended install is the single bundled script from the CDN. CSS is included automatically.
<script src="https://cdn.neikiri.dev/neiki-assistant/neiki-assistant.min.js"></script>Pin a specific version
<script src="https://cdn.neikiri.dev/neiki-assistant/1.0.0/neiki-assistant.min.js"></script>Alternative CDN — jsDelivr
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-assistant@latest/dist/neiki-assistant.min.js"></script>
<!-- Pinned -->
<script src="https://cdn.jsdelivr.net/gh/neikiri/[email protected]/dist/neiki-assistant.min.js"></script>Package manager
npm install neiki-assistant
# or
yarn add neiki-assistant
# or
pnpm add neiki-assistantSelf-hosted
<script src="path/to/neiki-assistant.min.js"></script>Quick Start
The minified CDN build embeds all widget CSS and registers the <neiki-assistant> custom element automatically.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Site</title>
</head>
<body>
<!-- Place it anywhere; it renders as a fixed, floating widget -->
<neiki-assistant
api="/api/chat"
title="Support"
subtitle="Usually replies in a few seconds"
language="en"
theme="auto">
</neiki-assistant>
<script src="https://cdn.neikiri.dev/neiki-assistant/neiki-assistant.min.js"></script>
</body>
</html>Version-pinned CDN URL
When distributing over a CDN, pin to a specific version to avoid unexpected breaking changes:
<script src="https://cdn.neikiri.dev/neiki-assistant/1.0.0/neiki-assistant.min.js"></script>For local development, open demo/index.html through a local server because the source module loads CSS with fetch().
🎨 Optional Custom Styling
The widget includes default styles automatically. You can customize it with CSS custom properties on the element:
neiki-assistant {
--neiki-accent: #10b981;
--neiki-bg: #ffffff;
--neiki-panel: #ffffff;
--neiki-text: #111827;
--neiki-user-bg: #10b981;
--neiki-radius: 20px;
--neiki-font: Inter, system-ui, sans-serif;
--neiki-z-index: 2147483000;
}🧩 Component API
Attributes
| Attribute | Default | Description |
| --- | --- | --- |
| api | empty | Backend endpoint that receives chat requests. |
| title | localized | Header title. |
| subtitle | localized | Header subtitle. |
| welcome | localized | Initial assistant message. |
| placeholder | localized | Composer placeholder. |
| language | browser language | en or cs. Falls back to English. |
| theme | auto | light, dark or auto. |
| accent | #2563eb | Primary brand color. |
| position | bottom-right | bottom-right or bottom-left. |
| storage-key | current path | Key suffix for localStorage persistence. |
| max-history | 40 | Maximum stored messages per conversation. |
| open | absent | Opens the widget when present. |
Methods
| Method | Description |
| --- | --- |
| open() | Opens the chat window. |
| close() | Closes the chat window. |
| toggle() | Toggles the chat window. |
| clear() | Starts a new conversation, archiving the current one to history if it has messages. |
| sendMessage(text) | Sends a message programmatically. |
Events
| Event | Description |
| --- | --- |
| neiki:message | Fired after a reply is received. Includes event.detail.messages. |
| neiki:clear | Fired when a new conversation is started. |
const assistant = document.querySelector('neiki-assistant');
assistant.open();
assistant.sendMessage('How do I install this widget?');
assistant.addEventListener('neiki:message', (event) => {
console.log(event.detail.messages);
});
assistant.addEventListener('neiki:clear', () => {
console.log('Started a new conversation');
});🌐 Backend Integration
The browser sends a POST request to the configured api endpoint:
{
"messages": [
{ "role": "assistant", "content": "Hi, how can I help you today?" },
{ "role": "user", "content": "Hello" }
],
"locale": "en"
}Return JSON:
{ "reply": "Hello from your backend." }Or stream server-sent chunks:
data: {"content":"Hello "}
data: {"content":"from streaming."}
data: [DONE]The frontend does not know or store API keys. Your backend can use OpenAI, OpenRouter, Ollama, Local AI or any custom provider.
💡 Usage Examples
Custom branding
<neiki-assistant
accent="#10b981"
theme="dark"
title="Ask Acme"
subtitle="Product assistant">
</neiki-assistant>Czech localization
<neiki-assistant
api="/api/chat"
language="cs"
welcome="Dobrý den, jak vám dnes můžu pomoci?">
</neiki-assistant>Opened by default, custom storage key
<neiki-assistant
api="/api/chat"
storage-key="support-widget"
open>
</neiki-assistant>🌍 Localization
Translations live in src/i18n/. To add another language to the CDN build, create one new translation file with the same keys as en.js. The build script automatically includes every .js locale file in that directory.
🛠️ Build
The repository keeps source files in src/ and demo files in demo/. The existing dist/ directory is generated manually.
Run:
python minify.pyThe script writes:
dist/neiki-assistant.min.jsdist/neiki-assistant.min.css
The JavaScript bundle contains the CSS, so end users only need the JS file.
♿ Accessibility & UX
- Keyboard accessible controls with visible focus states.
- ARIA roles and labels on the dialog, log and icon buttons.
aria-livemessage log announces new replies to assistive technology.- Reduced motion support disables transitions and animations when requested.
- Shadow DOM isolation prevents style conflicts with host pages.
🔒 Security Notes
- Never put provider API keys in the widget.
- Assistant and user content is escaped before markdown formatting.
- Links are restricted to safe URL schemes.
- Shadow DOM reduces host-page CSS conflicts.
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
👨💻 Author
neikiri GitHub: https://github.com/neikiri
📬 Contact
📧 Email: [email protected]
