@retrivora-ai/rag-engine 0.1.8 → 0.1.10

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 (34) hide show
  1. package/dist/{ChromaDBProvider-2JZSBOQX.mjs → ChromaDBProvider-T7TK3ONZ.mjs} +2 -2
  2. package/dist/{MilvusProvider-CJDBCBVI.mjs → MilvusProvider-Y5FV5EAE.mjs} +2 -2
  3. package/dist/{MongoDBProvider-WWVJG3WT.mjs → MongoDBProvider-QHMGD2LZ.mjs} +2 -2
  4. package/dist/{PineconeProvider-E6L5Z2FO.mjs → PineconeProvider-A47MRRYJ.mjs} +2 -2
  5. package/dist/{PostgreSQLProvider-ZNXA67IM.mjs → PostgreSQLProvider-PJ5ER5Z4.mjs} +1 -1
  6. package/dist/{QdrantProvider-JITRNJQN.mjs → QdrantProvider-OLPJK7CY.mjs} +2 -2
  7. package/dist/{RedisProvider-3VKFQXXD.mjs → RedisProvider-ANEJ3BHR.mjs} +2 -2
  8. package/dist/{UniversalVectorProvider-E6L4U4OX.mjs → UniversalVectorProvider-QJIV2AJJ.mjs} +3 -3
  9. package/dist/{WeaviateProvider-MXIPP44J.mjs → WeaviateProvider-WIK2QN23.mjs} +2 -2
  10. package/dist/{chunk-YIYDJQJM.mjs → chunk-2VR5ZMXV.mjs} +11 -11
  11. package/dist/{chunk-QEYVWVT5.mjs → chunk-5HXNKSCR.mjs} +1 -1
  12. package/dist/{chunk-MFWJZVF3.mjs → chunk-BMHJTWSU.mjs} +1 -1
  13. package/dist/{chunk-UKDXCXW7.mjs → chunk-EDLTMSNY.mjs} +1 -1
  14. package/dist/{chunk-I4E63NIC.mjs → chunk-FWCSY2DS.mjs} +14 -1
  15. package/dist/{chunk-7BQI4A5J.mjs → chunk-HOMXEE3M.mjs} +1 -1
  16. package/dist/{chunk-TSX6DQXX.mjs → chunk-RUKZC3ON.mjs} +1 -1
  17. package/dist/{chunk-YST6KYBJ.mjs → chunk-VEJNRS4B.mjs} +1 -1
  18. package/dist/{chunk-XZPVJS2B.mjs → chunk-VKE5ZW7Y.mjs} +1 -1
  19. package/dist/{chunk-Y6HQZDCJ.mjs → chunk-VV2ML6TM.mjs} +2 -2
  20. package/dist/{chunk-26EMHLIN.mjs → chunk-W2PQR3UK.mjs} +1 -1
  21. package/dist/handlers/index.mjs +3 -3
  22. package/dist/index.js +67 -58
  23. package/dist/index.mjs +74 -47
  24. package/dist/server.d.mts +36 -1
  25. package/dist/server.d.ts +36 -1
  26. package/dist/server.js +127 -0
  27. package/dist/server.mjs +124 -11
  28. package/package.json +1 -1
  29. package/src/app/constants.tsx +220 -0
  30. package/src/app/page.tsx +193 -363
  31. package/src/app/types.ts +30 -0
  32. package/src/components/ChatWindow.tsx +3 -11
  33. package/src/providers/vectordb/MultiTablePostgresProvider.ts +164 -0
  34. package/src/server.ts +1 -0
package/src/app/page.tsx CHANGED
@@ -5,87 +5,132 @@ import {
5
5
  Zap,
6
6
  GitBranch,
7
7
  HeartPulse,
8
- Database,
9
- Layers,
10
- Bot,
11
- Brain,
12
- Rabbit,
13
8
  FileText,
14
- Search,
15
- Puzzle,
16
- MessageSquare,
17
9
  ExternalLink,
18
10
  Package,
11
+ Check,
12
+ Copy,
19
13
  } from 'lucide-react';
20
14
  import { ChatWindow } from '@/components/ChatWindow';
21
15
  import { ChatWidget } from '@/components/ChatWidget';
22
16
  import { useConfig } from '@/components/ConfigProvider';
23
17
  import { ThemeToggle } from '@/components/ThemeToggle';
24
- import { Check, Copy } from 'lucide-react';
25
18
  import pkg from '../../package.json';
19
+ import { Snippet, ArchitectureCardProps } from './types';
20
+ import {
21
+ LANDING_PAGE_CONTENT,
22
+ VECTOR_DATABASES,
23
+ AI_MODELS,
24
+ PIPELINE_STEPS,
25
+ SNIPPETS,
26
+ ARCHITECTURE_CARDS,
27
+ QUICK_START_STEPS,
28
+ API_ENDPOINTS,
29
+ } from './constants';
30
+
31
+ // ── Components ──────────────────────────────────────────────────────────────
32
+
33
+ function ArchitectureCard({ icon, title, description, badge, badgeColor }: ArchitectureCardProps) {
34
+ return (
35
+ <div className="group rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/5 p-6 shadow-sm transition-all duration-300 hover:border-indigo-500/50 dark:hover:border-indigo-500/30 hover:shadow-xl hover:shadow-indigo-500/5">
36
+ <div className="mb-4 flex items-center justify-between">
37
+ <div className="text-3xl transition-transform duration-300 group-hover:scale-110">{icon}</div>
38
+ <span className={`rounded-full border px-3 py-0.5 text-[10px] font-bold uppercase tracking-wider ${badgeColor}`}>
39
+ {badge}
40
+ </span>
41
+ </div>
42
+ <h3 className="mb-2 font-bold text-slate-900 dark:text-white">{title}</h3>
43
+ <p className="text-xs text-slate-500 dark:text-white/40 leading-relaxed font-medium">{description}</p>
44
+ </div>
45
+ );
46
+ }
26
47
 
27
- /**
28
- * Custom hook for copy-to-clipboard functionality
29
- */
30
- function useCopyToClipboard() {
31
- const [copied, setCopied] = React.useState<string | null>(null);
48
+ function CodeViewer({ snippet }: { snippet: Snippet }) {
49
+ const [copied, setCopied] = React.useState(false);
32
50
 
33
- const copy = (text: string, id: string) => {
34
- navigator.clipboard.writeText(text);
35
- setCopied(id);
36
- setTimeout(() => setCopied(null), 2000);
51
+ const handleCopy = () => {
52
+ navigator.clipboard.writeText(snippet.code);
53
+ setCopied(true);
54
+ setTimeout(() => setCopied(false), 2000);
37
55
  };
38
56
 
39
- return { copied, copy };
57
+ return (
58
+ <div className="flex flex-col h-full rounded-2xl border border-slate-200 dark:border-white/10 bg-slate-50 dark:bg-slate-900/50 shadow-lg overflow-hidden min-h-[440px]">
59
+ <div className="flex items-center justify-between px-5 py-3 border-b border-slate-200 dark:border-white/10 bg-white dark:bg-slate-900">
60
+ <div className="flex items-center gap-3">
61
+ <div className="flex gap-1.5">
62
+ <div className="w-2.5 h-2.5 rounded-full bg-red-500" />
63
+ <div className="w-2.5 h-2.5 rounded-full bg-yellow-500" />
64
+ <div className="w-2.5 h-2.5 rounded-full bg-green-500" />
65
+ </div>
66
+ <span className="text-[10px] font-mono text-slate-400 dark:text-white/30 uppercase tracking-widest ml-2">{snippet.language}</span>
67
+ </div>
68
+ <button
69
+ onClick={handleCopy}
70
+ className="flex items-center gap-2 text-[10px] font-bold text-slate-500 dark:text-white/40 hover:text-indigo-600 dark:hover:text-indigo-400 transition-all active:scale-95"
71
+ >
72
+ {copied ? (
73
+ <>
74
+ <Check size={14} className="text-emerald-500" />
75
+ <span className="text-emerald-500">Copied!</span>
76
+ </>
77
+ ) : (
78
+ <>
79
+ <Copy size={14} />
80
+ <span>Copy Code</span>
81
+ </>
82
+ )}
83
+ </button>
84
+ </div>
85
+ <div className="p-8 font-mono text-[12px] leading-relaxed overflow-auto custom-scrollbar flex-grow bg-[#0f172a] text-indigo-50">
86
+ <pre className="whitespace-pre">
87
+ <code>{snippet.code}</code>
88
+ </pre>
89
+ </div>
90
+ </div>
91
+ );
40
92
  }
41
93
 
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
94
 
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;
95
+
96
+ // Data moved to constants.tsx
97
+
98
+ // ── Page ────────────────────────────────────────────────────────────────────
99
+
100
+ function DocViewer({ activeSnippet, setActiveSnippet }: { activeSnippet: Snippet, setActiveSnippet: (s: Snippet) => void }) {
101
+ return (
102
+ <>
103
+ <div className="mb-6 flex flex-wrap gap-2 border-b border-slate-100 dark:border-white/5 pb-6">
104
+ {SNIPPETS.map((snippet) => (
105
+ <button
106
+ key={snippet.id}
107
+ onClick={() => setActiveSnippet(snippet)}
108
+ className={`px-5 py-2 rounded-xl text-[10px] font-bold uppercase tracking-wider transition-all border ${activeSnippet.id === snippet.id
109
+ ? 'bg-indigo-600 text-white border-indigo-600 shadow-lg shadow-indigo-200 dark:shadow-indigo-500/20 scale-105'
110
+ : 'bg-white dark:bg-white/5 border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/40 hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-indigo-300 dark:hover:border-white/20'
111
+ }`}
112
+ >
113
+ {snippet.title}
114
+ </button>
115
+ ))}
116
+ </div>
117
+
118
+ <div className="flex-grow flex flex-col gap-6 animate-in fade-in slide-in-from-bottom-2 duration-500">
119
+ <div className="max-w-2xl">
120
+ <h3 className="text-xl font-bold text-slate-900 dark:text-white mb-2">{activeSnippet.title}</h3>
121
+ <p className="text-sm text-slate-500 dark:text-white/40 leading-relaxed font-medium italic">
122
+ {activeSnippet.description}
123
+ </p>
124
+ </div>
125
+ <CodeViewer snippet={activeSnippet} />
126
+ </div>
127
+ </>
128
+ );
129
+ }
85
130
 
86
131
  export default function HomePage() {
87
132
  const { ui } = useConfig();
88
- const { copied, copy } = useCopyToClipboard();
133
+ const [activeSnippet, setActiveSnippet] = React.useState<Snippet>(SNIPPETS[0]);
89
134
 
90
135
  return (
91
136
  <main className="min-h-screen bg-slate-50 dark:bg-[#080811] relative transition-colors duration-300">
@@ -99,7 +144,6 @@ export default function HomePage() {
99
144
  className="absolute -bottom-40 -right-40 w-[600px] h-[600px] rounded-full opacity-15 blur-3xl"
100
145
  style={{ background: ui.accentColor }}
101
146
  />
102
- {/* Grid pattern */}
103
147
  <div
104
148
  className="absolute inset-0 opacity-[0.05] dark:opacity-[0.03]"
105
149
  style={{
@@ -121,7 +165,6 @@ export default function HomePage() {
121
165
  <Zap className="w-5 h-5 text-white animate-pulse" />
122
166
  <div className="absolute inset-0 bg-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
123
167
  </div>
124
- {/* Logo Glow */}
125
168
  <div
126
169
  className="absolute inset-0 blur-lg opacity-40 group-hover:opacity-80 transition-opacity"
127
170
  style={{ background: ui.primaryColor }}
@@ -142,153 +185,89 @@ export default function HomePage() {
142
185
 
143
186
  <div className="flex items-center gap-3">
144
187
  <ThemeToggle />
145
- <a
146
- href="https://www.npmjs.com/package/@retrivora-ai/rag-engine"
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
188
+ <a href="https://www.npmjs.com/package/@retrivora-ai/rag-engine" target="_blank" rel="noreferrer" 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">
189
+ <Package className="w-4 h-4" /> NPM
153
190
  </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
191
+ <a href="https://github.com/abhinav1201/ai-accelerator" target="_blank" rel="noreferrer" 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">
192
+ <GitBranch className="w-4 h-4" /> GitHub
162
193
  </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
194
+ <a href="/api/health" target="_blank" rel="noreferrer" 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">
195
+ <HeartPulse className="w-3.5 h-3.5" /> Health
171
196
  </a>
172
197
  </div>
173
198
  </nav>
174
199
 
175
- {/* ── Hero + Chat layout ── */}
200
+ {/* ── Hero + Chat ── */}
176
201
  <div className="relative z-10 container mx-auto px-6 py-12">
177
202
  <div className="grid lg:grid-cols-2 gap-12 items-start">
178
- {/* Left — Hero copy */}
179
203
  <div className="flex flex-col gap-6 pt-4">
180
204
  <div
181
205
  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
- }}
206
+ style={{ borderColor: `${ui.primaryColor}40`, color: ui.primaryColor, background: `${ui.primaryColor}10` }}
187
207
  >
188
208
  <span className="w-1.5 h-1.5 rounded-full animate-pulse" style={{ background: ui.primaryColor }} />
189
- Dynamic & Universal Retrivora AI
209
+ {LANDING_PAGE_CONTENT.hero.badge}
190
210
  </div>
191
-
192
211
  <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
212
+ {LANDING_PAGE_CONTENT.hero.title.split('for')[0]} <br />
213
+ <span className="text-transparent bg-clip-text" style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}>
214
+ for {LANDING_PAGE_CONTENT.hero.title.split('for')[1]}
199
215
  </span>
200
216
  </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.
217
+ <p className="text-lg md:text-xl text-slate-600 dark:text-white/40 max-w-2xl leading-relaxed">
218
+ {LANDING_PAGE_CONTENT.hero.subtitle}
203
219
  </p>
220
+ <div className="flex flex-col gap-4 mt-4">
221
+ <div className="flex flex-col gap-2">
222
+ <span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">Vector Ecosystem</span>
223
+ <div className="flex flex-wrap gap-2">
224
+ {VECTOR_DATABASES.map(({ Icon, label }) => (
225
+ <span key={label} 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-[11px] font-semibold hover:bg-slate-50 dark:hover:bg-white/8 transition-all shadow-sm group">
226
+ <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.primaryColor }} /> {label}
227
+ </span>
228
+ ))}
229
+ </div>
230
+ </div>
204
231
 
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>
232
+ <div className="flex flex-col gap-2">
233
+ <span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">AI Model Garden</span>
234
+ <div className="flex flex-wrap gap-2">
235
+ {AI_MODELS.map(({ Icon, label }) => (
236
+ <span key={label} 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-[11px] font-semibold hover:bg-slate-50 dark:hover:bg-white/8 transition-all shadow-sm group">
237
+ <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.accentColor }} /> {label}
238
+ </span>
239
+ ))}
233
240
  </div>
234
- ))}
241
+ </div>
235
242
  </div>
236
243
  </div>
237
-
238
- {/* Right — Full chat window */}
239
244
  <div className="lg:sticky lg:top-6">
240
245
  <ChatWindow className="w-full" style={{ height: '620px' } as React.CSSProperties} />
241
246
  </div>
242
247
  </div>
243
248
 
244
- {/* ── Architecture section ── */}
249
+ {/* ── Lifecycle ── */}
245
250
  <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
+ <h2 className="text-2xl font-bold text-slate-900 dark:text-white text-center mb-2">{LANDING_PAGE_CONTENT.lifecycle.title}</h2>
251
252
  <div className="relative max-w-5xl mx-auto py-12">
252
- {/* Center Spine Line */}
253
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
254
  <div className="space-y-12 md:space-y-0">
256
255
  {PIPELINE_STEPS.map(({ step, Icon, title, desc, colors }, index) => {
257
256
  const isLeft = index % 2 === 0;
258
257
  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 */}
258
+ <div key={step} className={`relative flex flex-col md:flex-row items-center gap-8 ${isLeft ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
265
259
  <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}
260
+ <div className="relative p-6 rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 max-w-md text-left overflow-hidden group">
261
+ <div className="absolute -right-2 -bottom-4 text-7xl font-bold opacity-[0.1] italic" style={{ color: colors.from }}>{step}</div>
262
+ <h3 className="font-semibold text-slate-900 dark:text-white mb-2 text-lg flex items-center gap-2">
263
+ <Icon className="w-5 h-5" style={{ color: colors.from }} /> {title}
278
264
  </h3>
279
- <p className="text-slate-600 dark:text-white/40 text-sm leading-relaxed relative z-10">{desc}</p>
265
+ <p className="text-slate-600 dark:text-white/40 text-sm leading-relaxed">{desc}</p>
280
266
  </div>
281
267
  </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
- >
268
+ <div className="relative z-10 w-12 h-12 rounded-2xl flex items-center justify-center shadow-xl border-4 border-slate-50 dark:border-[#080811]" style={{ background: `linear-gradient(135deg, ${colors.from}, ${colors.to})` }}>
288
269
  <Icon className="w-6 h-6 text-white" />
289
270
  </div>
290
-
291
- {/* Spacer for the other side */}
292
271
  <div className="hidden md:block md:w-1/2" />
293
272
  </div>
294
273
  );
@@ -297,209 +276,60 @@ export default function HomePage() {
297
276
  </div>
298
277
  </div>
299
278
 
300
- {/* ── How to Use Section ── */}
301
- <div className="mt-32 max-w-5xl mx-auto mb-24 relative">
279
+ {/* ── Architecture Cards ── */}
280
+ <div className="relative z-10 mt-24 mb-32 grid gap-6 sm:grid-cols-3 max-w-5xl mx-auto">
281
+ {ARCHITECTURE_CARDS.map((card, i) => (
282
+ <ArchitectureCard key={i} {...card} />
283
+ ))}
284
+ </div>
285
+
286
+ {/* ── Documentation ── */}
287
+ <div className="mt-32 max-w-6xl mx-auto mb-24 relative">
302
288
  <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>
289
+ <h2 className="text-3xl font-bold text-slate-900 dark:text-white mb-4">{LANDING_PAGE_CONTENT.guide.title}</h2>
290
+ <p className="text-slate-600 dark:text-white/40 max-w-2xl mx-auto">{LANDING_PAGE_CONTENT.guide.subtitle}</p>
307
291
  </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 @retrivora-ai/rag-engine</span>
337
- <button
338
- onClick={() => copy('npm install @retrivora-ai/rag-engine', '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>
292
+ <div className="relative z-10 w-full grid gap-16 lg:grid-cols-[280px_1fr] items-start">
293
+ <aside className="flex flex-col gap-10">
294
+ <section>
295
+ <h2 className="mb-6 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
296
+ <FileText size={14} className="text-indigo-500" /> Quick Start
297
+ </h2>
298
+ <ol className="space-y-6">
299
+ {QUICK_START_STEPS.map((step, i) => (
300
+ <li key={i} className="group flex items-start gap-4">
301
+ <span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-lg bg-white dark:bg-white/5 text-slate-600 dark:text-white/40 font-mono text-[10px] border border-slate-200 dark:border-white/10 shadow-sm">{i + 1}</span>
302
+ <span className="text-xs text-slate-500 dark:text-white/50 font-medium leading-relaxed pt-1">{step}</span>
303
+ </li>
304
+ ))}
305
+ </ol>
306
+ </section>
307
+ <section className="rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 p-6 shadow-sm">
308
+ <h2 className="mb-6 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
309
+ <Zap size={14} className="text-indigo-500" /> API Endpoints
310
+ </h2>
311
+ <div className="grid gap-2.5">
312
+ {API_ENDPOINTS.map((slug) => (
313
+ <div key={slug} className="group flex items-center justify-between p-2 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-100 dark:border-white/5 hover:border-indigo-200 dark:hover:border-indigo-500/30">
314
+ <span className="text-[10px] font-mono text-slate-500 dark:text-white/30 group-hover:text-indigo-600">/api/{slug}</span>
315
+ <span className="text-[8px] font-bold text-indigo-600 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-500/10 px-1.5 py-0.5 rounded border border-indigo-100 dark:border-indigo-500/20">POST</span>
344
316
  </div>
345
- </div>
317
+ ))}
346
318
  </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 '@retrivora-ai/rag-engine';\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 '@retrivora-ai/rag-engine';
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 '@retrivora-ai/rag-engine/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 '@retrivora-ai/rag-engine/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=&quot;AI Assistant&quot;</span>
482
- </div>
483
- </div>
484
- </div>
485
- </div>
486
- </div>
319
+ </section>
320
+ </aside>
321
+ <section className="flex flex-col h-full min-h-[560px]">
322
+ <DocViewer activeSnippet={activeSnippet} setActiveSnippet={setActiveSnippet} />
323
+ </section>
487
324
  </div>
488
-
489
325
  <div className="mt-16 text-center">
490
- <a
491
- href="https://www.npmjs.com/package/@retrivora-ai/rag-engine"
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" />
326
+ <a href="https://www.npmjs.com/package/@retrivora-ai/rag-engine" 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 shadow-xl shadow-indigo-500/20">
327
+ <Package className="w-5 h-5" /> Get Started on NPM <ExternalLink className="w-4 h-4" />
497
328
  </a>
498
329
  </div>
499
330
  </div>
500
331
  </div>
501
332
 
502
- {/* ── Floating widget demo (bottom-right corner) ── */}
503
333
  <ChatWidget position="bottom-right" />
504
334
  </main>
505
335
  );