@retrivora-ai/rag-engine 0.1.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.
Files changed (61) hide show
  1. package/.env.example +77 -0
  2. package/README.md +149 -0
  3. package/dist/DocumentChunker-BUrIrcPk.d.mts +43 -0
  4. package/dist/DocumentChunker-BUrIrcPk.d.ts +43 -0
  5. package/dist/RAGPipeline-BmkIv1HD.d.mts +298 -0
  6. package/dist/RAGPipeline-BmkIv1HD.d.ts +298 -0
  7. package/dist/chunk-NCG2JKXB.mjs +1254 -0
  8. package/dist/chunk-ZPXLQR5Q.mjs +67 -0
  9. package/dist/handlers/index.d.mts +68 -0
  10. package/dist/handlers/index.d.ts +68 -0
  11. package/dist/handlers/index.js +1319 -0
  12. package/dist/handlers/index.mjs +13 -0
  13. package/dist/index.d.mts +93 -0
  14. package/dist/index.d.ts +93 -0
  15. package/dist/index.js +612 -0
  16. package/dist/index.mjs +551 -0
  17. package/dist/server.d.mts +211 -0
  18. package/dist/server.d.ts +211 -0
  19. package/dist/server.js +1457 -0
  20. package/dist/server.mjs +148 -0
  21. package/package.json +90 -0
  22. package/src/app/api/chat/route.ts +4 -0
  23. package/src/app/api/health/route.ts +4 -0
  24. package/src/app/api/ingest/route.ts +26 -0
  25. package/src/app/favicon.ico +0 -0
  26. package/src/app/globals.css +163 -0
  27. package/src/app/layout.tsx +35 -0
  28. package/src/app/page.tsx +506 -0
  29. package/src/components/ChatWidget.tsx +91 -0
  30. package/src/components/ChatWindow.tsx +248 -0
  31. package/src/components/ConfigProvider.tsx +56 -0
  32. package/src/components/MessageBubble.tsx +99 -0
  33. package/src/components/SourceCard.tsx +66 -0
  34. package/src/components/ThemeProvider.tsx +8 -0
  35. package/src/components/ThemeToggle.tsx +29 -0
  36. package/src/config/RagConfig.ts +159 -0
  37. package/src/config/UniversalProfiles.ts +83 -0
  38. package/src/config/serverConfig.ts +142 -0
  39. package/src/handlers/index.ts +202 -0
  40. package/src/hooks/useHydrated.ts +13 -0
  41. package/src/hooks/useRagChat.ts +167 -0
  42. package/src/hooks/useStoredMessages.ts +53 -0
  43. package/src/index.ts +27 -0
  44. package/src/llm/ILLMProvider.ts +60 -0
  45. package/src/llm/LLMFactory.ts +54 -0
  46. package/src/llm/providers/AnthropicProvider.ts +87 -0
  47. package/src/llm/providers/OllamaProvider.ts +102 -0
  48. package/src/llm/providers/OpenAIProvider.ts +92 -0
  49. package/src/llm/providers/UniversalLLMAdapter.ts +154 -0
  50. package/src/rag/DocumentChunker.ts +105 -0
  51. package/src/rag/RAGPipeline.ts +196 -0
  52. package/src/server.ts +30 -0
  53. package/src/types/pdf-parse.d.ts +13 -0
  54. package/src/utils/DocumentParser.ts +75 -0
  55. package/src/utils/templateUtils.ts +78 -0
  56. package/src/vectordb/IVectorDB.ts +75 -0
  57. package/src/vectordb/VectorDBFactory.ts +41 -0
  58. package/src/vectordb/adapters/MongoDbAdapter.ts +175 -0
  59. package/src/vectordb/adapters/PgVectorAdapter.ts +159 -0
  60. package/src/vectordb/adapters/PineconeAdapter.ts +115 -0
  61. package/src/vectordb/adapters/UniversalVectorDBAdapter.ts +177 -0
@@ -0,0 +1,506 @@
1
+ 'use client';
2
+
3
+ import React from 'react';
4
+ import {
5
+ Zap,
6
+ GitBranch,
7
+ HeartPulse,
8
+ Database,
9
+ Layers,
10
+ Bot,
11
+ Brain,
12
+ Rabbit,
13
+ FileText,
14
+ Search,
15
+ Puzzle,
16
+ MessageSquare,
17
+ ExternalLink,
18
+ Package,
19
+ } from 'lucide-react';
20
+ import { ChatWindow } from '@/components/ChatWindow';
21
+ import { ChatWidget } from '@/components/ChatWidget';
22
+ import { useConfig } from '@/components/ConfigProvider';
23
+ import { ThemeToggle } from '@/components/ThemeToggle';
24
+ import { Check, Copy } from 'lucide-react';
25
+ import pkg from '../../package.json';
26
+
27
+ /**
28
+ * Custom hook for copy-to-clipboard functionality
29
+ */
30
+ function useCopyToClipboard() {
31
+ const [copied, setCopied] = React.useState<string | null>(null);
32
+
33
+ const copy = (text: string, id: string) => {
34
+ navigator.clipboard.writeText(text);
35
+ setCopied(id);
36
+ setTimeout(() => setCopied(null), 2000);
37
+ };
38
+
39
+ return { copied, copy };
40
+ }
41
+
42
+ // ── Feature pills data ────────────────────────────────────────────────────────
43
+ const FEATURE_PILLS = [
44
+ { Icon: Database, label: 'MongoDB' },
45
+ { Icon: Layers, label: 'PostgreSQL' },
46
+ { Icon: Zap, label: 'Pinecone' },
47
+ { Icon: Bot, label: 'Claude' },
48
+ { Icon: Brain, label: 'Gemini' },
49
+ { Icon: MessageSquare, label: 'Copilot' },
50
+ { Icon: Rabbit, label: 'Ollama' },
51
+ { Icon: Package, label: 'ChromaDB' },
52
+ ] as const;
53
+
54
+ // ── Pipeline step cards ───────────────────────────────────────────────────────
55
+ const PIPELINE_STEPS = [
56
+ {
57
+ step: '01',
58
+ Icon: FileText,
59
+ title: 'Ingest',
60
+ desc: 'Universal support for PDF, DOCX, CSV, and JSON. Documents are parsed, chunked, and embedded.',
61
+ colors: { from: '#10b981', to: '#14b8a6' }, // Emerald -> Teal
62
+ },
63
+ {
64
+ step: '02',
65
+ Icon: Search,
66
+ title: 'Retrieve',
67
+ desc: 'Queries are converted to vectors. Semantic search finds context across any configured Vector DB.',
68
+ colors: { from: '#14b8a6', to: '#06b6d4' }, // Teal -> Cyan
69
+ },
70
+ {
71
+ step: '03',
72
+ Icon: Puzzle,
73
+ title: 'Augment',
74
+ desc: 'Retrieved context is injected into the LLM prompt with namespaced project isolation.',
75
+ colors: { from: '#06b6d4', to: '#3b82f6' }, // Cyan -> Blue
76
+ },
77
+ {
78
+ step: '04',
79
+ Icon: MessageSquare,
80
+ title: 'Generate',
81
+ desc: 'Providers like OpenAI, Anthropic, or Gemini produce grounded, source-cited responses.',
82
+ colors: { from: '#3b82f6', to: '#6366f1' }, // Blue -> Indigo
83
+ },
84
+ ] as const;
85
+
86
+ export default function HomePage() {
87
+ const { ui } = useConfig();
88
+ const { copied, copy } = useCopyToClipboard();
89
+
90
+ return (
91
+ <main className="min-h-screen bg-slate-50 dark:bg-[#080811] relative transition-colors duration-300">
92
+ {/* ── Ambient gradient background ── */}
93
+ <div className="absolute inset-0 overflow-hidden pointer-events-none">
94
+ <div
95
+ className="absolute -top-40 -left-40 w-[600px] h-[600px] rounded-full opacity-20 blur-3xl"
96
+ style={{ background: ui.primaryColor }}
97
+ />
98
+ <div
99
+ className="absolute -bottom-40 -right-40 w-[600px] h-[600px] rounded-full opacity-15 blur-3xl"
100
+ style={{ background: ui.accentColor }}
101
+ />
102
+ {/* Grid pattern */}
103
+ <div
104
+ className="absolute inset-0 opacity-[0.05] dark:opacity-[0.03]"
105
+ style={{
106
+ backgroundImage:
107
+ 'linear-gradient(currentColor 1px, transparent 1px), linear-gradient(90deg, currentColor 1px, transparent 1px)',
108
+ backgroundSize: '48px 48px',
109
+ }}
110
+ />
111
+ </div>
112
+
113
+ {/* ── Navbar ── */}
114
+ <nav className="sticky top-0 z-50 flex items-center justify-between px-8 py-5 border-b border-slate-200 dark:border-white/5 bg-white/80 dark:bg-[#080811]/80 backdrop-blur-md">
115
+ <div className="flex items-center gap-3 group cursor-default">
116
+ <div className="relative">
117
+ <div
118
+ className="w-10 h-10 rounded-xl flex items-center justify-center shadow-lg relative z-10 overflow-hidden transition-transform group-hover:scale-110 duration-500"
119
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
120
+ >
121
+ <Zap className="w-5 h-5 text-white animate-pulse" />
122
+ <div className="absolute inset-0 bg-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
123
+ </div>
124
+ {/* Logo Glow */}
125
+ <div
126
+ className="absolute inset-0 blur-lg opacity-40 group-hover:opacity-80 transition-opacity"
127
+ style={{ background: ui.primaryColor }}
128
+ />
129
+ </div>
130
+ <div className="flex flex-col -gap-0.5">
131
+ <span className="font-black text-transparent bg-clip-text text-xl tracking-tight leading-none"
132
+ style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}
133
+ >
134
+ Retrivora&nbsp;AI
135
+ </span>
136
+ <div className="flex items-center gap-1.5">
137
+ <span className="font-bold text-slate-900 dark:text-white text-[10px] tracking-[0.15em] uppercase opacity-70">Accelerator</span>
138
+ <span className="text-[9px] px-1.5 py-0.5 rounded-full bg-slate-100 dark:bg-white/5 text-slate-500 dark:text-white/40 font-mono border border-slate-200/50 dark:border-white/10">v{pkg.version}</span>
139
+ </div>
140
+ </div>
141
+ </div>
142
+
143
+ <div className="flex items-center gap-3">
144
+ <ThemeToggle />
145
+ <a
146
+ href="https://www.npmjs.com/package/@abhinav1201/rag-ai-accelerator"
147
+ target="_blank"
148
+ rel="noreferrer"
149
+ className="text-slate-500 hover:text-[#CB3837] dark:text-white/40 dark:hover:text-[#CB3837] text-sm transition-colors flex items-center gap-1.5"
150
+ >
151
+ <Package className="w-4 h-4" />
152
+ NPM
153
+ </a>
154
+ <a
155
+ href="https://github.com/abhinav1201/ai-accelerator"
156
+ target="_blank"
157
+ rel="noreferrer"
158
+ className="text-slate-500 hover:text-slate-900 dark:text-white/40 dark:hover:text-white/70 text-sm transition-colors flex items-center gap-1.5"
159
+ >
160
+ <GitBranch className="w-4 h-4" />
161
+ GitHub
162
+ </a>
163
+ <a
164
+ href="/api/health"
165
+ target="_blank"
166
+ rel="noreferrer"
167
+ className="px-3 py-1.5 rounded-lg text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:bg-slate-100 dark:hover:bg-white/5 transition-all flex items-center gap-1.5"
168
+ >
169
+ <HeartPulse className="w-3.5 h-3.5" />
170
+ Health
171
+ </a>
172
+ </div>
173
+ </nav>
174
+
175
+ {/* ── Hero + Chat layout ── */}
176
+ <div className="relative z-10 container mx-auto px-6 py-12">
177
+ <div className="grid lg:grid-cols-2 gap-12 items-start">
178
+ {/* Left — Hero copy */}
179
+ <div className="flex flex-col gap-6 pt-4">
180
+ <div
181
+ className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full text-xs font-medium border w-fit"
182
+ style={{
183
+ borderColor: `${ui.primaryColor}40`,
184
+ color: ui.primaryColor,
185
+ background: `${ui.primaryColor}10`,
186
+ }}
187
+ >
188
+ <span className="w-1.5 h-1.5 rounded-full animate-pulse" style={{ background: ui.primaryColor }} />
189
+ Dynamic & Universal Retrivora AI
190
+ </div>
191
+
192
+ <h1 className="text-5xl md:text-7xl font-black text-slate-900 dark:text-white mb-6 tracking-tight">
193
+ The Universal Bridge <br />
194
+ <span
195
+ className="text-transparent bg-clip-text"
196
+ style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}
197
+ >
198
+ for Generative AI
199
+ </span>
200
+ </h1>
201
+ <p className="text-lg md:text-xl text-slate-600 dark:text-white/40 max-w-2xl mx-auto leading-relaxed">
202
+ Retrivora AI is a vendor-agnostic RAG engine that connects any Document to any LLM and Vector Database in minutes.
203
+ </p>
204
+
205
+ {/* Feature pills */}
206
+ <div className="flex flex-wrap gap-3 mt-2">
207
+ {FEATURE_PILLS.map(({ Icon, label }) => (
208
+ <span
209
+ key={label}
210
+ className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 text-sm hover:bg-slate-50 dark:hover:bg-white/8 transition-all cursor-default shadow-sm dark:shadow-none"
211
+ >
212
+ <Icon className="w-3.5 h-3.5" style={{ color: ui.primaryColor }} />
213
+ {label}
214
+ </span>
215
+ ))}
216
+ </div>
217
+
218
+ {/* Stats */}
219
+ <div className="grid grid-cols-3 gap-4 mt-4 pt-4 border-t border-slate-200 dark:border-white/10">
220
+ {[
221
+ { value: '6+', label: 'Vector DBs' },
222
+ { value: '5+', label: 'LLM Providers' },
223
+ { value: 'Universal', label: 'File Parsing' },
224
+ ].map(({ value, label }) => (
225
+ <div key={label} className="text-center">
226
+ <div
227
+ className="text-2xl font-bold bg-clip-text text-transparent"
228
+ style={{ backgroundImage: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
229
+ >
230
+ {value}
231
+ </div>
232
+ <div className="text-slate-500 dark:text-white/40 text-xs mt-0.5">{label}</div>
233
+ </div>
234
+ ))}
235
+ </div>
236
+ </div>
237
+
238
+ {/* Right — Full chat window */}
239
+ <div className="lg:sticky lg:top-6">
240
+ <ChatWindow className="w-full" style={{ height: '620px' } as React.CSSProperties} />
241
+ </div>
242
+ </div>
243
+
244
+ {/* ── Architecture section ── */}
245
+ <div className="mt-24 mb-12">
246
+ <h2 className="text-2xl font-bold text-slate-900 dark:text-white text-center mb-2">The RAG Lifecycle</h2>
247
+ <p className="text-slate-500 dark:text-white/40 text-center text-sm mb-10">
248
+ Automated ingestion, semantic retrieval, and grounded generation
249
+ </p>
250
+
251
+ <div className="relative max-w-5xl mx-auto py-12">
252
+ {/* Center Spine Line */}
253
+ <div className="absolute left-1/2 top-0 bottom-0 w-0.5 bg-slate-200 dark:bg-white/10 -translate-x-1/2 hidden md:block" />
254
+
255
+ <div className="space-y-12 md:space-y-0">
256
+ {PIPELINE_STEPS.map(({ step, Icon, title, desc, colors }, index) => {
257
+ const isLeft = index % 2 === 0;
258
+ return (
259
+ <div
260
+ key={step}
261
+ className={`relative flex flex-col md:flex-row items-center gap-8 cursor-pointer ${isLeft ? 'md:flex-row' : 'md:flex-row-reverse'
262
+ }`}
263
+ >
264
+ {/* Content Card */}
265
+ <div className={`w-full md:w-1/2 relative flex ${isLeft ? 'justify-end' : 'justify-start'}`}>
266
+ {/* Branch Line (Connecting icon to card) */}
267
+ <div className={`absolute top-1/2 -translate-y-1/2 h-0.5 hidden md:block opacity-30 ${isLeft ? '-right-8 w-8' : '-left-8 w-8'}`} style={{ backgroundColor: colors.from }} />
268
+
269
+ <div className="relative p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 hover:bg-slate-50 dark:hover:bg-white/5 transition-all hover:border-slate-300 dark:hover:border-white/20 shadow-sm dark:shadow-none max-w-md text-left overflow-hidden group">
270
+ {/* Dissolved Background Step Number */}
271
+ <div className="absolute -right-2 -bottom-4 text-7xl font-bold opacity-[0.1] dark:opacity-[0.15] pointer-events-none select-none italic group-hover:scale-110 transition-transform duration-500" style={{ color: colors.from }}>
272
+ {step}
273
+ </div>
274
+
275
+ <h3 className="font-semibold text-slate-900 dark:text-white mb-2 text-lg relative z-10 flex items-center gap-2">
276
+ <Icon className="w-5 h-5 opacity-80" style={{ color: colors.from }} />
277
+ {title}
278
+ </h3>
279
+ <p className="text-slate-600 dark:text-white/40 text-sm leading-relaxed relative z-10">{desc}</p>
280
+ </div>
281
+ </div>
282
+
283
+ {/* Center Icon Node */}
284
+ <div
285
+ className="relative z-10 w-12 h-12 rounded-2xl flex items-center justify-center flex-shrink-0 shadow-xl transition-transform hover:scale-110 border-4 border-slate-50 dark:border-[#080811]"
286
+ style={{ background: `linear-gradient(135deg, ${colors.from}, ${colors.to})` }}
287
+ >
288
+ <Icon className="w-6 h-6 text-white" />
289
+ </div>
290
+
291
+ {/* Spacer for the other side */}
292
+ <div className="hidden md:block md:w-1/2" />
293
+ </div>
294
+ );
295
+ })}
296
+ </div>
297
+ </div>
298
+ </div>
299
+
300
+ {/* ── How to Use Section ── */}
301
+ <div className="mt-32 max-w-5xl mx-auto mb-24 relative">
302
+ <div className="text-center mb-16">
303
+ <h2 className="text-3xl font-bold text-slate-900 dark:text-white mb-4">How to Use</h2>
304
+ <p className="text-slate-600 dark:text-white/40 max-w-2xl mx-auto">
305
+ Integrate universal RAG capabilities into your Next.js application with just a few lines of code.
306
+ </p>
307
+ </div>
308
+
309
+ <div className="relative grid gap-12">
310
+ {/* Vertical Connector Line */}
311
+ <div className="absolute left-[44px] top-12 bottom-12 w-0.5 bg-slate-200 dark:bg-white/5 hidden md:block" />
312
+
313
+ {/* Step 1: Install */}
314
+ <div className="relative z-10 group">
315
+ <div className="flex flex-col md:flex-row items-start gap-8 p-8 rounded-3xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/2 backdrop-blur-sm transition-all hover:shadow-2xl hover:shadow-indigo-500/10 overflow-hidden">
316
+ {/* Dissolved Background Step Number */}
317
+ <div className="absolute -right-2 -bottom-6 text-9xl font-bold opacity-[0.08] dark:opacity-[0.12] pointer-events-none select-none italic group-hover:scale-110 transition-transform duration-700" style={{ color: ui.primaryColor }}>
318
+ 01
319
+ </div>
320
+
321
+ <div
322
+ className="w-12 h-12 rounded-2xl flex items-center justify-center text-white font-bold shrink-0 shadow-xl transition-transform group-hover:scale-110 relative z-10"
323
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
324
+ >
325
+ <Package className="w-6 h-6" />
326
+ </div>
327
+ <div className="flex-1 w-full relative z-10">
328
+ <div className="flex items-center justify-between mb-2">
329
+ <h3 className="text-xl font-semibold text-slate-900 dark:text-white">Install the package</h3>
330
+ <span className="text-[10px] font-mono text-slate-400 bg-slate-100 dark:bg-white/5 px-2 py-0.5 rounded">Terminal</span>
331
+ </div>
332
+ <p className="text-slate-600 dark:text-white/40 mb-6 text-sm">Add the Retrivora AI core to your project dependencies.</p>
333
+
334
+ <div className="relative group/code">
335
+ <div className="bg-slate-950 rounded-xl p-5 font-mono text-sm text-indigo-300 border border-white/5 flex items-center justify-between overflow-x-auto shadow-inner">
336
+ <span className="whitespace-nowrap">$ npm install @abhinav1201/rag-ai-accelerator</span>
337
+ <button
338
+ onClick={() => copy('npm install @abhinav1201/rag-ai-accelerator', 'step1')}
339
+ className="ml-4 p-2 rounded-lg bg-white/5 hover:bg-white/10 text-white/50 hover:text-white transition-all flex-shrink-0"
340
+ title="Copy to clipboard"
341
+ >
342
+ {copied === 'step1' ? <Check className="w-4 h-4 text-emerald-400" /> : <Copy className="w-4 h-4" />}
343
+ </button>
344
+ </div>
345
+ </div>
346
+ </div>
347
+ </div>
348
+ </div>
349
+
350
+ {/* Step 2 & 3 Grid */}
351
+ <div className="grid lg:grid-cols-2 gap-8">
352
+ {/* Step 2: Configure UI */}
353
+ <div className="relative z-10 group">
354
+ <div className="h-full flex flex-col p-8 rounded-3xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/2 backdrop-blur-sm transition-all hover:shadow-2xl hover:shadow-indigo-500/10 overflow-hidden">
355
+ {/* Dissolved Background Step Number */}
356
+ <div className="absolute -right-2 -bottom-6 text-8xl font-bold opacity-[0.08] dark:opacity-[0.12] pointer-events-none select-none italic group-hover:scale-110 transition-transform duration-700" style={{ color: ui.primaryColor }}>
357
+ 02
358
+ </div>
359
+
360
+ <div className="flex items-start gap-6 mb-6 relative z-10">
361
+ <div
362
+ className="w-12 h-12 rounded-2xl flex items-center justify-center text-white font-bold shrink-0 shadow-xl transition-transform group-hover:scale-110"
363
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
364
+ >
365
+ <Layers className="w-6 h-6" />
366
+ </div>
367
+ <div>
368
+ <h3 className="text-xl font-semibold text-slate-900 dark:text-white mb-1">Setup UI</h3>
369
+ <p className="text-slate-600 dark:text-white/40 text-xs">Drop the widget into your layout.</p>
370
+ </div>
371
+ </div>
372
+
373
+ <div className="relative flex-1 group/code z-10">
374
+ <div className="absolute top-3 right-3 z-20">
375
+ <button
376
+ onClick={() => copy(`import { ConfigProvider, ChatWidget } from '@abhinav1201/rag-ai-accelerator';\n\n<ConfigProvider config={{ projectId: 'demo' }}>\n {children}\n <ChatWidget position="bottom-right" />\n</ConfigProvider>`, 'step2')}
377
+ className="p-1.5 rounded-md bg-white/5 hover:bg-white/10 text-white/30 hover:text-white transition-all"
378
+ >
379
+ {copied === 'step2' ? <Check className="w-3 h-3 text-emerald-400" /> : <Copy className="w-3 h-3" />}
380
+ </button>
381
+ </div>
382
+ <div className="bg-slate-950 rounded-xl p-4 font-mono text-[11px] text-slate-400 border border-white/5 h-full overflow-x-auto">
383
+ <div className="text-[10px] text-white/20 mb-3 flex items-center gap-1.5 uppercase tracking-widest font-sans">
384
+ <FileText className="w-3 h-3" /> src/app/layout.tsx
385
+ </div>
386
+ <pre className="text-slate-300">
387
+ {`import { ConfigProvider, ChatWidget } from '@abhinav1201/rag-ai-accelerator';
388
+
389
+ <ConfigProvider config={{ projectId: 'demo' }}>
390
+ {children}
391
+ <ChatWidget position="bottom-right" />
392
+ </ConfigProvider>`}
393
+ </pre>
394
+ </div>
395
+ </div>
396
+ </div>
397
+ </div>
398
+
399
+ {/* Step 3: API Handler */}
400
+ <div className="relative z-10 group">
401
+ <div className="h-full flex flex-col p-8 rounded-3xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/2 backdrop-blur-sm transition-all hover:shadow-2xl hover:shadow-indigo-500/10 overflow-hidden">
402
+ {/* Dissolved Background Step Number */}
403
+ <div className="absolute -right-2 -bottom-6 text-8xl font-bold opacity-[0.08] dark:opacity-[0.12] pointer-events-none select-none italic group-hover:scale-110 transition-transform duration-700" style={{ color: ui.primaryColor }}>
404
+ 03
405
+ </div>
406
+
407
+ <div className="flex items-start gap-6 mb-6 relative z-10">
408
+ <div
409
+ className="w-12 h-12 rounded-2xl flex items-center justify-center text-white font-bold shrink-0 shadow-xl transition-transform group-hover:scale-110"
410
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
411
+ >
412
+ <Search className="w-6 h-6" />
413
+ </div>
414
+ <div>
415
+ <h3 className="text-xl font-semibold text-slate-900 dark:text-white mb-1">Mount Routes</h3>
416
+ <p className="text-slate-600 dark:text-white/40 text-xs">Bridge your server to the AI.</p>
417
+ </div>
418
+ </div>
419
+
420
+ <div className="relative flex-1 group/code z-10">
421
+ <div className="absolute top-3 right-3 z-20">
422
+ <button
423
+ onClick={() => copy(`import { createChatHandler, getRagConfig } from '@abhinav1201/rag-ai-accelerator/server';\n\nexport const POST = createChatHandler(getRagConfig());`, 'step3')}
424
+ className="p-1.5 rounded-md bg-white/5 hover:bg-white/10 text-white/30 hover:text-white transition-all"
425
+ >
426
+ {copied === 'step3' ? <Check className="w-3 h-3 text-emerald-400" /> : <Copy className="w-3 h-3" />}
427
+ </button>
428
+ </div>
429
+ <div className="bg-slate-950 rounded-xl p-4 font-mono text-[11px] text-slate-400 border border-white/5 h-full overflow-x-auto">
430
+ <div className="text-[10px] text-white/20 mb-3 flex items-center gap-1.5 uppercase tracking-widest font-sans">
431
+ <FileText className="w-3 h-3" /> api/chat/route.ts
432
+ </div>
433
+ <pre className="text-slate-300">
434
+ {`import { createChatHandler, getRagConfig } from '@abhinav1201/rag-ai-accelerator/server';
435
+
436
+ export const POST = createChatHandler(getRagConfig());`}
437
+ </pre>
438
+ </div>
439
+ </div>
440
+ </div>
441
+ </div>
442
+ </div>
443
+
444
+ {/* Step 4: Environment Variables */}
445
+ <div className="relative z-10 group">
446
+ <div className="flex flex-col md:flex-row items-start gap-8 p-8 rounded-3xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/2 backdrop-blur-sm transition-all hover:shadow-2xl hover:shadow-indigo-500/10 overflow-hidden">
447
+ {/* Dissolved Background Step Number */}
448
+ <div className="absolute -right-2 -bottom-6 text-9xl font-bold opacity-[0.08] dark:opacity-[0.12] pointer-events-none select-none italic group-hover:scale-110 transition-transform duration-700" style={{ color: ui.primaryColor }}>
449
+ 04
450
+ </div>
451
+
452
+ <div
453
+ className="w-12 h-12 rounded-2xl flex items-center justify-center text-white font-bold shrink-0 shadow-xl transition-transform group-hover:scale-110 relative z-10"
454
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
455
+ >
456
+ <Search className="w-6 h-6" />
457
+ </div>
458
+ <div className="flex-1 w-full relative z-10">
459
+ <div className="flex items-center justify-between mb-2">
460
+ <h3 className="text-xl font-semibold text-slate-900 dark:text-white">Configure Environment</h3>
461
+ <span className="text-[10px] font-mono text-slate-400 bg-slate-100 dark:bg-white/5 px-2 py-0.5 rounded">.env.local</span>
462
+ </div>
463
+ <p className="text-slate-600 dark:text-white/40 mb-6 text-sm">
464
+ Essential variables for both <span className="text-slate-900 dark:text-white font-medium">Server (Adapters)</span> and <span className="text-slate-900 dark:text-white font-medium">Client (UI context)</span>.
465
+ </p>
466
+
467
+ <div className="relative group/code">
468
+ <div className="absolute top-3 right-3 z-20">
469
+ <button
470
+ onClick={() => copy(`VECTOR_DB_PROVIDER=universal_rest\nLLM_PROVIDER=openai\nLLM_MODEL=gpt-4o\nNEXT_PUBLIC_UI_TITLE="AI Assistant"`, 'step4')}
471
+ className="p-1.5 rounded-md bg-white/5 hover:bg-white/10 text-white/30 hover:text-white transition-all"
472
+ >
473
+ {copied === 'step4' ? <Check className="w-3 h-3 text-emerald-400" /> : <Copy className="w-3 h-3" />}
474
+ </button>
475
+ </div>
476
+ <div className="bg-slate-950 rounded-xl p-5 font-mono text-sm text-indigo-300 border border-white/5 flex flex-col shadow-inner">
477
+ <span className="text-slate-500 text-xs mb-2"># Core Providers</span>
478
+ <span className="mb-1">VECTOR_DB_PROVIDER=universal_rest</span>
479
+ <span className="mb-4">LLM_PROVIDER=openai</span>
480
+ <span className="text-slate-500 text-xs mb-2"># Client UI (Public)</span>
481
+ <span>NEXT_PUBLIC_UI_TITLE="AI Assistant"</span>
482
+ </div>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ </div>
487
+ </div>
488
+
489
+ <div className="mt-16 text-center">
490
+ <a
491
+ href="https://www.npmjs.com/package/@abhinav1201/rag-ai-accelerator"
492
+ className="inline-flex items-center gap-3 px-8 py-4 rounded-2xl bg-slate-900 dark:bg-white text-white dark:text-slate-900 font-bold hover:scale-[1.02] active:scale-[0.98] transition-all shadow-xl shadow-indigo-500/20"
493
+ >
494
+ <Package className="w-5 h-5" />
495
+ Get Started on NPM
496
+ <ExternalLink className="w-4 h-4" />
497
+ </a>
498
+ </div>
499
+ </div>
500
+ </div>
501
+
502
+ {/* ── Floating widget demo (bottom-right corner) ── */}
503
+ <ChatWidget position="bottom-right" />
504
+ </main>
505
+ );
506
+ }
@@ -0,0 +1,91 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import { MessageSquare, X } from 'lucide-react';
5
+ import { ChatWindow } from './ChatWindow';
6
+ import { useConfig } from './ConfigProvider';
7
+
8
+ interface ChatWidgetProps {
9
+ /** Position of the floating button. Defaults to bottom-right. */
10
+ position?: 'bottom-right' | 'bottom-left';
11
+ }
12
+
13
+ export function ChatWidget({ position = 'bottom-right' }: ChatWidgetProps) {
14
+ const { ui } = useConfig();
15
+ const [isOpen, setIsOpen] = useState(false);
16
+ const [hasUnread, setHasUnread] = useState(false);
17
+
18
+ if (ui.showWidget === false) return null;
19
+
20
+ const positionClass =
21
+ position === 'bottom-left'
22
+ ? 'bottom-6 left-6'
23
+ : 'bottom-6 right-6';
24
+
25
+ const windowPositionClass =
26
+ position === 'bottom-left'
27
+ ? 'bottom-20 left-6'
28
+ : 'bottom-20 right-6';
29
+
30
+ const handleOpen = () => {
31
+ setIsOpen(true);
32
+ setHasUnread(false);
33
+ };
34
+
35
+ return (
36
+ <>
37
+ {/* ── Chat Window (slides up) ── */}
38
+ <div
39
+ className={`fixed z-[99] w-[380px] max-w-[calc(100vw-3rem)] transition-all duration-300 ease-in-out ${windowPositionClass} ${isOpen
40
+ ? 'opacity-100 translate-y-0 pointer-events-auto'
41
+ : 'opacity-0 translate-y-4 pointer-events-none'
42
+ }`}
43
+ style={{ height: '600px', maxHeight: 'calc(100vh - 6rem)' }}
44
+ >
45
+ <ChatWindow
46
+ className="h-full relative z-10"
47
+ showClose
48
+ onClose={() => setIsOpen(false)}
49
+ />
50
+ {/* Pointer (Tail) */}
51
+ <div
52
+ className={`absolute -bottom-1.5 w-4 h-4 rotate-45 border-r border-b border-slate-200 dark:border-white/10 z-0 ${
53
+ ui.visualStyle === 'solid' ? 'bg-white dark:bg-[#0f0f1a]' : 'bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl'
54
+ } ${position === 'bottom-left' ? 'left-5' : 'right-5'}`}
55
+ />
56
+ </div>
57
+
58
+ {/* ── Floating Action Button ── */}
59
+ <button
60
+ onClick={isOpen ? () => setIsOpen(false) : handleOpen}
61
+ className={`fixed z-[100] w-14 h-14 shadow-2xl flex items-center justify-center transition-all duration-300 cursor-pointer hover:scale-110 active:scale-95 ${
62
+ ui.borderRadius === 'full' ? 'rounded-full' : 'rounded-2xl'
63
+ } ${positionClass}`}
64
+ style={{ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }}
65
+ aria-label="Open chat"
66
+ >
67
+ {/* Ripple ring */}
68
+ <span
69
+ className="absolute inset-0 rounded-full animate-ping opacity-20"
70
+ style={{ background: ui.primaryColor }}
71
+ />
72
+
73
+ <span
74
+ className={`transition-transform duration-300 ${isOpen ? 'rotate-90 scale-90' : 'rotate-0 scale-100'}`}
75
+ >
76
+ {isOpen
77
+ ? <X className="w-6 h-6 text-white" />
78
+ : <MessageSquare className="w-6 h-6 text-white" />
79
+ }
80
+ </span>
81
+
82
+ {/* Unread badge */}
83
+ {hasUnread && !isOpen && (
84
+ <span className="absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white">
85
+ 1
86
+ </span>
87
+ )}
88
+ </button>
89
+ </>
90
+ );
91
+ }