@keak/sdk 1.0.9 → 2.0.1

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.
@@ -3,7 +3,7 @@
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import { execSync } from 'child_process';
6
- import { AIHelper, LocalAIHelper } from './ai-helper.js';
6
+ import { LocalAIHelper } from './ai-helper.js';
7
7
  import ConversionDetector from './conversion-detector.js';
8
8
  import { FrameworkConfigManager } from './framework-config.js';
9
9
 
@@ -33,23 +33,23 @@ ${colors.cyan}${colors.bright}
33
33
  ╚═══════════════════════════════════════╝
34
34
  ${colors.reset}
35
35
  `);
36
-
36
+
37
37
  const detector = new ConversionDetector();
38
38
  const targetDir = args[1] || process.cwd();
39
-
39
+
40
40
  console.log(`${colors.blue}🎯 Setting up conversion tracking...${colors.reset}\n`);
41
-
41
+
42
42
  const result = detector.createConversionFiles(targetDir);
43
-
43
+
44
44
  if (result.success) {
45
45
  const report = result.report;
46
-
46
+
47
47
  console.log(`${colors.green}✅ Conversion tracking setup complete!${colors.reset}`);
48
48
  console.log(`${colors.cyan}🌐 Results page: ${result.htmlPath}${colors.reset}`);
49
49
  console.log(`
50
50
  ${colors.blue}📊 Results:${colors.reset}
51
51
  • Files processed: ${report.stats.filesProcessed}
52
- • Files modified: ${report.stats.filesModified}
52
+ • Files modified: ${report.stats.filesModified}
53
53
  • Elements wrapped: ${report.stats.elementsWrapped}
54
54
  `);
55
55
 
@@ -60,7 +60,7 @@ ${colors.blue}📊 Results:${colors.reset}
60
60
  console.log(`
61
61
  ${colors.yellow}🔧 What happened:${colors.reset}
62
62
  1. All React files were scanned automatically
63
- 2. Clickable elements (buttons, links, etc.) were wrapped with components
63
+ 2. Clickable elements (buttons, links, etc.) were wrapped with <Conversion> components
64
64
  3. Backup files (.keak-backup) were created for all changes
65
65
  4. Your components now automatically track conversion events
66
66
 
@@ -70,7 +70,7 @@ ${colors.green}🚀 Your conversion tracking is now active!${colors.reset}
70
70
  console.error(`${colors.red}❌ Failed to setup conversion tracking: ${result.error}${colors.reset}`);
71
71
  process.exit(1);
72
72
  }
73
-
73
+
74
74
  process.exit(0);
75
75
  }
76
76
 
@@ -89,7 +89,6 @@ class KeakInstaller {
89
89
  this.projectRoot = process.cwd();
90
90
  this.framework = null;
91
91
  this.entryFile = null;
92
- this.aiApiKey = process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY;
93
92
  }
94
93
 
95
94
  async run() {
@@ -139,14 +138,14 @@ class KeakInstaller {
139
138
 
140
139
  detectFramework() {
141
140
  const packageJsonPath = path.join(this.projectRoot, 'package.json');
142
-
141
+
143
142
  if (!fs.existsSync(packageJsonPath)) {
144
143
  throw new Error('No package.json found. Are you in a Node.js project?');
145
144
  }
146
-
145
+
147
146
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
148
147
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
149
-
148
+
150
149
  if (deps['next']) {
151
150
  this.framework = 'nextjs';
152
151
  console.log(`${colors.green}✓${colors.reset} Detected: Next.js`);
@@ -213,7 +212,7 @@ class KeakInstaller {
213
212
  };
214
213
 
215
214
  const entries = possibleEntries[this.framework] || possibleEntries.react;
216
-
215
+
217
216
  for (const entry of entries) {
218
217
  const fullPath = path.join(this.projectRoot, entry);
219
218
  if (fs.existsSync(fullPath)) {
@@ -222,10 +221,10 @@ class KeakInstaller {
222
221
  return;
223
222
  }
224
223
  }
225
-
224
+
226
225
  // If no entry file found, try to find any file with ReactDOM.render or createRoot
227
226
  this.entryFile = this.findReactDOMRenderFile();
228
-
227
+
229
228
  if (!this.entryFile) {
230
229
  throw new Error('Could not find React entry file. Please specify manually.');
231
230
  }
@@ -233,16 +232,16 @@ class KeakInstaller {
233
232
 
234
233
  findReactDOMRenderFile() {
235
234
  const searchDirs = ['src', '.'];
236
-
235
+
237
236
  for (const dir of searchDirs) {
238
237
  const fullDir = path.join(this.projectRoot, dir);
239
238
  if (!fs.existsSync(fullDir)) continue;
240
-
239
+
241
240
  const files = this.getAllFiles(fullDir, ['.js', '.jsx', '.ts', '.tsx']);
242
-
241
+
243
242
  for (const file of files) {
244
243
  const content = fs.readFileSync(file, 'utf-8');
245
- if (content.includes('ReactDOM.render') ||
244
+ if (content.includes('ReactDOM.render') ||
246
245
  content.includes('ReactDOM.createRoot') ||
247
246
  content.includes('createRoot(')) {
248
247
  console.log(`${colors.green}✓${colors.reset} Found React render in: ${path.relative(this.projectRoot, file)}`);
@@ -250,46 +249,46 @@ class KeakInstaller {
250
249
  }
251
250
  }
252
251
  }
253
-
252
+
254
253
  return null;
255
254
  }
256
255
 
257
256
  getAllFiles(dir, extensions) {
258
257
  const files = [];
259
-
258
+
260
259
  const items = fs.readdirSync(dir);
261
260
  for (const item of items) {
262
261
  const fullPath = path.join(dir, item);
263
-
262
+
264
263
  // Skip node_modules and other common directories
265
264
  if (item === 'node_modules' || item === '.git' || item === 'dist' || item === 'build') {
266
265
  continue;
267
266
  }
268
-
267
+
269
268
  const stat = fs.statSync(fullPath);
270
269
  if (stat.isDirectory()) {
271
270
  files.push(...this.getAllFiles(fullPath, extensions));
272
- } else if (extensions.some(ext =item.endsWith(ext))) {
271
+ } else if (extensions.some(ext => item.endsWith(ext))) {
273
272
  files.push(fullPath);
274
273
  }
275
274
  }
276
-
275
+
277
276
  return files;
278
277
  }
279
278
 
280
279
  isAlreadyInstalled() {
281
280
  if (!this.entryFile) return false;
282
-
281
+
283
282
  const content = fs.readFileSync(this.entryFile, 'utf-8');
284
- return content.includes('KeakProvider') || content.includes('@keak/sdk');
283
+ return content.includes('useKeak') || content.includes('@keak/sdk');
285
284
  }
286
285
 
287
286
  async autoInstall() {
288
287
  console.log(`\n${colors.blue}🔧 Attempting automatic installation...${colors.reset}\n`);
289
-
288
+
290
289
  const content = fs.readFileSync(this.entryFile, 'utf-8');
291
290
  let modified = content;
292
-
291
+
293
292
  try {
294
293
  if (this.framework === 'nextjs') {
295
294
  modified = this.wrapNextJs(content);
@@ -298,23 +297,23 @@ class KeakInstaller {
298
297
  } else {
299
298
  modified = this.wrapGenericReact(content);
300
299
  }
301
-
300
+
302
301
  if (modified !== content) {
303
302
  // Create backup
304
303
  const backupPath = `${this.entryFile}.backup`;
305
304
  fs.writeFileSync(backupPath, content);
306
305
  console.log(`${colors.cyan}📋 Created backup: ${path.basename(backupPath)}${colors.reset}`);
307
-
306
+
308
307
  // Write modified file
309
308
  fs.writeFileSync(this.entryFile, modified);
310
309
  console.log(`${colors.green}✓${colors.reset} Modified: ${path.relative(this.projectRoot, this.entryFile)}`);
311
-
310
+
312
311
  return true;
313
312
  }
314
313
  } catch (error) {
315
314
  console.log(`${colors.yellow}⚠️ Auto-installation needs help with your setup${colors.reset}`);
316
315
  }
317
-
316
+
318
317
  return false;
319
318
  }
320
319
 
@@ -323,10 +322,15 @@ class KeakInstaller {
323
322
 
324
323
  if (isAppDir) {
325
324
  // Next.js 13+ App Directory
326
- if (!content.includes('KeakProvider')) {
327
- // Add import - include both KeakProvider and KeakToolbar
328
- const importLine = "import { KeakProvider, KeakToolbar } from '@keak/sdk';\n";
325
+ if (!content.includes('useKeak')) {
326
+ // Add 'use client' directive if not present
329
327
  let modified = content;
328
+ if (!modified.includes("'use client'") && !modified.includes('"use client"')) {
329
+ modified = "'use client';\n\n" + modified;
330
+ }
331
+
332
+ // Add import
333
+ const importLine = "import { useKeak, KeakToolbar } from '@keak/sdk';\n";
330
334
 
331
335
  // Add import after existing imports
332
336
  const lastImportIndex = modified.lastIndexOf('import ');
@@ -337,26 +341,34 @@ class KeakInstaller {
337
341
  modified = importLine + modified;
338
342
  }
339
343
 
340
- // Wrap children in body with KeakProvider and add KeakToolbar
341
- const bodyMatch = modified.match(/(<body[^>]*>)([\s\S]*?)(<\/body>)/);
344
+ // Add useKeak() hook at the start of the layout component
345
+ const componentMatch = modified.match(/(export\s+default\s+function\s+\w+\s*\([^)]*\)\s*\{)\s*/);
346
+ if (componentMatch) {
347
+ modified = modified.replace(
348
+ componentMatch[0],
349
+ `${componentMatch[1]}
350
+ useKeak({ debug: true });
351
+ `
352
+ );
353
+ }
354
+
355
+ // Add KeakToolbar before closing body tag
356
+ const bodyMatch = modified.match(/(<\/body>)/);
342
357
  if (bodyMatch) {
343
- const bodyContent = bodyMatch[2].trim();
344
- const wrapped = `${bodyMatch[1]}
345
- <KeakProvider>
346
- ${bodyContent}
347
- <KeakToolbar />
348
- </KeakProvider>
349
- ${bodyMatch[3]}`;
350
- modified = modified.replace(bodyMatch[0], wrapped);
358
+ modified = modified.replace(
359
+ bodyMatch[0],
360
+ ` <KeakToolbar position="bottom-right" />
361
+ ${bodyMatch[0]}`
362
+ );
351
363
  }
352
364
 
353
365
  return modified;
354
366
  }
355
367
  } else {
356
- // Next.js Pages Directory
357
- if (!content.includes('KeakProvider')) {
358
- // Add import - include both KeakProvider and KeakToolbar
359
- const importLine = "import { KeakProvider, KeakToolbar } from '@keak/sdk';\n";
368
+ // Next.js Pages Directory (_app.tsx/jsx/js)
369
+ if (!content.includes('useKeak')) {
370
+ // Add import
371
+ const importLine = "import { useKeak, KeakToolbar } from '@keak/sdk';\n";
360
372
  let modified = content;
361
373
 
362
374
  const lastImportIndex = modified.lastIndexOf('import ');
@@ -367,16 +379,25 @@ ${bodyContent}
367
379
  modified = importLine + modified;
368
380
  }
369
381
 
370
- // Wrap Component with KeakProvider and add KeakToolbar
371
- const componentMatch = modified.match(/(return\s*\(?\s*)([\s\S]*?)(\s*\)?;?\s*})/);
382
+ // Add useKeak() hook at the start of MyApp component
383
+ const componentMatch = modified.match(/(function\s+\w+\s*\([^)]*\)\s*\{)\s*/);
372
384
  if (componentMatch) {
373
- const wrapped = `${componentMatch[1]}
374
- <KeakProvider>
375
- ${componentMatch[2]}
376
- <KeakToolbar />
377
- </KeakProvider>
378
- ${componentMatch[3]}`;
379
- modified = modified.replace(componentMatch[0], wrapped);
385
+ modified = modified.replace(
386
+ componentMatch[0],
387
+ `${componentMatch[1]}
388
+ useKeak({ debug: true });
389
+ `
390
+ );
391
+ }
392
+
393
+ // Add KeakToolbar after Component
394
+ const componentRenderMatch = modified.match(/(<Component\s+[^>]*\/>)/);
395
+ if (componentRenderMatch) {
396
+ modified = modified.replace(
397
+ componentRenderMatch[0],
398
+ `${componentRenderMatch[0]}
399
+ <KeakToolbar position="bottom-right" />`
400
+ );
380
401
  }
381
402
 
382
403
  return modified;
@@ -389,9 +410,9 @@ ${bodyContent}
389
410
  wrapCRA(content) {
390
411
  let modified = content;
391
412
 
392
- // Add import - include both KeakProvider and KeakToolbar
393
- if (!content.includes('KeakProvider')) {
394
- const importLine = "import { KeakProvider, KeakToolbar } from '@keak/sdk';\n";
413
+ // Add import
414
+ if (!content.includes('useKeak')) {
415
+ const importLine = "import { useKeak, KeakToolbar } from '@keak/sdk';\n";
395
416
 
396
417
  const lastImportIndex = modified.lastIndexOf('import ');
397
418
  if (lastImportIndex !== -1) {
@@ -402,36 +423,122 @@ ${bodyContent}
402
423
  }
403
424
  }
404
425
 
405
- // Find ReactDOM.render or createRoot
406
- if (content.includes('ReactDOM.render')) {
407
- // Old React 17 style
408
- const renderMatch = modified.match(/(ReactDOM\.render\s*\(\s*)([\s\S]*?)(\s*,\s*document\.getElementById)/);
409
- if (renderMatch) {
410
- const wrapped = `${renderMatch[1]}
411
- <KeakProvider>
412
- ${renderMatch[2]}
413
- <KeakToolbar />
414
- </KeakProvider>
415
- ${renderMatch[3]}`;
416
- modified = modified.replace(renderMatch[0], wrapped);
426
+ // Check if this is App component (has a component function)
427
+ const hasComponentFunction = content.match(/function\s+\w+\s*\(|const\s+\w+\s*=\s*\([^)]*\)\s*=>/);
428
+
429
+ if (hasComponentFunction) {
430
+ // This is App.tsx/jsx - add hook to component
431
+ const hookAdded = this.addUseKeakHookToComponent(modified);
432
+ if (hookAdded) {
433
+ modified = hookAdded;
417
434
  }
418
- } else if (content.includes('createRoot')) {
419
- // React 18 style
420
- const renderMatch = modified.match(/(root\.render\s*\(\s*)([\s\S]*?)(\s*\))/);
421
- if (renderMatch) {
422
- const wrapped = `${renderMatch[1]}
423
- <KeakProvider>
424
- ${renderMatch[2]}
425
- <KeakToolbar />
426
- </KeakProvider>
427
- ${renderMatch[3]}`;
428
- modified = modified.replace(renderMatch[0], wrapped);
435
+
436
+ // Add toolbar before the closing tag of return
437
+ const returnMatch = modified.match(/(<\/(?:[^>]+)>)\s*\n?\s*(\);?\s*[}$])/m);
438
+ if (returnMatch) {
439
+ modified = modified.replace(
440
+ returnMatch[0],
441
+ `${returnMatch[1]}
442
+ <KeakToolbar position="bottom-right" />
443
+ ${returnMatch[2]}`
444
+ );
445
+ }
446
+ } else {
447
+ // This is index.tsx/jsx - create wrapper component
448
+ // Find ReactDOM.render or createRoot and wrap with a component
449
+ if (content.includes('ReactDOM.render') || content.includes('createRoot')) {
450
+ // Add wrapper component before ReactDOM
451
+ const wrapperComponent = `
452
+ // Keak wrapper component with hook
453
+ function KeakWrapper({ children }) {
454
+ useKeak({ debug: true });
455
+ return (
456
+ <>
457
+ {children}
458
+ <KeakToolbar position="bottom-right" />
459
+ </>
460
+ );
461
+ }
462
+
463
+ `;
464
+ const reactDOMIndex = modified.search(/(ReactDOM\.render|createRoot)/);
465
+ if (reactDOMIndex !== -1) {
466
+ modified = modified.slice(0, reactDOMIndex) + wrapperComponent + modified.slice(reactDOMIndex);
467
+ }
468
+
469
+ // Wrap the rendered component
470
+ if (content.includes('ReactDOM.render')) {
471
+ // Old React 17 style
472
+ const renderMatch = modified.match(/(ReactDOM\.render\s*\(\s*)(<)/);
473
+ if (renderMatch) {
474
+ modified = modified.replace(
475
+ renderMatch[0],
476
+ `${renderMatch[1]}<KeakWrapper>
477
+ ${renderMatch[2]}`
478
+ );
479
+
480
+ const closeMatch = modified.match(/(<\/(?:[^>]+)>)\s*\n?\s*(,\s*document\.getElementById)/);
481
+ if (closeMatch) {
482
+ modified = modified.replace(
483
+ closeMatch[0],
484
+ `${closeMatch[1]}
485
+ </KeakWrapper>${closeMatch[2]}`
486
+ );
487
+ }
488
+ }
489
+ } else if (content.includes('createRoot')) {
490
+ // React 18 style
491
+ const renderMatch = modified.match(/(root\.render\s*\(\s*)(<)/);
492
+ if (renderMatch) {
493
+ modified = modified.replace(
494
+ renderMatch[0],
495
+ `${renderMatch[1]}<KeakWrapper>
496
+ ${renderMatch[2]}`
497
+ );
498
+
499
+ const closeMatch = modified.match(/(<\/(?:[^>]+)>)\s*\n?\s*(\))/);
500
+ if (closeMatch) {
501
+ modified = modified.replace(
502
+ closeMatch[0],
503
+ `${closeMatch[1]}
504
+ </KeakWrapper>${closeMatch[2]}`
505
+ );
506
+ }
507
+ }
508
+ }
429
509
  }
430
510
  }
431
511
 
432
512
  return modified;
433
513
  }
434
514
 
515
+ addUseKeakHookToComponent(content) {
516
+ // Try to add useKeak() hook at the start of the component
517
+ // Match function components
518
+ const functionMatch = content.match(/(function\s+\w+\s*\([^)]*\)\s*\{)\s*/);
519
+ if (functionMatch) {
520
+ return content.replace(
521
+ functionMatch[0],
522
+ `${functionMatch[1]}
523
+ useKeak({ debug: true });
524
+ `
525
+ );
526
+ }
527
+
528
+ // Match arrow function components
529
+ const arrowMatch = content.match(/(const\s+\w+\s*=\s*\([^)]*\)\s*=>\s*\{)\s*/);
530
+ if (arrowMatch) {
531
+ return content.replace(
532
+ arrowMatch[0],
533
+ `${arrowMatch[1]}
534
+ useKeak({ debug: true });
535
+ `
536
+ );
537
+ }
538
+
539
+ return null;
540
+ }
541
+
435
542
  wrapGenericReact(content) {
436
543
  // Generic React app wrapper
437
544
  return this.wrapCRA(content);
@@ -439,52 +546,25 @@ ${bodyContent}
439
546
 
440
547
  async aiAssistedInstall() {
441
548
  console.log(`\n${colors.cyan}🤖 Using AI to help with installation...${colors.reset}\n`);
442
-
549
+
443
550
  const content = fs.readFileSync(this.entryFile, 'utf-8');
444
- const aiHelper = new AIHelper();
445
551
  const localHelper = new LocalAIHelper();
446
-
447
- try {
448
- // First try the Keak AI service (free, no API key needed)
449
- console.log(`${colors.blue}Connecting to Keak AI service...${colors.reset}`);
450
- const modifiedContent = await Promise.race([
451
- aiHelper.getInstallationHelp(content, this.entryFile, this.framework),
452
- new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000))
453
- ]);
454
-
455
- if (modifiedContent && modifiedContent !== content) {
456
- // Create backup
457
- const backupPath = `${this.entryFile}.backup`;
458
- fs.writeFileSync(backupPath, content);
459
- console.log(`${colors.cyan}📋 Created backup: ${path.basename(backupPath)}${colors.reset}`);
460
-
461
- // Write modified file
462
- fs.writeFileSync(this.entryFile, modifiedContent);
463
- console.log(`${colors.green}✓${colors.reset} AI successfully updated: ${path.relative(this.projectRoot, this.entryFile)}`);
464
-
465
- console.log(`\n${colors.green}${colors.bright}✨ Success! Keak has been installed with AI assistance.${colors.reset}`);
466
- this.showPostInstallInstructions();
467
- return;
468
- }
469
- } catch (error) {
470
- console.log(`${colors.yellow}Online AI unavailable, using local intelligence...${colors.reset}`);
471
- }
472
-
473
- // Fallback to local AI helper
552
+
553
+ // Use local AI helper (updated to use hook-based format)
474
554
  try {
475
555
  const isTypeScript = this.entryFile.endsWith('.ts') || this.entryFile.endsWith('.tsx');
476
- const modifiedContent = localHelper.addKeakProvider(content, isTypeScript);
477
-
556
+ const modifiedContent = localHelper.addKeakHook(content, isTypeScript);
557
+
478
558
  if (modifiedContent && modifiedContent !== content) {
479
559
  // Create backup
480
560
  const backupPath = `${this.entryFile}.backup`;
481
561
  fs.writeFileSync(backupPath, content);
482
562
  console.log(`${colors.cyan}📋 Created backup: ${path.basename(backupPath)}${colors.reset}`);
483
-
563
+
484
564
  // Write modified file
485
565
  fs.writeFileSync(this.entryFile, modifiedContent);
486
566
  console.log(`${colors.green}✓${colors.reset} Successfully updated: ${path.relative(this.projectRoot, this.entryFile)}`);
487
-
567
+
488
568
  console.log(`\n${colors.green}${colors.bright}✨ Success! Keak has been installed.${colors.reset}`);
489
569
  this.showPostInstallInstructions();
490
570
  return;
@@ -492,16 +572,16 @@ ${bodyContent}
492
572
  } catch (error) {
493
573
  console.log(`${colors.yellow}Automated installation needs manual help.${colors.reset}`);
494
574
  }
495
-
575
+
496
576
  // If all else fails, show manual instructions
497
577
  this.showManualInstructions();
498
578
  }
499
579
 
500
580
  showManualInstructions() {
501
- const relativeEntry = this.entryFile
581
+ const relativeEntry = this.entryFile
502
582
  ? path.relative(this.projectRoot, this.entryFile)
503
583
  : 'your entry file (e.g., src/index.tsx or src/App.tsx)';
504
-
584
+
505
585
  console.log(`
506
586
  ${colors.yellow}📝 Manual Installation Required${colors.reset}
507
587
 
@@ -510,10 +590,13 @@ Please add Keak to your app manually:
510
590
  1. Open ${colors.cyan}${relativeEntry}${colors.reset}
511
591
 
512
592
  2. Add this import at the top:
513
- ${colors.green}import { KeakProvider } from '@keak/sdk';${colors.reset}
593
+ ${colors.green}import { useKeak, KeakToolbar } from '@keak/sdk';${colors.reset}
514
594
 
515
- 3. Wrap your main component:
516
- ${colors.green}<KeakProvider><YourApp /></KeakProvider>${colors.reset}
595
+ 3. Add the hook in your component:
596
+ ${colors.green}useKeak({ debug: true });${colors.reset}
597
+
598
+ 4. Add the toolbar to your JSX:
599
+ ${colors.green}<KeakToolbar position="bottom-right" />${colors.reset}
517
600
 
518
601
  Example for ${this.framework}:
519
602
  ${this.getFrameworkExample()}
@@ -524,36 +607,52 @@ ${this.getFrameworkExample()}
524
607
  const examples = {
525
608
  'nextjs': `
526
609
  // app/layout.tsx
527
- import { KeakProvider } from '@keak/sdk';
610
+ 'use client';
611
+
612
+ import { useKeak, KeakToolbar } from '@keak/sdk';
528
613
 
529
614
  export default function RootLayout({ children }) {
615
+ useKeak({ debug: true });
616
+
530
617
  return (
531
- <html><body>
532
- <KeakProvider>
618
+ <html>
619
+ <body>
533
620
  {children}
534
- </KeakProvider>
535
- </body></html>);
621
+ <KeakToolbar position="bottom-right" />
622
+ </body>
623
+ </html>
624
+ );
536
625
  }`,
537
626
  'create-react-app': `
538
- // src/index.js
539
- import { KeakProvider } from '@keak/sdk';
540
-
541
- root.render(
542
- <KeakProvider>
543
- <App />
544
- </KeakProvider>
545
- );`,
627
+ // src/App.tsx
628
+ import { useKeak, KeakToolbar } from '@keak/sdk';
629
+
630
+ function App() {
631
+ useKeak({ debug: true });
632
+
633
+ return (
634
+ <div className="App">
635
+ {/* Your app content */}
636
+ <KeakToolbar position="bottom-right" />
637
+ </div>
638
+ );
639
+ }`,
546
640
  'vite-react': `
547
- // src/main.tsx
548
- import { KeakProvider } from '@keak/sdk';
549
-
550
- ReactDOM.createRoot(document.getElementById('root')).render(
551
- <KeakProvider>
552
- <App />
553
- </KeakProvider>
554
- );`
641
+ // src/App.tsx
642
+ import { useKeak, KeakToolbar } from '@keak/sdk';
643
+
644
+ function App() {
645
+ useKeak({ debug: true });
646
+
647
+ return (
648
+ <>
649
+ {/* Your app content */}
650
+ <KeakToolbar position="bottom-right" />
651
+ </>
652
+ );
653
+ }`
555
654
  };
556
-
655
+
557
656
  return examples[this.framework] || examples['create-react-app'];
558
657
  }
559
658
 
@@ -567,6 +666,7 @@ Start your development server and look for the ${colors.bright}Keak toolbar${col
567
666
  in the ${colors.bright}bottom-right corner${colors.reset} of your app.
568
667
 
569
668
  ${colors.blue}Quick Tips:${colors.reset}
669
+ • The toolbar auto-shows in development mode only
570
670
  • Click the toolbar to expand it
571
671
  • Use "Select" to pick elements for testing
572
672
  • Try the AI prompts for optimization ideas
@@ -574,8 +674,7 @@ ${colors.blue}Quick Tips:${colors.reset}
574
674
 
575
675
  ${colors.blue}🔧 Important for Next.js users:${colors.reset}
576
676
  • Keak requires Babel for source mapping
577
- • We've disabled Turbopack in your dev script
578
- • Use ${colors.bright}npm run dev:turbo${colors.reset} if you need Turbopack
677
+ • We've configured your build tools automatically
579
678
  • ${colors.yellow}Restart your dev server${colors.reset} for changes to take effect
580
679
 
581
680
  ${colors.blue}🎯 Want conversion tracking?${colors.reset}
@@ -607,7 +706,7 @@ const installer = new KeakInstaller();
607
706
  installer.run().catch((error) => {
608
707
  // Only show error in verbose mode or when run explicitly (not postinstall)
609
708
  const isPostInstall = process.env.npm_lifecycle_event === 'postinstall';
610
-
709
+
611
710
  if (!isPostInstall) {
612
711
  console.error(`${colors.red}Installation failed: ${error.message}${colors.reset}`);
613
712
  process.exit(1);
@@ -615,4 +714,4 @@ installer.run().catch((error) => {
615
714
  // Silent fail for postinstall - don't block package installation
616
715
  console.log(`${colors.yellow}ℹ️ Keak auto-setup skipped. Run 'npx keak-setup' manually when ready.${colors.reset}`);
617
716
  }
618
- });
717
+ });