@retrivora-ai/rag-engine 1.9.7 → 1.9.8

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 (58) hide show
  1. package/README.md +127 -135
  2. package/dist/{ILLMProvider-Bhk6zJOK.d.mts → ILLMProvider-B8ROITYK.d.mts} +57 -2
  3. package/dist/{ILLMProvider-Bhk6zJOK.d.ts → ILLMProvider-B8ROITYK.d.ts} +57 -2
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +2198 -457
  7. package/dist/handlers/index.mjs +2195 -457
  8. package/dist/{index-BJ4cd-t5.d.mts → index-B8PbEFSY.d.mts} +12 -2
  9. package/dist/{index-Bu7T6xgr.d.ts → index-BCPKUAVL.d.ts} +27 -52
  10. package/dist/{index-C3SVtPYg.d.mts → index-CrxCy36A.d.mts} +27 -52
  11. package/dist/{index-B9J_XEh0.d.ts → index-DNvoi-sV.d.ts} +12 -2
  12. package/dist/index.css +578 -273
  13. package/dist/index.d.mts +29 -7
  14. package/dist/index.d.ts +29 -7
  15. package/dist/index.js +1160 -282
  16. package/dist/index.mjs +1185 -292
  17. package/dist/server.d.mts +62 -6
  18. package/dist/server.d.ts +62 -6
  19. package/dist/server.js +2061 -306
  20. package/dist/server.mjs +2055 -306
  21. package/package.json +11 -7
  22. package/src/app/constants.tsx +37 -7
  23. package/src/components/AmbientBackground.tsx +10 -10
  24. package/src/components/ArchitectureCard.tsx +43 -7
  25. package/src/components/ArchitectureCardsSection.tsx +37 -4
  26. package/src/components/ChatWidget.tsx +2 -1
  27. package/src/components/ChatWindow.tsx +4 -1
  28. package/src/components/CodeViewer.tsx +19 -14
  29. package/src/components/DocViewer.tsx +43 -49
  30. package/src/components/Documentation.tsx +71 -51
  31. package/src/components/Hero.tsx +103 -20
  32. package/src/components/Lifecycle.tsx +65 -25
  33. package/src/components/MarkdownComponents.tsx +44 -1
  34. package/src/components/MessageBubble.tsx +162 -50
  35. package/src/components/constants.tsx +4 -0
  36. package/src/config/RagConfig.ts +46 -0
  37. package/src/config/constants.ts +4 -0
  38. package/src/config/serverConfig.ts +15 -0
  39. package/src/core/ConfigResolver.ts +6 -0
  40. package/src/core/DatabaseStorage.ts +469 -0
  41. package/src/core/LicenseVerifier.ts +154 -0
  42. package/src/core/MultiAgentCoordinator.ts +239 -0
  43. package/src/core/Pipeline.ts +146 -15
  44. package/src/core/Retrivora.ts +6 -0
  45. package/src/core/VectorPlugin.ts +12 -3
  46. package/src/core/mcp.ts +261 -0
  47. package/src/handlers/index.ts +449 -63
  48. package/src/hooks/useRagChat.ts +96 -42
  49. package/src/hooks/useStoredMessages.ts +15 -4
  50. package/src/index.ts +5 -0
  51. package/src/llm/LLMFactory.ts +9 -1
  52. package/src/llm/providers/GroqProvider.ts +176 -0
  53. package/src/llm/providers/QwenProvider.ts +191 -0
  54. package/src/server.ts +7 -0
  55. package/src/types/chat.ts +14 -0
  56. package/src/types/props.ts +12 -0
  57. package/.env.example +0 -80
  58. package/LICENSE.txt +0 -21
@@ -10,43 +10,49 @@ export function Documentation() {
10
10
  const [activeSnippet, setActiveSnippet] = React.useState<Snippet>(SNIPPETS[0]);
11
11
 
12
12
  return (
13
- <div className="mt-32 max-w-6xl mx-auto mb-24 relative">
14
- <div className="text-center mb-16">
15
- <h2 className="text-3xl font-bold text-slate-900 dark:text-white mb-4">{LANDING_PAGE_CONTENT.guide.title}</h2>
16
- <p className="text-slate-600 dark:text-white/40 max-w-2xl mx-auto">{LANDING_PAGE_CONTENT.guide.subtitle}</p>
13
+ <div className="max-w-6xl mx-auto">
14
+ {/* Header */}
15
+ <div className="text-center mb-14">
16
+ <span className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-indigo-50 border border-indigo-100 text-[10px] font-bold uppercase tracking-widest text-indigo-600 mb-5">
17
+ <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse" />
18
+ Developer Guide
19
+ </span>
20
+ <h2 className="text-3xl md:text-4xl font-black text-slate-900 mb-4">
21
+ {LANDING_PAGE_CONTENT.guide.title}
22
+ </h2>
23
+ <p className="text-slate-500 max-w-xl mx-auto text-base leading-relaxed">
24
+ {LANDING_PAGE_CONTENT.guide.subtitle}
25
+ </p>
17
26
  </div>
18
- <div className="relative z-10 w-full grid gap-16 lg:grid-cols-[280px_1fr] items-start">
19
- <aside className="flex flex-col gap-8">
27
+
28
+ {/* Grid */}
29
+ <div className="w-full grid gap-8 lg:grid-cols-[270px_1fr] items-start">
30
+ {/* Sidebar */}
31
+ <aside className="flex flex-col gap-5">
32
+ {/* Quick Start */}
20
33
  <section>
21
- <h2 className="mb-4 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
22
- <FileText size={14} className="text-indigo-500" /> Quick Start
34
+ <h2 className="mb-3 text-[10px] font-black text-slate-400 uppercase tracking-[0.3em] flex items-center gap-2">
35
+ <FileText size={12} className="text-indigo-500" /> Quick Start
23
36
  </h2>
24
- <ol className="space-y-2.5">
37
+ <ol className="space-y-1">
25
38
  {QUICK_START_STEPS.map((step, i) => {
26
39
  const isActive = activeSnippet.id === step.id;
27
40
  return (
28
41
  <li key={step.id}>
29
42
  <button
30
- onClick={() => {
31
- const snip = SNIPPETS.find((s) => s.id === step.id);
32
- if (snip) setActiveSnippet(snip);
33
- }}
34
- className={`w-full flex items-start gap-4 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
43
+ onClick={() => { const s = SNIPPETS.find(s => s.id === step.id); if (s) setActiveSnippet(s); }}
44
+ className={`w-full flex items-start gap-3 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
35
45
  isActive
36
- ? 'bg-indigo-500/10 dark:bg-indigo-500/10 border-indigo-200 dark:border-indigo-500/30'
37
- : 'bg-white dark:bg-white/3 border-slate-200 dark:border-white/5 hover:border-slate-300 dark:hover:border-white/10 hover:bg-slate-50 dark:hover:bg-white/5 shadow-sm'
46
+ ? 'bg-indigo-50 border-indigo-200 shadow-sm'
47
+ : 'bg-white border-slate-200 hover:border-slate-300 hover:bg-slate-50'
38
48
  }`}
39
49
  >
40
50
  <span className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-lg font-mono text-[10px] font-bold border transition-all ${
41
- isActive
42
- ? 'bg-indigo-600 text-white border-indigo-600 shadow-md shadow-indigo-500/20'
43
- : 'bg-slate-100 dark:bg-white/5 text-slate-600 dark:text-white/40 border-slate-200 dark:border-white/10'
51
+ isActive ? 'bg-indigo-600 text-white border-indigo-600 shadow-sm' : 'bg-slate-100 text-slate-500 border-slate-200'
44
52
  }`}>{i + 1}</span>
45
53
  <div className="pt-0.5">
46
- <span className={`text-xs font-semibold block transition-colors ${
47
- isActive ? 'text-indigo-600 dark:text-indigo-400 font-bold' : 'text-slate-700 dark:text-white/70 font-medium'
48
- }`}>{step.text}</span>
49
- <span className="text-[9px] text-slate-400 dark:text-white/30 block mt-0.5">Step {i + 1}</span>
54
+ <span className={`text-xs font-semibold block ${isActive ? 'text-indigo-700 font-bold' : 'text-slate-700'}`}>{step.text}</span>
55
+ <span className="text-[9px] text-slate-400 block mt-0.5">Step {i + 1}</span>
50
56
  </div>
51
57
  </button>
52
58
  </li>
@@ -55,36 +61,30 @@ export function Documentation() {
55
61
  </ol>
56
62
  </section>
57
63
 
64
+ {/* Advanced */}
58
65
  <section>
59
- <h2 className="mb-4 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
60
- <Code size={14} className="text-violet-500" /> Advanced Options
66
+ <h2 className="mb-3 text-[10px] font-black text-slate-400 uppercase tracking-[0.3em] flex items-center gap-2">
67
+ <Code size={12} className="text-violet-500" /> Advanced Options
61
68
  </h2>
62
- <ol className="space-y-2.5">
69
+ <ol className="space-y-1">
63
70
  {ADVANCED_STEPS.map((step, i) => {
64
71
  const isActive = activeSnippet.id === step.id;
65
72
  return (
66
73
  <li key={step.id}>
67
74
  <button
68
- onClick={() => {
69
- const snip = SNIPPETS.find((s) => s.id === step.id);
70
- if (snip) setActiveSnippet(snip);
71
- }}
72
- className={`w-full flex items-start gap-4 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
75
+ onClick={() => { const s = SNIPPETS.find(s => s.id === step.id); if (s) setActiveSnippet(s); }}
76
+ className={`w-full flex items-start gap-3 p-3 rounded-xl border text-left transition-all active:scale-[0.98] ${
73
77
  isActive
74
- ? 'bg-violet-500/10 dark:bg-violet-500/10 border-violet-200 dark:border-violet-500/30'
75
- : 'bg-white dark:bg-white/3 border-slate-200 dark:border-white/5 hover:border-slate-300 dark:hover:border-white/10 hover:bg-slate-50 dark:hover:bg-white/5 shadow-sm'
78
+ ? 'bg-violet-50 border-violet-200 shadow-sm'
79
+ : 'bg-white border-slate-200 hover:border-slate-300 hover:bg-slate-50'
76
80
  }`}
77
81
  >
78
82
  <span className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-lg font-mono text-[10px] font-bold border transition-all ${
79
- isActive
80
- ? 'bg-violet-600 text-white border-violet-600 shadow-md shadow-violet-500/20'
81
- : 'bg-slate-100 dark:bg-white/5 text-slate-600 dark:text-white/40 border-slate-200 dark:border-white/10'
83
+ isActive ? 'bg-violet-600 text-white border-violet-600 shadow-sm' : 'bg-slate-100 text-slate-500 border-slate-200'
82
84
  }`}>{i + 5}</span>
83
85
  <div className="pt-0.5">
84
- <span className={`text-xs font-semibold block transition-colors ${
85
- isActive ? 'text-violet-600 dark:text-violet-400 font-bold' : 'text-slate-700 dark:text-white/70 font-medium'
86
- }`}>{step.text}</span>
87
- <span className="text-[9px] text-slate-400 dark:text-white/30 block mt-0.5">Extension</span>
86
+ <span className={`text-xs font-semibold block ${isActive ? 'text-violet-700 font-bold' : 'text-slate-700'}`}>{step.text}</span>
87
+ <span className="text-[9px] text-slate-400 block mt-0.5">Extension</span>
88
88
  </div>
89
89
  </button>
90
90
  </li>
@@ -93,27 +93,47 @@ export function Documentation() {
93
93
  </ol>
94
94
  </section>
95
95
 
96
- <section className="rounded-2xl border border-slate-200 dark:border-white/10 bg-white dark:bg-white/3 p-6 shadow-sm">
97
- <h2 className="mb-6 text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.3em] flex items-center gap-3">
98
- <Zap size={14} className="text-indigo-500" /> API Endpoints
96
+ {/* API Endpoints */}
97
+ <section className="rounded-2xl border border-slate-200 bg-white p-5 shadow-sm">
98
+ <h2 className="mb-4 text-[10px] font-black text-slate-400 uppercase tracking-[0.3em] flex items-center gap-2">
99
+ <Zap size={12} className="text-indigo-500" /> API Endpoints
99
100
  </h2>
100
- <div className="grid gap-2.5">
101
+ <div className="grid gap-2">
101
102
  {API_ENDPOINTS.map((slug) => (
102
- <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">
103
- <span className="text-[10px] font-mono text-slate-500 dark:text-white/30 group-hover:text-indigo-600">/api/{slug}</span>
104
- <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>
103
+ <div
104
+ key={slug}
105
+ className="flex items-center justify-between p-2.5 rounded-lg bg-slate-50 border border-slate-100 hover:border-indigo-200 hover:bg-indigo-50 transition-all group"
106
+ >
107
+ <span className="text-[10px] font-mono text-slate-500 group-hover:text-indigo-600 transition-colors">/api/{slug}</span>
108
+ <span className="text-[8px] font-bold text-indigo-600 bg-indigo-50 px-1.5 py-0.5 rounded border border-indigo-100">POST</span>
105
109
  </div>
106
110
  ))}
107
111
  </div>
108
112
  </section>
109
113
  </aside>
114
+
115
+ {/* Code Viewer */}
110
116
  <section className="flex flex-col h-full min-h-[560px]">
111
- <DocViewer activeSnippet={activeSnippet} setActiveSnippet={setActiveSnippet} />
117
+ <div className="rounded-2xl border border-slate-200 bg-white overflow-hidden h-full shadow-sm">
118
+ <DocViewer activeSnippet={activeSnippet} setActiveSnippet={setActiveSnippet} />
119
+ </div>
112
120
  </section>
113
121
  </div>
114
- <div className="mt-16 text-center">
115
- <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">
116
- <Package className="w-5 h-5" /> Get Started on NPM <ExternalLink className="w-4 h-4" />
122
+
123
+ {/* CTA */}
124
+ <div className="mt-14 text-center">
125
+ <a
126
+ href="https://www.npmjs.com/package/@retrivora-ai/rag-engine"
127
+ target="_blank" rel="noreferrer"
128
+ className="inline-flex items-center gap-3 px-8 py-4 rounded-2xl text-white font-bold text-sm shadow-lg transition-all hover:-translate-y-0.5"
129
+ style={{
130
+ background: 'linear-gradient(135deg, #4f46e5, #7c3aed)',
131
+ boxShadow: '0 8px 24px -6px rgba(79, 70, 229, 0.35)',
132
+ }}
133
+ >
134
+ <Package className="w-5 h-5" />
135
+ Get Started on NPM
136
+ <ExternalLink className="w-4 h-4" />
117
137
  </a>
118
138
  </div>
119
139
  </div>
@@ -1,58 +1,141 @@
1
1
  'use client';
2
2
 
3
3
  import React from 'react';
4
+ import Link from 'next/link';
4
5
  import { useConfig } from '@/components/ConfigProvider';
5
6
  import { ChatWindow } from '@/components/ChatWindow';
6
7
  import { LANDING_PAGE_CONTENT, VECTOR_DATABASES, AI_MODELS } from '@/app/constants';
8
+ import { ArrowRight, Package, GitBranch, Shield, Zap, CheckCircle } from 'lucide-react';
7
9
 
8
10
  export function Hero() {
9
11
  const { ui } = useConfig();
10
12
 
11
13
  return (
12
- <div className="grid lg:grid-cols-2 gap-12 items-start">
13
- <div className="flex flex-col gap-6 pt-4">
14
+ <div className="grid lg:grid-cols-2 gap-12 xl:gap-16 items-start">
15
+ {/* ── Left Column ─────────────────────────────── */}
16
+ <div className="flex flex-col gap-7 pt-4">
17
+ {/* Badge */}
14
18
  <div
15
- className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full text-xs font-medium border w-fit"
16
- style={{ borderColor: `${ui.primaryColor}40`, color: ui.primaryColor, background: `${ui.primaryColor}10` }}
19
+ className="inline-flex items-center gap-2.5 px-4 py-2 rounded-full text-xs font-semibold border w-fit"
20
+ style={{
21
+ borderColor: `${ui.primaryColor}30`,
22
+ color: ui.primaryColor,
23
+ background: `${ui.primaryColor}08`,
24
+ }}
17
25
  >
18
- <span className="w-1.5 h-1.5 rounded-full animate-pulse" style={{ background: ui.primaryColor }} />
26
+ <span
27
+ className="w-2 h-2 rounded-full"
28
+ style={{ background: ui.primaryColor, animation: 'pulseRing 2.5s ease-in-out infinite' }}
29
+ />
19
30
  {LANDING_PAGE_CONTENT.hero.badge}
20
31
  </div>
21
- <h1 className="text-5xl md:text-7xl font-black text-slate-900 dark:text-white mb-6 tracking-tight">
22
- {LANDING_PAGE_CONTENT.hero.title.split('for')[0]} <br />
23
- <span className="text-transparent bg-clip-text" style={{ backgroundImage: `linear-gradient(to right, ${ui.primaryColor}, ${ui.accentColor})` }}>
32
+
33
+ {/* Headline */}
34
+ <h1 className="text-5xl md:text-6xl xl:text-7xl font-black text-slate-900 tracking-tight leading-[1.05]">
35
+ {LANDING_PAGE_CONTENT.hero.title.split('for')[0]}
36
+ <br />
37
+ <span
38
+ className="text-transparent bg-clip-text"
39
+ style={{ backgroundImage: `linear-gradient(135deg, ${ui.primaryColor} 0%, ${ui.accentColor} 60%, #a855f7 100%)` }}
40
+ >
24
41
  for {LANDING_PAGE_CONTENT.hero.title.split('for')[1]}
25
42
  </span>
26
43
  </h1>
27
- <p className="text-lg md:text-xl text-slate-600 dark:text-white/40 max-w-2xl leading-relaxed">
44
+
45
+ {/* Subtitle */}
46
+ <p className="text-lg md:text-xl text-slate-500 max-w-lg leading-relaxed">
28
47
  {LANDING_PAGE_CONTENT.hero.subtitle}
29
48
  </p>
30
- <div className="flex flex-col gap-4 mt-4">
31
- <div className="flex flex-col gap-2">
32
- <span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">Vector Ecosystem</span>
49
+
50
+ {/* Trust pills */}
51
+ {/* <div className="flex flex-wrap items-center gap-2 mt-1">
52
+ {[
53
+ // { icon: Shield, color: 'text-emerald-600', bg: 'bg-emerald-50 border-emerald-100', label: 'MIT Licensed' },
54
+ { icon: Package, color: 'text-red-500', bg: 'bg-red-50 border-red-100', label: 'npm install @retrivora-ai/rag-engine' },
55
+ // { icon: CheckCircle, color: 'text-indigo-600', bg: 'bg-indigo-50 border-indigo-100', label: 'TypeScript First' },
56
+ ].map(({ icon: Icon, color, bg, label }) => (
57
+ <span key={label} className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-[11px] font-semibold text-slate-600 ${bg}`}>
58
+ <Icon className={`h-3 w-3 ${color}`} /> {label}
59
+ </span>
60
+ ))}
61
+ </div> */}
62
+
63
+ {/* Provider ecosystem */}
64
+ <div className="flex flex-col gap-4 border-t border-slate-100">
65
+ <div className="flex flex-col gap-2.5">
66
+ <span className="text-[10px] font-black text-slate-400 uppercase tracking-[0.22em] ml-1">
67
+ Vector Ecosystem
68
+ </span>
33
69
  <div className="flex flex-wrap gap-2">
34
70
  {VECTOR_DATABASES.map(({ Icon, label }) => (
35
- <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">
36
- <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.primaryColor }} /> {label}
71
+ <span
72
+ key={label}
73
+ className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white border border-slate-200 text-slate-600 text-[11px] font-semibold hover:border-indigo-300 hover:bg-indigo-50 hover:text-indigo-700 transition-all cursor-default group shadow-sm"
74
+ >
75
+ <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.primaryColor }} />
76
+ {label}
37
77
  </span>
38
78
  ))}
39
79
  </div>
40
80
  </div>
41
81
 
42
- <div className="flex flex-col gap-2">
43
- <span className="text-[10px] font-black text-slate-400 dark:text-white/30 uppercase tracking-[0.2em] ml-1">AI Model Garden</span>
82
+ <div className="flex flex-col gap-2.5">
83
+ <span className="text-[10px] font-black text-slate-400 uppercase tracking-[0.22em] ml-1">
84
+ AI Model Garden
85
+ </span>
44
86
  <div className="flex flex-wrap gap-2">
45
87
  {AI_MODELS.map(({ Icon, label }) => (
46
- <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">
47
- <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.accentColor }} /> {label}
88
+ <span
89
+ key={label}
90
+ className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-white border border-slate-200 text-slate-600 text-[11px] font-semibold hover:border-violet-300 hover:bg-violet-50 hover:text-violet-700 transition-all cursor-default group shadow-sm"
91
+ >
92
+ <Icon className="w-3 h-3 transition-transform group-hover:scale-110" style={{ color: ui.accentColor }} />
93
+ {label}
48
94
  </span>
49
95
  ))}
50
96
  </div>
51
97
  </div>
52
98
  </div>
99
+
100
+ {/* CTAs */}
101
+ <div className="flex flex-wrap items-center gap-3 mt-1">
102
+ <Link
103
+ href="/register"
104
+ className="group flex items-center gap-2 px-6 py-3.5 rounded-xl text-sm font-bold text-white transition-all duration-200 shadow-lg hover:-translate-y-0.5"
105
+ style={{
106
+ background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})`,
107
+ boxShadow: `0 8px 24px -6px ${ui.primaryColor}45`,
108
+ }}
109
+ >
110
+ Get Started Free
111
+ <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
112
+ </Link>
113
+ {/* <a
114
+ href="https://github.com/abhinav1201/ai-accelerator"
115
+ target="_blank" rel="noreferrer"
116
+ className="flex items-center gap-2 px-6 py-3.5 rounded-xl text-sm font-semibold text-slate-700 hover:text-slate-900 border border-slate-200 hover:border-slate-300 bg-white hover:bg-slate-50 transition-all shadow-sm"
117
+ >
118
+ <GitBranch className="h-4 w-4" />
119
+ View on GitHub
120
+ </a> */}
121
+ </div>
53
122
  </div>
54
- <div className="lg:sticky lg:top-6 h-[calc(100vh-3rem)] min-h-[500px] max-h-[800px]">
55
- <ChatWindow className="w-full h-full" />
123
+
124
+ {/* ── Right Column — Live Demo ─────────────────── */}
125
+ <div className="relative lg:sticky lg:top-6 h-[480px] lg:h-[calc(100vh-6rem)] min-h-[400px] lg:min-h-[520px] max-h-[800px]">
126
+ {/* Decorative glow ring */}
127
+ <div
128
+ className="absolute -inset-3 rounded-3xl pointer-events-none"
129
+ style={{ background: `radial-gradient(ellipse at center, ${ui.primaryColor}12 0%, transparent 70%)` }}
130
+ />
131
+ <div className="relative h-full rounded-2xl overflow-hidden border border-slate-200 shadow-xl shadow-slate-200/80">
132
+ <ChatWindow className="w-full h-full" />
133
+ </div>
134
+ {/* "Live demo" tag */}
135
+ <div className="absolute -bottom-3 left-1/2 -translate-x-1/2 flex items-center gap-1.5 px-3.5 py-1.5 bg-white border border-slate-200 rounded-full text-[10px] font-semibold text-slate-500 shadow-md whitespace-nowrap">
136
+ <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse" />
137
+ Live Retrivora demo — powered by this SDK
138
+ </div>
56
139
  </div>
57
140
  </div>
58
141
  );
@@ -5,32 +5,72 @@ import { LANDING_PAGE_CONTENT, PIPELINE_STEPS } from '@/app/constants';
5
5
 
6
6
  export function Lifecycle() {
7
7
  return (
8
- <div className="mt-24 mb-12">
9
- <h2 className="text-2xl font-bold text-slate-900 dark:text-white text-center mb-2">{LANDING_PAGE_CONTENT.lifecycle.title}</h2>
10
- <div className="relative max-w-5xl mx-auto py-12">
11
- <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" />
12
- <div className="space-y-12 md:space-y-0">
13
- {PIPELINE_STEPS.map(({ step, Icon, title, desc, colors }, index) => {
14
- const isLeft = index % 2 === 0;
15
- return (
16
- <div key={step} className={`relative flex flex-col md:flex-row items-center gap-8 ${isLeft ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
17
- <div className={`w-full md:w-1/2 relative flex ${isLeft ? 'justify-end' : 'justify-start'}`}>
18
- <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">
19
- <div className="absolute -right-2 -bottom-4 text-7xl font-bold opacity-[0.1] italic" style={{ color: colors.from }}>{step}</div>
20
- <h3 className="font-semibold text-slate-900 dark:text-white mb-2 text-lg flex items-center gap-2">
21
- <Icon className="w-5 h-5" style={{ color: colors.from }} /> {title}
22
- </h3>
23
- <p className="text-slate-600 dark:text-white/40 text-sm leading-relaxed">{desc}</p>
24
- </div>
25
- </div>
26
- <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})` }}>
27
- <Icon className="w-6 h-6 text-white" />
28
- </div>
29
- <div className="hidden md:block md:w-1/2" />
8
+ <div className="relative">
9
+ {/* Section header */}
10
+ <div className="text-center mb-14">
11
+ <span className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-indigo-50 border border-indigo-100 text-[10px] font-bold uppercase tracking-widest text-indigo-600 mb-5">
12
+ <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse" />
13
+ How It Works
14
+ </span>
15
+ <h2 className="text-3xl md:text-4xl font-black text-slate-900 mb-4">
16
+ {LANDING_PAGE_CONTENT.lifecycle.title}
17
+ </h2>
18
+ <p className="text-slate-500 max-w-lg mx-auto text-base leading-relaxed">
19
+ Four composable stages from raw documents to grounded AI responses.
20
+ </p>
21
+ </div>
22
+
23
+ {/* Steps grid */}
24
+ <div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-5 max-w-6xl mx-auto">
25
+ {PIPELINE_STEPS.map(({ step, Icon, title, desc, colors }, index) => (
26
+ <div
27
+ key={step}
28
+ className="group relative bg-white rounded-2xl border border-slate-200 p-6 transition-all duration-300 hover:-translate-y-1 hover:shadow-lg hover:shadow-slate-200/80 overflow-hidden cursor-default"
29
+ >
30
+ {/* Gradient top border */}
31
+ <div
32
+ className="absolute top-0 left-0 right-0 h-0.5 rounded-t-2xl"
33
+ style={{ background: `linear-gradient(90deg, ${colors.from}, ${colors.to})` }}
34
+ />
35
+
36
+ {/* Step number watermark */}
37
+ <div
38
+ className="absolute -right-2 -bottom-4 text-8xl font-black opacity-[0.05] select-none pointer-events-none group-hover:opacity-[0.08] transition-opacity"
39
+ style={{ color: colors.from }}
40
+ >
41
+ {step}
42
+ </div>
43
+
44
+ {/* Icon container */}
45
+ <div
46
+ className="relative z-10 w-11 h-11 rounded-xl flex items-center justify-center mb-5 transition-transform duration-300 group-hover:scale-105"
47
+ style={{
48
+ background: `linear-gradient(135deg, ${colors.from}18, ${colors.to}10)`,
49
+ border: `1px solid ${colors.from}25`,
50
+ }}
51
+ >
52
+ <Icon className="w-5 h-5" style={{ color: colors.from }} />
53
+ </div>
54
+
55
+ {/* Content */}
56
+ <div className="relative z-10">
57
+ <div
58
+ className="text-[10px] font-black uppercase tracking-widest mb-1.5"
59
+ style={{ color: colors.from }}
60
+ >
61
+ Step {index + 1}
30
62
  </div>
31
- );
32
- })}
33
- </div>
63
+ <h3 className="text-base font-bold text-slate-900 mb-2">{title}</h3>
64
+ <p className="text-sm text-slate-500 leading-relaxed">{desc}</p>
65
+ </div>
66
+
67
+ {/* Hover glow */}
68
+ <div
69
+ className="absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"
70
+ style={{ background: `radial-gradient(ellipse at 50% 0%, ${colors.from}07 0%, transparent 70%)` }}
71
+ />
72
+ </div>
73
+ ))}
34
74
  </div>
35
75
  </div>
36
76
  );
@@ -116,10 +116,11 @@ export function createMarkdownComponents({
116
116
  />
117
117
  );
118
118
  }
119
+ return <CodeBlock language={lang}>{content}</CodeBlock>;
119
120
  }
120
121
 
121
122
  return (
122
- <code className={className} {...props}>
123
+ <code className="px-1.5 py-0.5 rounded bg-slate-100 dark:bg-white/10 text-rose-600 dark:text-rose-400 font-mono text-[11px]" {...props}>
123
124
  {typeof children === 'string' || typeof children === 'number'
124
125
  ? children
125
126
  : JSON.stringify(children)}
@@ -129,6 +130,48 @@ export function createMarkdownComponents({
129
130
  };
130
131
  }
131
132
 
133
+ function CodeBlock({ children, language }: { children: string; language?: string }) {
134
+ const [copied, setCopied] = React.useState(false);
135
+
136
+ const handleCopy = async () => {
137
+ try {
138
+ await navigator.clipboard.writeText(children);
139
+ setCopied(true);
140
+ setTimeout(() => setCopied(false), 2000);
141
+ } catch (e) {
142
+ console.warn('Failed to copy code', e);
143
+ }
144
+ };
145
+
146
+ return (
147
+ <div className="not-prose my-4 rounded-xl border border-slate-200 dark:border-white/10 overflow-hidden bg-slate-900 text-slate-100 shadow-lg select-text">
148
+ <div className="flex items-center justify-between px-4 py-2 bg-slate-950 border-b border-slate-800 text-xs font-semibold text-slate-400 select-none">
149
+ <span className="font-mono lowercase">{language || 'code'}</span>
150
+ <button
151
+ onClick={handleCopy}
152
+ className="flex items-center gap-1.5 px-2 py-1 rounded hover:bg-slate-800 hover:text-slate-250 transition-colors cursor-pointer text-slate-400 border border-transparent hover:border-slate-800"
153
+ type="button"
154
+ >
155
+ {copied ? (
156
+ <>
157
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" className="text-emerald-500"><polyline points="20 6 9 17 4 12"/></svg>
158
+ <span className="text-emerald-500">Copied!</span>
159
+ </>
160
+ ) : (
161
+ <>
162
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
163
+ <span>Copy</span>
164
+ </>
165
+ )}
166
+ </button>
167
+ </div>
168
+ <div className="p-4 overflow-x-auto font-mono text-[11px] leading-relaxed text-slate-200 bg-slate-900/90 whitespace-pre">
169
+ <code>{children}</code>
170
+ </div>
171
+ </div>
172
+ );
173
+ }
174
+
132
175
  /** Safely render table cell children that might be plain objects. */
133
176
  function normaliseChild(children: unknown): React.ReactNode {
134
177
  if (