claude-team-dashboard 1.2.2

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.

Potentially problematic release.


This version of claude-team-dashboard might be problematic. Click here for more details.

Files changed (49) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/LICENSE +21 -0
  3. package/README.md +722 -0
  4. package/cleanup.js +73 -0
  5. package/config.js +50 -0
  6. package/dist/assets/icons-Ijf8rQIc.js +1 -0
  7. package/dist/assets/index-Cqc1m1x_.css +1 -0
  8. package/dist/assets/index-jGy3ms0W.js +9 -0
  9. package/dist/assets/react-vendor-DbmSkCAF.js +1 -0
  10. package/dist/index.html +16 -0
  11. package/index.html +13 -0
  12. package/package.json +93 -0
  13. package/server.js +953 -0
  14. package/src/App.jsx +372 -0
  15. package/src/animations-enhanced.css +929 -0
  16. package/src/animations.css +783 -0
  17. package/src/components/ActivityFeed.jsx +289 -0
  18. package/src/components/AgentActivity.jsx +104 -0
  19. package/src/components/AgentCard.jsx +163 -0
  20. package/src/components/AgentOutputViewer.jsx +334 -0
  21. package/src/components/ArchiveViewer.jsx +283 -0
  22. package/src/components/ConnectionStatus.jsx +124 -0
  23. package/src/components/DetailedTaskProgress.jsx +126 -0
  24. package/src/components/ErrorBoundary.jsx +132 -0
  25. package/src/components/Header.jsx +154 -0
  26. package/src/components/LiveAgentStream.jsx +176 -0
  27. package/src/components/LiveCommunication.jsx +326 -0
  28. package/src/components/LiveMetrics.jsx +100 -0
  29. package/src/components/RealTimeMessages.jsx +298 -0
  30. package/src/components/SkeletonLoader.jsx +384 -0
  31. package/src/components/StatsOverview.jsx +209 -0
  32. package/src/components/SystemStatus.jsx +57 -0
  33. package/src/components/TaskList.jsx +306 -0
  34. package/src/components/TeamCard.jsx +126 -0
  35. package/src/components/TeamHistory.jsx +204 -0
  36. package/src/components/__tests__/ConnectionStatus.test.jsx +54 -0
  37. package/src/components/__tests__/StatsOverview.test.jsx +66 -0
  38. package/src/config/constants.js +59 -0
  39. package/src/hooks/useCounterAnimation.js +219 -0
  40. package/src/hooks/useWebSocket.js +76 -0
  41. package/src/index.css +1818 -0
  42. package/src/main.jsx +17 -0
  43. package/src/polish-enhancements.css +303 -0
  44. package/src/premium-visual-polish.css +830 -0
  45. package/src/responsive-enhancements.css +666 -0
  46. package/src/styles/theme.css +395 -0
  47. package/src/test/setup.js +19 -0
  48. package/start.js +36 -0
  49. package/vite.config.js +37 -0
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Claude Team Dashboard - Design Tokens
3
+ * Tailwind CSS v4 @theme Configuration
4
+ *
5
+ * This file defines all design tokens using Tailwind v4's CSS-first approach.
6
+ * All tokens are automatically available as:
7
+ * - Utility classes (e.g., bg-primary-500, text-neutral-300)
8
+ * - CSS variables (e.g., var(--color-primary-500))
9
+ */
10
+
11
+ @import "tailwindcss";
12
+
13
+ @theme {
14
+ /* ==========================================
15
+ COLOR SYSTEM - OKLCH Color Space
16
+ ========================================== */
17
+
18
+ /* Primary - Claude Orange (Enhanced Brand Colors) */
19
+ --color-primary-50: oklch(0.97 0.02 35);
20
+ --color-primary-100: oklch(0.94 0.05 40);
21
+ --color-primary-200: oklch(0.88 0.10 45);
22
+ --color-primary-300: oklch(0.80 0.15 45);
23
+ --color-primary-400: oklch(0.72 0.18 45);
24
+ --color-primary-500: oklch(0.68 0.20 40); /* Main brand color */
25
+ --color-primary-600: oklch(0.60 0.21 35);
26
+ --color-primary-700: oklch(0.49 0.18 30);
27
+ --color-primary-800: oklch(0.40 0.14 28);
28
+ --color-primary-900: oklch(0.32 0.10 25);
29
+ --color-primary-950: oklch(0.20 0.06 22);
30
+
31
+ /* Neutral - Dark Mode Optimized (Charcoal Scale) */
32
+ --color-neutral-950: oklch(0.12 0.01 240); /* Deep charcoal, not pure black */
33
+ --color-neutral-900: oklch(0.18 0.01 245); /* Background dark */
34
+ --color-neutral-850: oklch(0.20 0.01 245); /* Card background */
35
+ --color-neutral-800: oklch(0.24 0.01 248); /* Elevated surface */
36
+ --color-neutral-700: oklch(0.32 0.01 250); /* Borders */
37
+ --color-neutral-600: oklch(0.42 0.01 252); /* Dividers */
38
+ --color-neutral-500: oklch(0.52 0.01 255); /* Muted text */
39
+ --color-neutral-400: oklch(0.62 0.01 258); /* Secondary text */
40
+ --color-neutral-300: oklch(0.72 0.01 260); /* Primary text (dark mode) */
41
+ --color-neutral-200: oklch(0.82 0.01 262); /* Off-white text */
42
+ --color-neutral-100: oklch(0.92 0.01 265); /* Almost white */
43
+ --color-neutral-50: oklch(0.98 0.01 268); /* Pure white alternative */
44
+
45
+ /* Success - Green */
46
+ --color-success-50: oklch(0.95 0.05 145);
47
+ --color-success-100: oklch(0.90 0.08 145);
48
+ --color-success-200: oklch(0.85 0.10 145);
49
+ --color-success-300: oklch(0.78 0.13 145);
50
+ --color-success-400: oklch(0.70 0.15 145);
51
+ --color-success-500: oklch(0.62 0.18 142);
52
+ --color-success-600: oklch(0.52 0.16 140);
53
+ --color-success-700: oklch(0.42 0.14 138);
54
+ --color-success-800: oklch(0.35 0.11 136);
55
+ --color-success-900: oklch(0.28 0.08 134);
56
+
57
+ /* Warning - Amber/Yellow */
58
+ --color-warning-50: oklch(0.96 0.04 90);
59
+ --color-warning-100: oklch(0.92 0.08 88);
60
+ --color-warning-200: oklch(0.88 0.10 86);
61
+ --color-warning-300: oklch(0.84 0.11 84);
62
+ --color-warning-400: oklch(0.80 0.12 85);
63
+ --color-warning-500: oklch(0.74 0.14 82);
64
+ --color-warning-600: oklch(0.64 0.15 78);
65
+ --color-warning-700: oklch(0.52 0.13 75);
66
+ --color-warning-800: oklch(0.42 0.10 72);
67
+ --color-warning-900: oklch(0.35 0.08 70);
68
+
69
+ /* Error - Red */
70
+ --color-error-50: oklch(0.95 0.05 25);
71
+ --color-error-100: oklch(0.90 0.08 25);
72
+ --color-error-200: oklch(0.85 0.12 25);
73
+ --color-error-300: oklch(0.75 0.16 25);
74
+ --color-error-400: oklch(0.65 0.20 25);
75
+ --color-error-500: oklch(0.58 0.22 23);
76
+ --color-error-600: oklch(0.50 0.20 20);
77
+ --color-error-700: oklch(0.42 0.18 18);
78
+ --color-error-800: oklch(0.35 0.15 16);
79
+ --color-error-900: oklch(0.28 0.12 14);
80
+
81
+ /* Info - Blue */
82
+ --color-info-50: oklch(0.95 0.04 245);
83
+ --color-info-100: oklch(0.90 0.06 245);
84
+ --color-info-200: oklch(0.85 0.08 245);
85
+ --color-info-300: oklch(0.78 0.11 245);
86
+ --color-info-400: oklch(0.70 0.13 245);
87
+ --color-info-500: oklch(0.62 0.15 242);
88
+ --color-info-600: oklch(0.52 0.16 240);
89
+ --color-info-700: oklch(0.42 0.14 238);
90
+ --color-info-800: oklch(0.35 0.12 236);
91
+ --color-info-900: oklch(0.28 0.10 234);
92
+
93
+ /* Purple - Accent */
94
+ --color-purple-50: oklch(0.95 0.04 295);
95
+ --color-purple-100: oklch(0.90 0.06 295);
96
+ --color-purple-200: oklch(0.85 0.08 295);
97
+ --color-purple-300: oklch(0.78 0.11 295);
98
+ --color-purple-400: oklch(0.72 0.14 295);
99
+ --color-purple-500: oklch(0.64 0.16 292);
100
+ --color-purple-600: oklch(0.54 0.17 290);
101
+ --color-purple-700: oklch(0.44 0.15 288);
102
+ --color-purple-800: oklch(0.36 0.13 286);
103
+ --color-purple-900: oklch(0.28 0.10 284);
104
+
105
+ /* Cyan - Accent */
106
+ --color-cyan-50: oklch(0.95 0.03 200);
107
+ --color-cyan-100: oklch(0.90 0.05 200);
108
+ --color-cyan-200: oklch(0.85 0.07 200);
109
+ --color-cyan-300: oklch(0.80 0.09 200);
110
+ --color-cyan-400: oklch(0.75 0.10 200);
111
+ --color-cyan-500: oklch(0.67 0.12 198);
112
+ --color-cyan-600: oklch(0.57 0.13 195);
113
+ --color-cyan-700: oklch(0.47 0.11 192);
114
+ --color-cyan-800: oklch(0.38 0.09 190);
115
+ --color-cyan-900: oklch(0.30 0.07 188);
116
+
117
+ /* ==========================================
118
+ SPACING SYSTEM - 8px Base Grid
119
+ ========================================== */
120
+
121
+ --spacing-0: 0;
122
+ --spacing-1: 0.25rem; /* 4px */
123
+ --spacing-2: 0.5rem; /* 8px */
124
+ --spacing-3: 0.75rem; /* 12px */
125
+ --spacing-4: 1rem; /* 16px */
126
+ --spacing-5: 1.25rem; /* 20px */
127
+ --spacing-6: 1.5rem; /* 24px */
128
+ --spacing-7: 1.75rem; /* 28px */
129
+ --spacing-8: 2rem; /* 32px */
130
+ --spacing-9: 2.25rem; /* 36px */
131
+ --spacing-10: 2.5rem; /* 40px */
132
+ --spacing-11: 2.75rem; /* 44px */
133
+ --spacing-12: 3rem; /* 48px */
134
+ --spacing-14: 3.5rem; /* 56px */
135
+ --spacing-16: 4rem; /* 64px */
136
+ --spacing-20: 5rem; /* 80px */
137
+ --spacing-24: 6rem; /* 96px */
138
+ --spacing-32: 8rem; /* 128px */
139
+ --spacing-40: 10rem; /* 160px */
140
+
141
+ /* ==========================================
142
+ TYPOGRAPHY SYSTEM
143
+ ========================================== */
144
+
145
+ /* Font Families */
146
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto',
147
+ 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
148
+ 'Droid Sans', 'Helvetica Neue', sans-serif;
149
+ --font-mono: 'Menlo', 'Monaco', 'Courier New', monospace;
150
+
151
+ /* Font Sizes - Perfect Fourth Scale (1.333) */
152
+ --font-size-xs: 0.75rem; /* 12px */
153
+ --font-size-sm: 0.875rem; /* 14px */
154
+ --font-size-base: 1rem; /* 16px */
155
+ --font-size-lg: 1.125rem; /* 18px */
156
+ --font-size-xl: 1.25rem; /* 20px */
157
+ --font-size-2xl: 1.5rem; /* 24px */
158
+ --font-size-3xl: 1.875rem; /* 30px */
159
+ --font-size-4xl: 2.25rem; /* 36px */
160
+ --font-size-5xl: 3rem; /* 48px */
161
+ --font-size-6xl: 3.75rem; /* 60px */
162
+
163
+ /* Font Weights */
164
+ --font-weight-normal: 400;
165
+ --font-weight-medium: 500;
166
+ --font-weight-semibold: 600;
167
+ --font-weight-bold: 700;
168
+ --font-weight-extrabold: 800;
169
+
170
+ /* Line Heights */
171
+ --line-height-none: 1;
172
+ --line-height-tight: 1.25;
173
+ --line-height-snug: 1.375;
174
+ --line-height-normal: 1.6;
175
+ --line-height-relaxed: 1.75;
176
+ --line-height-loose: 2;
177
+
178
+ /* Letter Spacing */
179
+ --letter-spacing-tighter: -0.05em;
180
+ --letter-spacing-tight: -0.025em;
181
+ --letter-spacing-normal: -0.011em;
182
+ --letter-spacing-wide: 0.025em;
183
+ --letter-spacing-wider: 0.05em;
184
+
185
+ /* ==========================================
186
+ BORDER RADIUS
187
+ ========================================== */
188
+
189
+ --radius-none: 0;
190
+ --radius-sm: 0.25rem; /* 4px */
191
+ --radius-base: 0.5rem; /* 8px */
192
+ --radius-md: 0.75rem; /* 12px */
193
+ --radius-lg: 1rem; /* 16px */
194
+ --radius-xl: 1.25rem; /* 20px */
195
+ --radius-2xl: 1.5rem; /* 24px */
196
+ --radius-3xl: 2rem; /* 32px */
197
+ --radius-full: 9999px;
198
+
199
+ /* ==========================================
200
+ SHADOWS - Elevation System
201
+ ========================================== */
202
+
203
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05);
204
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
205
+ --shadow-base: 0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.05);
206
+ --shadow-md: 0 8px 16px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);
207
+ --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.15), 0 8px 12px rgba(0, 0, 0, 0.1);
208
+ --shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.2), 0 12px 16px rgba(0, 0, 0, 0.15);
209
+ --shadow-2xl: 0 32px 64px rgba(0, 0, 0, 0.3), 0 16px 24px rgba(0, 0, 0, 0.2);
210
+
211
+ /* ==========================================
212
+ BREAKPOINTS
213
+ ========================================== */
214
+
215
+ --breakpoint-sm: 640px;
216
+ --breakpoint-md: 768px;
217
+ --breakpoint-lg: 1024px;
218
+ --breakpoint-xl: 1280px;
219
+ --breakpoint-2xl: 1536px;
220
+ --breakpoint-3xl: 1920px;
221
+
222
+ /* ==========================================
223
+ ANIMATION DURATIONS
224
+ ========================================== */
225
+
226
+ --duration-fast: 150ms;
227
+ --duration-base: 200ms;
228
+ --duration-medium: 300ms;
229
+ --duration-slow: 500ms;
230
+ --duration-slower: 700ms;
231
+
232
+ /* ==========================================
233
+ Z-INDEX LAYERS
234
+ ========================================== */
235
+
236
+ --z-index-dropdown: 1000;
237
+ --z-index-sticky: 1020;
238
+ --z-index-fixed: 1030;
239
+ --z-index-modal-backdrop: 1040;
240
+ --z-index-modal: 1050;
241
+ --z-index-popover: 1060;
242
+ --z-index-tooltip: 1070;
243
+ }
244
+
245
+ /* ==========================================
246
+ CUSTOM CSS VARIABLES (Runtime Access)
247
+ ========================================== */
248
+
249
+ :root {
250
+ /* Surface Colors */
251
+ --surface-base: var(--color-neutral-900);
252
+ --surface-elevated-1: var(--color-neutral-850);
253
+ --surface-elevated-2: var(--color-neutral-800);
254
+ --surface-elevated-3: var(--color-neutral-700);
255
+
256
+ /* Glass Effect */
257
+ --surface-glass: rgba(30, 41, 59, 0.6);
258
+ --surface-glass-border: rgba(255, 255, 255, 0.1);
259
+
260
+ /* Gradients */
261
+ --gradient-primary: linear-gradient(135deg, #f97316 0%, #fb923c 100%);
262
+ --gradient-dark-base: linear-gradient(135deg, #0a0e1a 0%, #1a1f35 25%, #0f1729 50%, #1e2538 75%, #0a0e1a 100%);
263
+ --gradient-card: linear-gradient(135deg, rgba(30, 41, 59, 0.95) 0%, rgba(15, 23, 42, 0.9) 100%);
264
+ --gradient-card-hover: linear-gradient(135deg, rgba(30, 41, 59, 1) 0%, rgba(15, 23, 42, 0.95) 100%);
265
+
266
+ /* Accent Gradients */
267
+ --gradient-orange-glow: linear-gradient(90deg, transparent, rgba(249, 115, 22, 0.5), transparent);
268
+ --gradient-blue: linear-gradient(90deg, #3b82f6 0%, #60a5fa 100%);
269
+ --gradient-green: linear-gradient(90deg, #10b981 0%, #34d399 100%);
270
+ --gradient-purple: linear-gradient(90deg, #a855f7 0%, #c084fc 100%);
271
+
272
+ /* Glow Shadows */
273
+ --shadow-glow-orange: 0 0 30px rgba(249, 115, 22, 0.4), 0 8px 24px rgba(249, 115, 22, 0.2);
274
+ --shadow-glow-blue: 0 0 30px rgba(59, 130, 246, 0.4), 0 8px 24px rgba(59, 130, 246, 0.2);
275
+ --shadow-glow-green: 0 0 30px rgba(34, 197, 94, 0.4), 0 8px 24px rgba(34, 197, 94, 0.2);
276
+ --shadow-glow-purple: 0 0 30px rgba(168, 85, 247, 0.4), 0 8px 24px rgba(168, 85, 247, 0.2);
277
+
278
+ /* Easing Functions */
279
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
280
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
281
+ --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
282
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
283
+ --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
284
+
285
+ /* Opacity Scale */
286
+ --opacity-0: 0;
287
+ --opacity-5: 0.05;
288
+ --opacity-10: 0.1;
289
+ --opacity-20: 0.2;
290
+ --opacity-30: 0.3;
291
+ --opacity-40: 0.4;
292
+ --opacity-50: 0.5;
293
+ --opacity-60: 0.6;
294
+ --opacity-70: 0.7;
295
+ --opacity-80: 0.8;
296
+ --opacity-90: 0.9;
297
+ --opacity-95: 0.95;
298
+ --opacity-100: 1;
299
+
300
+ /* Color Scheme */
301
+ color-scheme: dark;
302
+ }
303
+
304
+ /* ==========================================
305
+ GLOBAL BASE STYLES
306
+ ========================================== */
307
+
308
+ * {
309
+ margin: 0;
310
+ padding: 0;
311
+ box-sizing: border-box;
312
+ }
313
+
314
+ body {
315
+ font-family: var(--font-sans);
316
+ -webkit-font-smoothing: antialiased;
317
+ -moz-osx-font-smoothing: grayscale;
318
+ background: var(--gradient-dark-base);
319
+ background-size: 400% 400%;
320
+ animation: gradientShift 20s ease infinite;
321
+ color: var(--color-neutral-300);
322
+ min-height: 100vh;
323
+ }
324
+
325
+ @keyframes gradientShift {
326
+ 0% { background-position: 0% 50%; }
327
+ 50% { background-position: 100% 50%; }
328
+ 100% { background-position: 0% 50%; }
329
+ }
330
+
331
+ /* ==========================================
332
+ ACCESSIBILITY - Focus Indicators
333
+ ========================================== */
334
+
335
+ *:focus-visible {
336
+ outline: 2px solid var(--color-primary-500);
337
+ outline-offset: 2px;
338
+ border-radius: var(--radius-sm);
339
+ }
340
+
341
+ /* ==========================================
342
+ REDUCED MOTION
343
+ ========================================== */
344
+
345
+ @media (prefers-reduced-motion: reduce) {
346
+ *,
347
+ *::before,
348
+ *::after {
349
+ animation-duration: 0.01ms !important;
350
+ animation-iteration-count: 1 !important;
351
+ transition-duration: 0.01ms !important;
352
+ }
353
+ }
354
+
355
+ /* ==========================================
356
+ TEXT SELECTION
357
+ ========================================== */
358
+
359
+ ::selection {
360
+ background: rgba(249, 115, 22, 0.3);
361
+ color: #ffffff;
362
+ }
363
+
364
+ ::-moz-selection {
365
+ background: rgba(249, 115, 22, 0.3);
366
+ color: #ffffff;
367
+ }
368
+
369
+ /* ==========================================
370
+ SCROLLBAR STYLING (Dark Mode)
371
+ ========================================== */
372
+
373
+ ::-webkit-scrollbar {
374
+ width: 8px;
375
+ height: 8px;
376
+ }
377
+
378
+ ::-webkit-scrollbar-track {
379
+ background: var(--color-neutral-900);
380
+ }
381
+
382
+ ::-webkit-scrollbar-thumb {
383
+ background: var(--color-neutral-700);
384
+ border-radius: var(--radius-full);
385
+ }
386
+
387
+ ::-webkit-scrollbar-thumb:hover {
388
+ background: var(--color-neutral-600);
389
+ }
390
+
391
+ /* Firefox */
392
+ * {
393
+ scrollbar-width: thin;
394
+ scrollbar-color: var(--color-neutral-700) var(--color-neutral-900);
395
+ }
@@ -0,0 +1,19 @@
1
+ import { afterEach } from 'vitest';
2
+ import { cleanup } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+
5
+ // Cleanup after each test
6
+ afterEach(() => {
7
+ cleanup();
8
+ });
9
+
10
+ // Mock WebSocket for tests
11
+ global.WebSocket = class WebSocket {
12
+ constructor() {
13
+ this.readyState = 1; // OPEN
14
+ }
15
+ send() {}
16
+ close() {}
17
+ addEventListener() {}
18
+ removeEventListener() {}
19
+ };
package/start.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ const { spawn } = require('child_process');
3
+
4
+ console.log('Starting Claude Agent Dashboard...\n');
5
+
6
+ // Start backend server
7
+ const server = spawn('node', ['server.js'], {
8
+ stdio: 'inherit',
9
+ shell: true
10
+ });
11
+
12
+ // Start frontend dev server
13
+ const client = spawn('npx', ['vite'], {
14
+ stdio: 'inherit',
15
+ shell: true
16
+ });
17
+
18
+ // Handle process termination
19
+ process.on('SIGINT', () => {
20
+ console.log('\nShutting down...');
21
+ server.kill();
22
+ client.kill();
23
+ process.exit();
24
+ });
25
+
26
+ server.on('error', (error) => {
27
+ console.error('Server error:', error);
28
+ });
29
+
30
+ client.on('error', (error) => {
31
+ console.error('Client error:', error);
32
+ });
33
+
34
+ console.log('Backend server starting on http://localhost:3001');
35
+ console.log('Frontend dashboard starting on http://localhost:5173');
36
+ console.log('\nPress Ctrl+C to stop both servers\n');
package/vite.config.js ADDED
@@ -0,0 +1,37 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ react({
7
+ babel: {
8
+ plugins: [
9
+ ['babel-plugin-react-compiler', {
10
+ target: '19'
11
+ }]
12
+ ]
13
+ }
14
+ })
15
+ ],
16
+ server: {
17
+ port: 5173,
18
+ host: '127.0.0.1',
19
+ strictPort: false,
20
+ proxy: {
21
+ '/api': {
22
+ target: 'http://localhost:3001',
23
+ changeOrigin: true
24
+ }
25
+ }
26
+ },
27
+ build: {
28
+ rollupOptions: {
29
+ output: {
30
+ manualChunks: {
31
+ 'react-vendor': ['react', 'react-dom'],
32
+ 'icons': ['lucide-react']
33
+ }
34
+ }
35
+ }
36
+ }
37
+ });