vanilla-agent 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -359,6 +359,252 @@ The script build exposes a `window.AgentWidget` global with `initAgentWidget()`
359
359
  - `window.AgentWidget.markdownPostprocessor()` - Markdown postprocessor
360
360
  - `window.AgentWidget.directivePostprocessor()` - Directive postprocessor
361
361
 
362
+ ### React Framework Integration
363
+
364
+ The widget is fully compatible with React frameworks. Use the ESM imports to integrate it as a client component.
365
+
366
+ #### Framework Compatibility
367
+
368
+ | Framework | Compatible | Implementation Notes |
369
+ |-----------|------------|---------------------|
370
+ | **Vite** | ✅ Yes | No special requirements - works out of the box |
371
+ | **Create React App** | ✅ Yes | No special requirements - works out of the box |
372
+ | **Next.js** | ✅ Yes | Requires `'use client'` directive (App Router) |
373
+ | **Remix** | ✅ Yes | Use dynamic import or `useEffect` guard for SSR |
374
+ | **Gatsby** | ✅ Yes | Use in `wrapRootElement` or check `typeof window !== 'undefined'` |
375
+ | **Astro** | ✅ Yes | Use `client:load` or `client:only="react"` directive |
376
+
377
+ #### Quick Start with Vite or Create React App
378
+
379
+ For client-side-only React frameworks (Vite, CRA), create a component:
380
+
381
+ ```typescript
382
+ // src/components/ChatWidget.tsx
383
+ import { useEffect } from 'react';
384
+ import 'vanilla-agent/widget.css';
385
+ import { initAgentWidget, markdownPostprocessor } from 'vanilla-agent';
386
+ import type { AgentWidgetInitHandle } from 'vanilla-agent';
387
+
388
+ export function ChatWidget() {
389
+ useEffect(() => {
390
+ let handle: AgentWidgetInitHandle | null = null;
391
+
392
+ handle = initAgentWidget({
393
+ target: 'body',
394
+ config: {
395
+ apiUrl: "/api/chat/dispatch",
396
+ theme: {
397
+ primary: "#111827",
398
+ accent: "#1d4ed8",
399
+ },
400
+ launcher: {
401
+ enabled: true,
402
+ title: "Chat Assistant",
403
+ subtitle: "Here to help you get answers fast"
404
+ },
405
+ postprocessMessage: ({ text }) => markdownPostprocessor(text)
406
+ }
407
+ });
408
+
409
+ // Cleanup on unmount
410
+ return () => {
411
+ if (handle) {
412
+ handle.destroy();
413
+ }
414
+ };
415
+ }, []);
416
+
417
+ return null; // Widget injects itself into the DOM
418
+ }
419
+ ```
420
+
421
+ Then use it in your app:
422
+
423
+ ```typescript
424
+ // src/App.tsx
425
+ import { ChatWidget } from './components/ChatWidget';
426
+
427
+ function App() {
428
+ return (
429
+ <div>
430
+ {/* Your app content */}
431
+ <ChatWidget />
432
+ </div>
433
+ );
434
+ }
435
+
436
+ export default App;
437
+ ```
438
+
439
+ #### Next.js Integration
440
+
441
+ For Next.js App Router, add the `'use client'` directive:
442
+
443
+ ```typescript
444
+ // components/ChatWidget.tsx
445
+ 'use client';
446
+
447
+ import { useEffect } from 'react';
448
+ import 'vanilla-agent/widget.css';
449
+ import { initAgentWidget, markdownPostprocessor } from 'vanilla-agent';
450
+ import type { AgentWidgetInitHandle } from 'vanilla-agent';
451
+
452
+ export function ChatWidget() {
453
+ useEffect(() => {
454
+ let handle: AgentWidgetInitHandle | null = null;
455
+
456
+ handle = initAgentWidget({
457
+ target: 'body',
458
+ config: {
459
+ apiUrl: "/api/chat/dispatch",
460
+ launcher: {
461
+ enabled: true,
462
+ title: "Chat Assistant",
463
+ },
464
+ postprocessMessage: ({ text }) => markdownPostprocessor(text)
465
+ }
466
+ });
467
+
468
+ return () => {
469
+ if (handle) {
470
+ handle.destroy();
471
+ }
472
+ };
473
+ }, []);
474
+
475
+ return null;
476
+ }
477
+ ```
478
+
479
+ Use it in your layout or page:
480
+
481
+ ```typescript
482
+ // app/layout.tsx
483
+ import { ChatWidget } from '@/components/ChatWidget';
484
+
485
+ export default function RootLayout({ children }) {
486
+ return (
487
+ <html lang="en">
488
+ <body>
489
+ {children}
490
+ <ChatWidget />
491
+ </body>
492
+ </html>
493
+ );
494
+ }
495
+ ```
496
+
497
+ **Alternative: Dynamic Import (SSR-Safe)**
498
+
499
+ If you encounter SSR issues, use Next.js dynamic imports:
500
+
501
+ ```typescript
502
+ // app/layout.tsx
503
+ import dynamic from 'next/dynamic';
504
+
505
+ const ChatWidget = dynamic(
506
+ () => import('@/components/ChatWidget').then(mod => mod.ChatWidget),
507
+ { ssr: false }
508
+ );
509
+
510
+ export default function RootLayout({ children }) {
511
+ return (
512
+ <html lang="en">
513
+ <body>
514
+ {children}
515
+ <ChatWidget />
516
+ </body>
517
+ </html>
518
+ );
519
+ }
520
+ ```
521
+
522
+ #### Remix Integration
523
+
524
+ For Remix, guard the widget initialization with a client-side check:
525
+
526
+ ```typescript
527
+ // app/components/ChatWidget.tsx
528
+ import { useEffect, useState } from 'react';
529
+
530
+ export function ChatWidget() {
531
+ const [mounted, setMounted] = useState(false);
532
+
533
+ useEffect(() => {
534
+ setMounted(true);
535
+
536
+ // Dynamic import to avoid SSR issues
537
+ import('vanilla-agent/widget.css');
538
+ import('vanilla-agent').then(({ initAgentWidget, markdownPostprocessor }) => {
539
+ const handle = initAgentWidget({
540
+ target: 'body',
541
+ config: {
542
+ apiUrl: "/api/chat/dispatch",
543
+ launcher: { enabled: true },
544
+ postprocessMessage: ({ text }) => markdownPostprocessor(text)
545
+ }
546
+ });
547
+
548
+ return () => handle?.destroy();
549
+ });
550
+ }, []);
551
+
552
+ if (!mounted) return null;
553
+ return null;
554
+ }
555
+ ```
556
+
557
+ #### Gatsby Integration
558
+
559
+ Use Gatsby's `wrapRootElement` API:
560
+
561
+ ```typescript
562
+ // gatsby-browser.js
563
+ import { ChatWidget } from './src/components/ChatWidget';
564
+
565
+ export const wrapRootElement = ({ element }) => (
566
+ <>
567
+ {element}
568
+ <ChatWidget />
569
+ </>
570
+ );
571
+ ```
572
+
573
+ #### Astro Integration
574
+
575
+ Use Astro's client directives with React islands:
576
+
577
+ ```astro
578
+ ---
579
+ // src/components/ChatWidget.astro
580
+ import { ChatWidget } from './ChatWidget.tsx';
581
+ ---
582
+
583
+ <ChatWidget client:load />
584
+ ```
585
+
586
+ #### Using the Theme Configurator
587
+
588
+ For easy configuration generation, use the [Theme Configurator](https://github.com/becomevocal/chaty/tree/main/examples/embedded-app) which includes a "React (Client Component)" export option. It generates a complete React component with your custom theme, launcher settings, and all configuration options.
589
+
590
+ #### Installation
591
+
592
+ ```bash
593
+ npm install vanilla-agent
594
+ # or
595
+ pnpm add vanilla-agent
596
+ # or
597
+ yarn add vanilla-agent
598
+ ```
599
+
600
+ #### Key Considerations
601
+
602
+ 1. **CSS Import**: The CSS import (`import 'vanilla-agent/widget.css'`) works natively with all modern React build tools
603
+ 2. **Client-Side Only**: The widget manipulates the DOM, so it must run client-side only
604
+ 3. **Cleanup**: Always call `handle.destroy()` in the cleanup function to prevent memory leaks
605
+ 4. **API Routes**: Ensure your `apiUrl` points to a valid backend endpoint
606
+ 5. **TypeScript Support**: Full TypeScript definitions are included for all exports
607
+
362
608
  ### Using default configuration
363
609
 
364
610
  The package exports a complete default configuration that you can use as a base: