# RagStack Chat Component AI chat with source attribution for **any web framework**. Integrates with AWS Bedrock Knowledge Base. ## Quick Start - Web Component (Any Framework) Use the chat in Vue, Angular, Svelte, or vanilla JavaScript: ```html ``` **Get CDN URL:** Dashboard → Chat tab → Embed Chat Widget section ## Dashboard Chat Tab The Chat tab in the admin dashboard provides: ### System Prompt Editor Customize the AI assistant's behavior by editing the system prompt. Changes apply immediately to new conversations. **Location:** Chat tab → System Prompt (expandable section) ### Embed Code Generator Get ready-to-use embed code with your CDN URL pre-filled: - **Basic (Public):** For unauthenticated access - **Authenticated:** Includes user-id and user-token attributes with example JavaScript **Location:** Chat tab → Embed Chat Widget (expandable section) ## Quick Start - React Component For React applications: ```bash npm install @ragstack/ragstack-chat ``` ```tsx import { ChatWithSources } from '@ragstack/ragstack-chat'; export function App() { return ( ); } ``` ## Configuration ### Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `conversationId` | string (UUID) | auto-generated | Unique conversation ID (must be a valid UUID v4; auto-generated if omitted or invalid) | | `headerText` | string | `"Document Q&A"` | Header title | | `headerSubtitle` | string | `"Ask questions about your documents"` | Header subtitle | | `inputPlaceholder` | string | `"Ask a question..."` | Input field placeholder | | `showSources` | boolean | `true` | Show/hide sources | | `maxWidth` | string | `"100%"` | Component width | | `userId` | string \| null | `null` | User ID for authenticated mode | | `userToken` | string \| null | `null` | Auth token for authenticated mode | | `className` | string | - | Additional CSS class | | `onSendMessage` | function | - | Callback when user sends message | | `onResponseReceived` | function | - | Callback when AI responds | ### Callbacks ```tsx // When user sends a message onSendMessage={(message: string, conversationId: string) => { console.log(`${conversationId}: ${message}`); }} // When AI responds onResponseReceived={(response: ChatMessage) => { console.log('Response:', response.content); console.log('Sources:', response.sources); }} ``` ## Source Citations ### Collapsible Sources Source citations appear below each AI response in a collapsible UI: - **Default state:** Collapsed (clean UI) - **Expand/collapse:** Click "Show/Hide" button - **Persistence:** State saved in sessionStorage (persists on page refresh) - **Accessibility:** Keyboard navigable (Tab + Enter), screen reader support ```tsx // Example document source { title: "financial-report-2024.pdf", location: "chunk-005", snippet: "Q4 revenue was $2.3M...", documentUrl: "https://s3.amazonaws.com/...", // Optional documentAccessAllowed: true // Configuration flag } // Example media source (video/audio) { title: "team-meeting.mp4", location: "1:30-2:00", // Timestamp range snippet: "We discussed the Q4 targets...", documentUrl: "https://s3.amazonaws.com/...#t=90,120", // URL with timestamp fragment isMedia: true, mediaType: "video", // "video" or "audio" timestampStart: 90, // seconds timestampEnd: 120, speaker: "speaker_0" // When diarization enabled } ``` ### Document Downloads When `chat_allow_document_access` is enabled (admin UI -> Configuration): - **"View Document" links** appear in source citations - **Presigned S3 URLs** for original uploaded files (not vector chunks) - **1-hour expiry** for security - **Read-only access** (no modification) **User experience:** 1. User sends query -> AI responds with sources 2. User expands sources -> sees snippets + "View Document" links 3. User clicks link -> original PDF/image/doc downloads 4. URL expires after 1 hour **Admin controls:** - Toggle on/off in real-time (no redeployment) - Changes take effect on the next Lambda invocation (request-scoped cache) ### Media Sources (Video/Audio) When sources come from video or audio files: - **Timestamp display:** Shows time range (e.g., "1:30-2:00") - **Click to play:** Opens inline player at that timestamp - **Speaker label:** Shows speaker ID when diarization is enabled - **Inline player:** HTML5 video/audio player embedded in source citation **URL format:** Presigned S3 URLs include `#t=start,end` media fragment for automatic seeking. **Player features:** - Play/pause controls - Seek bar - Volume control - Compact inline display (max 400px width for video) ### Accessibility Features - **Keyboard navigation:** Tab to navigate, Enter/Space to activate - **Screen reader support:** ARIA labels, state announcements - **Focus indicators:** Visible focus outlines on all interactive elements - **Semantic HTML:** `` elements (not ``) ## Styling The widget is fully customizable via CSS variables. Override any variable on the `ragstack-chat` element or a parent container. ### Quick Example ```css ragstack-chat { --chat-color-user-bg: #7c3aed; --chat-color-source-accent: #7c3aed; --chat-font-family: 'Inter', sans-serif; } ``` ### CSS Variables Reference #### Colors | Variable | Default (Light) | Default (Dark) | shadcn/ui Equivalent | |----------|-----------------|----------------|----------------------| | `--chat-color-bg` | `#ffffff` | `#1a1a1a` | `--background` | | `--chat-color-bg-secondary` | `#f5f5f5` | `#2a2a2a` | `--secondary` | | `--chat-color-text` | `#1a1a1a` | `#ffffff` | `--foreground` | | `--chat-color-text-secondary` | `#666666` | `#999999` | `--muted-foreground` | | `--chat-color-border` | `#d5d5d5` | `#333333` | `--border` | | `--chat-color-border-light` | `#e3e3e3` | `#2a2a2a` | `--border` (lighter) | | `--chat-color-primary` | `#0056b3` | `#0056b3` | `--primary` | | `--chat-color-user-bg` | `#0972d3` | `#0972d3` | `--primary` | | `--chat-color-user-text` | `#ffffff` | `#ffffff` | `--primary-foreground` | | `--chat-color-assistant-bg` | `#f5f5f5` | `#2a2a2a` | `--muted` | | `--chat-color-assistant-text` | `#1a1a1a` | `#ffffff` | `--muted-foreground` | | `--chat-color-source-bg` | `#f8f9fa` | `#252525` | `--card` | | `--chat-color-source-border` | `#d5d5d5` | `#333333` | `--border` | | `--chat-color-source-accent` | `#0972d3` | `#539fe5` | `--accent` | #### Spacing | Variable | Default | Description | |----------|---------|-------------| | `--chat-spacing-xs` | `4px` | Extra small gaps | | `--chat-spacing-sm` | `8px` | Small gaps, button padding | | `--chat-spacing-md` | `12px` | Medium gaps, input padding | | `--chat-spacing-lg` | `16px` | Large gaps, section padding | | `--chat-spacing-xl` | `20px` | Extra large gaps | | `--chat-spacing-xxl` | `24px` | Container padding | #### Border Radius | Variable | Default | shadcn/ui Equivalent | |----------|---------|----------------------| | `--chat-radius-sm` | `2px` | `--radius` (sm) | | `--chat-radius-md` | `4px` | `--radius` | | `--chat-radius-lg` | `8px` | `--radius` (lg) | #### Typography | Variable | Default | Description | |----------|---------|-------------| | `--chat-font-family` | System fonts | Font stack | | `--chat-font-size-xs` | `12px` | Timestamps, labels | | `--chat-font-size-sm` | `13px` | Secondary text | | `--chat-font-size-base` | `14px` | Body text | | `--chat-font-size-lg` | `16px` | Headers | | `--chat-font-size-xl` | `18px` | Large headers | | `--chat-line-height-tight` | `1.4` | Compact text | | `--chat-line-height-normal` | `1.5` | Body text | | `--chat-line-height-relaxed` | `1.6` | Readable paragraphs | #### Transitions | Variable | Default | Description | |----------|---------|-------------| | `--chat-transition-fast` | `100ms ease-in-out` | Hover states | | `--chat-transition-normal` | `200ms ease-in-out` | UI changes | ### HTML Attributes Configure the widget via HTML attributes: | Attribute | Type | Default | Description | |-----------|------|---------|-------------| | `conversation-id` | string (UUID) | auto-generated | Unique conversation identifier (must be UUID v4; auto-generated if omitted or invalid) | | `header-text` | string | `"Document Q&A"` | Header title text | | `header-subtitle` | string | `"Ask questions about your documents"` | Subtitle below header | | `input-placeholder` | string | `"Ask a question..."` | Input field placeholder | | `show-sources` | boolean | `true` | Show/hide source citations | | `max-width` | string | `"100%"` | Component max width | | `user-id` | string | - | User ID for authenticated mode | | `user-token` | string | - | Auth token for authenticated mode | | `background-color` | string | - | Background color (e.g., `"#ffffff"`) | | `text-color` | string | - | Text color (e.g., `"#1a1a1a"`) | ### Full Customization Example ```html ``` ### CSS Classes ```tsx ``` ## Web Components Use the component in any framework via Web Components: ```html ``` ### Framework Examples **Vue 3:** ```vue ``` **Angular:** ```typescript import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import '@ragstack/ragstack-chat/wc'; @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule {} ``` **Svelte:** ```svelte ``` ## Backend Setup The component requires: 1. **SAM deployment** - Creates Bedrock Knowledge Base, Cognito User Pool, and AppSync GraphQL API 2. **Knowledge Base ID** - From SAM outputs, configured in web component build 3. **AppSync GraphQL** - Query endpoint injected during build ## Troubleshooting **Component doesn't render:** - Check browser console for errors - Verify CDN URL is correct **"No response from API":** - Verify SAM deployment completed successfully - Check GraphQL endpoint is configured - Verify Bedrock Knowledge Base has content **Styling conflicts:** - Check CSS specificity - Inspect in DevTools - Use `!important` if needed ## Types ### ChatMessage ```typescript interface ChatMessage { role: 'user' | 'assistant'; content: string; sources?: Source[]; timestamp: string; } ``` ### Source ```typescript interface Source { title: string; // Document filename location: string; // Page, offset, or timestamp range (e.g., "1:30-2:00") snippet: string; // Quote // Media-specific fields (optional) isMedia?: boolean; // true for video/audio sources mediaType?: 'video' | 'audio'; timestampStart?: number; // seconds timestampEnd?: number; // seconds speaker?: string; // speaker ID when diarization enabled } ``` ## Related Documentation - [Architecture](ARCHITECTURE.md) - System design - [Development](DEVELOPMENT.md) - Local dev - [Configuration](CONFIGURATION.md) - Runtime settings - [Troubleshooting](TROUBLESHOOTING.md) - Common issues