Spaces:
Runtime error
Frontend Architecture
Last Updated: 2026-03-08
Two Products, Two Different Tools
The project has two distinct frontend surfaces with different constraints:
| Surface | Tool | Why |
|---|---|---|
| Chatbot widget | Preact + Shadow DOM | Embeddable, 3KB, no host-site conflicts |
| Admin panel | React (Vite + shadcn/ui) | Standalone SaaS, rich UI ecosystem needed |
Chatbot Widget β Preact + Shadow DOM
Why Not React
The widget gets embedded in clients' websites via a <script> tag. If the host site also uses React (a common case), two React instances on the same page cause conflicts β state, events, and CSS bleed between them. React has no built-in isolation mechanism.
Why Preact
- 3KB gzipped (React is ~45KB). Third-party scripts must be small.
- 100% React-compatible API β same
useState,useEffect, JSX, component model. Writing Preact IS writing React syntax. - Bundled inline (IIFE format) β no shared global. Zero conflict with host's React, Vue, Angular, jQuery, or any framework.
- Real-world data: a widget case study went from 36KB (React) β 5.9KB (Preact) with identical functionality.
Why Shadow DOM
Shadow DOM is a native browser API that creates a fully isolated DOM tree:
- Host site CSS cannot leak into the widget
- Widget CSS cannot leak into the host site
- Browser support: 96%+ globally
Combined with Preact, the widget is self-contained β paste one <script> tag on any site (WordPress, Flask, Vue, plain HTML, Shopify, Webflow) and it works.
Packaging
- Build tool: Vite (outputs IIFE bundle)
- Output: single JS file, self-executing when loaded
- Shadow root attached to a custom element (
<smart-chatbot>)
Known Caveats
1. Content Security Policy (CSP)
Security-hardened sites (banks, enterprise SaaS) may block external scripts via HTTP headers. Shadow DOM cannot override CSP. Fix: client adds your domain to their script-src whitelist (one line of config on their end). Typical SME clients (restaurants, shops, law firms) never have strict CSP.
2. z-index stacking context
The widget container lives in the host page's regular DOM. If the host page applies transform, filter, or will-change on a parent element, it creates a stacking context that can render the widget behind page elements. Fix: offer an iframe fallback mode (total isolation) for clients who report this issue.
3. Mobile apps (Kotlin / Java / Swift) These load the widget via WebView (renders a URL). Whether the widget is Preact or React is completely invisible to native code β WebView just needs a URL. No special changes needed for mobile integration.
Admin Panel β React (Vite + shadcn/ui)
Why React (not Vue or Svelte)
The admin panel is a standalone SaaS web app (not embedded anywhere). Different constraints apply:
- Ecosystem: Complex admin UIs need data tables, file uploaders, date pickers, charts. React has the largest component ecosystem β everything is already built.
- shadcn/ui: Copy-paste component library built on Radix UI primitives + Tailwind. Components are owned (not npm dependencies), fully customizable. Best fit for a branded admin panel.
- Career value: Admin panel work is visible in a portfolio. React is the market standard for SaaS dashboards.
- Vue 3 has a gentler learning curve but a smaller ecosystem. Svelte has great performance but ~10x fewer enterprise components. Neither is worth the tradeoff for a complex admin surface.
Deployment
- Separate repo from the FastAPI backend
- Deployed independently (Netlify / Vercel)
- Connects to FastAPI via REST API (CORS configured per-tenant)
- Build: Vite
Onboarding flow
Monireach provisions a new client β gives them the admin panel URL + API key β owner registers and starts configuring β clicks "Publish" when ready β widget on their site goes live.
Scope (Step 10)
- System prompt / persona editor per tenant
- Knowledge base CRUD (upload, edit, delete documents)
- Theme/branding configurator (colors, fonts, widget position, bot name, logo, avatar)
- Go Live toggle:
is_activeflag β widget inactive until owner publishes; returns "not available" state to end users while inactive - Test mode: owner chats with bot privately before publishing (
mode: "test" | "live"flag β only owner sees it) - Conversation history viewer
- Dashboard: message volume, response quality scores, feedback (thumbs up/down), top queries, RAG failure detection
- Validation mode toggle (
async|sync) per tenant - LLM provider config (per-tenant API key, provider selection)
- Auth: Google OAuth + 2FA (authenticator app) for SME admins
- Reference UX: ADA Support admin panel β streamlined for SMEs + Khmer market, not a 1:1 clone
Future scope (post Step 10)
- Handoff to live agent β escalation when chatbot can't answer; routes conversation to human agent in real time; requires presence/availability logic and notification (email, Telegram, etc.)
- Messaging platform integration β same chatbot on Telegram, WhatsApp, and other platforms; all RAG/prompt/KB logic identical, only I/O channel changes; one config drives both website widget and messaging apps simultaneously
Preact = React for Learning Purposes
Since Preact's API is identical to React:
- Building the widget in Preact teaches React syntax
- Building the admin panel in React reinforces the same patterns
- Both projects together = legitimate React/Preact experience to discuss in interviews
For AI Engineering interviews, depth on React internals is not expected. Ability to build a component-based UI and discuss state management patterns is sufficient.