ai-site-pilot 0.5.13 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -1,559 +1,559 @@
1
- # AI Instructions for ai-site-pilot
2
-
3
- This file helps AI coding assistants (Claude, GPT, Copilot) integrate ai-site-pilot into projects.
4
-
5
- ## What is ai-site-pilot?
6
-
7
- A drop-in AI chat widget that can **control and navigate websites**. The AI can execute tools to filter content, open modals, navigate sections, and more.
8
-
9
- **Key features:**
10
- - Works with any AI model via OpenRouter (Gemini, GPT-4, Claude, Llama)
11
- - Fast & affordable with Gemini 2.5 Flash-Lite default
12
- - Auto-generates system prompts from site content
13
- - Streaming responses with tool execution
14
-
15
- ## IMPORTANT: Keeping Chatbot in Sync with Site Content
16
-
17
- **The chatbot must always reflect the current site content.** To achieve this:
18
-
19
- 1. **Find where site data lives** - Look for constants files, data files, CMS exports, or API endpoints that contain the site's content (products, services, team, etc.)
20
-
21
- 2. **Import from the same source** - The API route should import from these existing data sources, NOT duplicate the data
22
-
23
- 3. **Maintain this pattern** - When updating site content, the chatbot automatically stays in sync
24
-
25
- ### Example Pattern
26
-
27
- ```typescript
28
- // lib/data.ts - The site's single source of truth
29
- export const CLASSES = [
30
- { id: 'ballet', name: 'Ballet', description: 'Classical ballet', price: '$80/mo' },
31
- { id: 'jazz', name: 'Jazz', description: 'High-energy jazz', price: '$75/mo' },
32
- ];
33
-
34
- export const TEACHERS = [
35
- { id: 'sarah', name: 'Sarah Johnson', role: 'Owner', bio: '15 years experience' },
36
- ];
37
-
38
- export const SITE_INFO = {
39
- name: 'Dance Studio',
40
- email: 'info@studio.com',
41
- phone: '555-1234',
42
- };
43
- ```
44
-
45
- ```typescript
46
- // app/api/chat/route.ts - Imports from the SAME source
47
- import { CLASSES, TEACHERS, SITE_INFO } from '@/lib/data';
48
- import { createHandler } from 'ai-site-pilot/api';
49
- import { defineTool } from 'ai-site-pilot/tools';
50
-
51
- // Define tools (plain objects work too, defineTool just adds type safety)
52
- const navigateTool = defineTool({
53
- name: 'navigate_to_section',
54
- description: 'Navigate to a section of the page',
55
- parameters: {
56
- type: 'object',
57
- properties: {
58
- section: { type: 'string', enum: ['home', 'classes', 'teachers', 'contact'] },
59
- },
60
- required: ['section'],
61
- },
62
- });
63
-
64
- export const POST = createHandler({
65
- siteContent: {
66
- name: SITE_INFO.name,
67
- items: [
68
- ...CLASSES.map(c => ({ ...c, category: 'class' })),
69
- ...TEACHERS.map(t => ({ ...t, category: 'teacher' })),
70
- ],
71
- contact: {
72
- email: SITE_INFO.email,
73
- phone: SITE_INFO.phone,
74
- },
75
- },
76
- tools: [navigateTool],
77
- });
78
- ```
79
-
80
- ```tsx
81
- // components/ClassList.tsx - Also uses the same source
82
- import { CLASSES } from '@/lib/data';
83
-
84
- export function ClassList() {
85
- return CLASSES.map(c => <ClassCard key={c.id} {...c} />);
86
- }
87
- ```
88
-
89
- **Update `lib/data.ts` → Both site AND chatbot update automatically.**
90
-
91
- ### Route Discovery Checklist (CRITICAL)
92
-
93
- Before setting up ai-site-pilot, you MUST discover all routes and content. Missing pages leads to broken navigation.
94
-
95
- **Step 1: Enumerate ALL routes**
96
- ```bash
97
- # Find all page files (Next.js App Router)
98
- find src/app -name "page.tsx" -o -name "page.js" | sort
99
-
100
- # Or for Pages Router
101
- find src/pages -name "*.tsx" -o -name "*.js" | grep -v "_" | sort
102
- ```
103
-
104
- **Step 2: Build the pages array from actual routes**
105
- ```typescript
106
- // Map file paths to route names
107
- // src/app/page.tsx → 'home'
108
- // src/app/about/page.tsx → 'about'
109
- // src/app/classes/page.tsx → 'classes'
110
- // src/app/contact/page.tsx → 'contact'
111
-
112
- pages: ['home', 'about', 'classes', 'contact'] // Must match actual routes!
113
- ```
114
-
115
- **Step 3: Find data sources for each page**
116
- For each page.tsx, check:
117
- - Inline data arrays (e.g., `const classes = [...]`)
118
- - Imported data (e.g., `import { CLASSES } from '@/lib/data'`)
119
- - Component props passed from parent layouts
120
- - API calls or database queries
121
-
122
- **Step 4: Consolidate into shared data file**
123
- If data is scattered, create a shared file:
124
- ```typescript
125
- // lib/data.ts - Single source of truth
126
- export const SITE_INFO = { name: '...', email: '...', phone: '...' };
127
- export const CLASSES = [...];
128
- export const TEACHERS = [...];
129
- export const FAQS = [...];
130
- ```
131
-
132
- **Step 5: Verify navigation tool enum matches routes**
133
- ```typescript
134
- const navigateTool = defineTool({
135
- name: 'navigate_to_section',
136
- parameters: {
137
- properties: {
138
- section: {
139
- type: 'string',
140
- // This MUST include all navigable pages/sections
141
- enum: ['home', 'about', 'classes', 'teachers', 'schedule', 'contact'],
142
- },
143
- },
144
- },
145
- });
146
- ```
147
-
148
- ### Common Mistakes to Avoid
149
-
150
- 1. **Missing subpages** - Check for nested routes like `/about/team`, `/about/history`
151
- 2. **Hardcoded pages array** - Don't copy from templates; verify against actual routes
152
- 3. **Stale navigation enums** - If you add a new page, update the tool enum
153
- 4. **Duplicated data** - Always import from shared source, never copy values
154
-
155
- ### Making Tools Execute Reliably
156
-
157
- By default, AI models may describe where content is instead of using tools to navigate there. Add explicit instructions to make tools execute:
158
-
159
- ```typescript
160
- siteContent: {
161
- // ... your content
162
- additionalContext: `
163
- IMPORTANT - Tool Usage:
164
- - When users ask about classes, ALWAYS use navigate_to_section to show them, then explain.
165
- - When users ask about teachers, ALWAYS navigate to the team section.
166
- - DO NOT just describe where to find things - USE THE TOOLS to take users there directly.
167
- - Be proactive: if discussing a topic, navigate to show it.
168
- `.trim(),
169
- }
170
-
171
- // Or with manual systemPrompt:
172
- systemPrompt: `...
173
- ## CRITICAL: Tool Usage
174
- You MUST use tools proactively. When discussing any topic:
175
- 1. First, use the relevant tool to navigate/show/filter
176
- 2. Then, provide your explanation
177
- Never just describe where something is - take the user there!
178
- ...`
179
- ```
180
-
181
- ## Quick Setup (Recommended)
182
-
183
- ### 1. Install
184
-
185
- ```bash
186
- npm install ai-site-pilot
187
- ```
188
-
189
- ### 2. Configure Tailwind (Required)
190
-
191
- **Tailwind v4** (CSS-based):
192
- ```css
193
- @import "tailwindcss";
194
- @source "../../node_modules/ai-site-pilot/dist/**/*.{js,mjs}";
195
- ```
196
-
197
- **Tailwind v3** (JS config):
198
- ```js
199
- // tailwind.config.js
200
- module.exports = {
201
- content: [
202
- './app/**/*.{js,ts,jsx,tsx}',
203
- './components/**/*.{js,ts,jsx,tsx}',
204
- './node_modules/ai-site-pilot/dist/**/*.{js,mjs}',
205
- ],
206
- }
207
- ```
208
-
209
- ### 3. Create API Route with `siteContent`
210
-
211
- The easiest way - just pass your site's data and the prompt is auto-generated:
212
-
213
- ```typescript
214
- // app/api/chat/route.ts
215
- import { createHandler } from 'ai-site-pilot/api';
216
- import { defineTool } from 'ai-site-pilot/tools';
217
-
218
- // Define tools the AI can use
219
- const navigateTool = defineTool({
220
- name: 'navigate_to_section',
221
- description: 'Scroll to a section of the page',
222
- parameters: {
223
- type: 'object',
224
- properties: {
225
- section: {
226
- type: 'string',
227
- description: 'Section ID to navigate to',
228
- enum: ['hero', 'services', 'about', 'contact'],
229
- },
230
- },
231
- required: ['section'],
232
- },
233
- });
234
-
235
- const showServiceTool = defineTool({
236
- name: 'show_service',
237
- description: 'Show details about a specific service',
238
- parameters: {
239
- type: 'object',
240
- properties: {
241
- serviceId: {
242
- type: 'string',
243
- description: 'The service ID',
244
- },
245
- },
246
- required: ['serviceId'],
247
- },
248
- });
249
-
250
- // Create handler with site content - prompt is auto-generated!
251
- export const POST = createHandler({
252
- model: 'google/gemini-2.5-flash-lite',
253
- siteContent: {
254
- name: 'Acme Dance Studio',
255
- type: 'dance studio',
256
- description: 'Premier dance education for all ages',
257
- personality: 'warm, encouraging, and helpful',
258
- pages: ['home', 'classes', 'teachers', 'schedule', 'contact'],
259
- items: [
260
- // Classes
261
- { id: 'ballet', name: 'Ballet', category: 'class', description: 'Classical ballet for ages 3-adult', price: '$80/month' },
262
- { id: 'jazz', name: 'Jazz', category: 'class', description: 'High-energy jazz for ages 6+', price: '$75/month' },
263
- { id: 'hip-hop', name: 'Hip Hop', category: 'class', description: 'Street dance styles for ages 8+', price: '$70/month' },
264
- // Teachers
265
- { id: 'sarah', name: 'Sarah Johnson', category: 'teacher', description: 'Owner, 15 years experience, specializes in ballet' },
266
- { id: 'mike', name: 'Mike Chen', category: 'teacher', description: 'Hip hop and jazz instructor, 8 years experience' },
267
- ],
268
- faqs: [
269
- { question: 'What should I wear?', answer: 'Leotard and ballet slippers for ballet, athletic wear for jazz and hip hop.' },
270
- { question: 'Do you offer trial classes?', answer: 'Yes! First class is free for new students.' },
271
- ],
272
- contact: {
273
- email: 'info@acmedance.com',
274
- phone: '555-123-4567',
275
- address: '123 Dance Street, NYC',
276
- hours: 'Mon-Sat 9am-8pm',
277
- },
278
- },
279
- tools: [navigateTool, showServiceTool],
280
- });
281
- ```
282
-
283
- **The AI now automatically knows:**
284
- - All your classes, teachers, pricing
285
- - FAQs and contact info
286
- - What tools to use and when
287
-
288
- ### 4. Add the Chat Widget
289
-
290
- ```tsx
291
- // components/ChatWidget.tsx
292
- 'use client';
293
-
294
- import { SitePilot } from 'ai-site-pilot';
295
- import 'ai-site-pilot/styles.css';
296
-
297
- export function ChatWidget() {
298
- const handleToolCall = (name: string, args: Record<string, unknown>) => {
299
- switch (name) {
300
- case 'navigate_to_section':
301
- document.getElementById(args.section as string)?.scrollIntoView({
302
- behavior: 'smooth',
303
- });
304
- break;
305
- case 'show_service':
306
- // Dispatch event for your page to handle
307
- window.dispatchEvent(new CustomEvent('show-service', {
308
- detail: { serviceId: args.serviceId },
309
- }));
310
- break;
311
- }
312
- };
313
-
314
- return (
315
- <SitePilot
316
- apiEndpoint="/api/chat"
317
- onToolCall={handleToolCall}
318
- suggestions={[
319
- { text: 'What classes do you offer?', icon: '💃' },
320
- { text: 'Meet the teachers', icon: '👩‍🏫' },
321
- { text: 'Contact us', icon: '📞' },
322
- ]}
323
- theme={{ accent: 'pink' }} // or accentColor: '#ec4899'
324
- welcomeMessage="Hi! I'm your dance studio assistant. How can I help you today?"
325
- />
326
- );
327
- }
328
- ```
329
-
330
- ### 5. Environment Variable
331
-
332
- ```bash
333
- # .env.local
334
- OPENROUTER_API_KEY=sk-or-...
335
- ```
336
-
337
- Get your API key at [openrouter.ai](https://openrouter.ai) and add credits to your account.
338
-
339
- ## Alternative: Manual System Prompt
340
-
341
- If you need full control, use `systemPrompt` instead of `siteContent`:
342
-
343
- ```typescript
344
- export const POST = createHandler({
345
- model: 'google/gemini-2.5-flash-lite',
346
- systemPrompt: `You are an assistant for Acme Dance Studio.
347
-
348
- ## Classes
349
- - Ballet: Ages 3-adult, $80/month
350
- - Jazz: Ages 6+, $75/month
351
- - Hip Hop: Ages 8+, $70/month
352
-
353
- ## Tools
354
- - navigate_to_section: Scroll to a section (hero, classes, teachers, contact)
355
- - show_service: Show details about a class
356
-
357
- When users ask about classes, provide specific details.
358
- Use tools proactively to show relevant content.`,
359
- tools: [navigateTool, showServiceTool],
360
- });
361
- ```
362
-
363
- ## SiteContent Schema
364
-
365
- ```typescript
366
- interface SiteContent {
367
- name: string; // Business name
368
- type?: string; // Business type (e.g., 'dance studio')
369
- description?: string; // Brief description
370
- personality?: string; // AI personality (e.g., 'warm and helpful')
371
- pages?: string[]; // Available navigation pages
372
- items?: SiteContentItem[]; // Products, services, team, etc.
373
- faqs?: Array<{ question: string; answer: string }>;
374
- contact?: {
375
- email?: string;
376
- phone?: string;
377
- address?: string;
378
- hours?: string;
379
- };
380
- additionalContext?: string; // Extra info for the prompt
381
- }
382
-
383
- interface SiteContentItem {
384
- id: string; // Unique identifier
385
- name: string; // Display name
386
- category?: string; // Category (e.g., 'class', 'teacher', 'product')
387
- description?: string; // Description
388
- [key: string]: unknown; // Any extra fields (price, duration, etc.)
389
- }
390
- ```
391
-
392
- ## Theme Presets
393
-
394
- Use preset names for easy theming:
395
-
396
- ```tsx
397
- <SitePilot theme={{ accent: 'pink' }} /> // Hot pink
398
- <SitePilot theme={{ accent: 'amber' }} /> // Default orange/amber
399
- <SitePilot theme={{ accent: 'blue' }} /> // Primary blue
400
- <SitePilot theme={{ accent: 'green' }} /> // Emerald green
401
- <SitePilot theme={{ accent: 'purple' }} /> // Violet purple
402
- <SitePilot theme={{ accent: 'cyan' }} /> // Teal cyan
403
- ```
404
-
405
- Or use a custom hex color:
406
-
407
- ```tsx
408
- <SitePilot theme={{ accentColor: '#8b5cf6' }} />
409
- ```
410
-
411
- ## Tool-Only Response Handling
412
-
413
- When the AI uses tools without text, customize the fallback message:
414
-
415
- ```tsx
416
- import { SitePilot, createFallbackMessageGenerator } from 'ai-site-pilot';
417
-
418
- const generateFallback = createFallbackMessageGenerator({
419
- navigate_to_section: (args) => `Scrolled to **${args.section}**.`,
420
- show_service: (args) => `Showing details for **${args.serviceId}**.`,
421
- filter_products: (args) => `Filtered to **${args.category}** products.`,
422
- });
423
-
424
- <SitePilot
425
- apiEndpoint="/api/chat"
426
- generateFallbackMessage={generateFallback}
427
- />
428
- ```
429
-
430
- ## Full Props Reference
431
-
432
- ```typescript
433
- interface SitePilotProps {
434
- // Required
435
- apiEndpoint: string;
436
-
437
- // Tool handling
438
- onToolCall?: (name: string, args: Record<string, unknown>) => void;
439
- generateFallbackMessage?: (toolName: string, args: Record<string, unknown>) => string;
440
-
441
- // UI customization
442
- suggestions?: Array<{ text: string; icon?: string }>;
443
- welcomeMessage?: string;
444
- placeholder?: string;
445
- defaultOpen?: boolean;
446
- position?: 'bottom-right' | 'bottom-left';
447
-
448
- // Theme
449
- theme?: {
450
- accent?: 'amber' | 'pink' | 'blue' | 'green' | 'purple' | 'red' | 'cyan' | 'orange';
451
- accentColor?: string; // Hex color (overrides accent)
452
- backgroundColor?: string;
453
- radius?: number;
454
- };
455
-
456
- // Features
457
- features?: {
458
- speech?: boolean; // Voice input
459
- tts?: boolean; // Text-to-speech
460
- fullscreen?: boolean; // Fullscreen toggle
461
- };
462
- }
463
- ```
464
-
465
- ## Common Patterns
466
-
467
- ### E-commerce Site
468
-
469
- ```typescript
470
- siteContent: {
471
- name: 'MyStore',
472
- type: 'online store',
473
- items: [
474
- { id: 'laptop-1', name: 'MacBook Pro', category: 'product', price: '$1999', inStock: true },
475
- { id: 'phone-1', name: 'iPhone 15', category: 'product', price: '$999', inStock: true },
476
- ],
477
- pages: ['home', 'products', 'cart', 'checkout'],
478
- }
479
-
480
- // Tools: search_products, filter_by_category, add_to_cart, open_product
481
- ```
482
-
483
- ### Portfolio Site
484
-
485
- ```typescript
486
- siteContent: {
487
- name: 'Jane Developer',
488
- type: 'portfolio',
489
- items: [
490
- { id: 'project-1', name: 'Acme Dashboard', category: 'project', status: 'Live', tech: 'React, Node' },
491
- { id: 'project-2', name: 'FitTrack App', category: 'project', status: 'Live', tech: 'React Native' },
492
- ],
493
- pages: ['hero', 'projects', 'about', 'contact'],
494
- }
495
-
496
- // Tools: filter_projects, open_project_modal, navigate_to_section, open_contact
497
- ```
498
-
499
- ### SaaS Landing Page
500
-
501
- ```typescript
502
- siteContent: {
503
- name: 'CloudSync',
504
- type: 'SaaS platform',
505
- description: 'Real-time data synchronization for teams',
506
- items: [
507
- { id: 'starter', name: 'Starter Plan', category: 'pricing', price: '$9/mo', features: '5 users, 10GB' },
508
- { id: 'pro', name: 'Pro Plan', category: 'pricing', price: '$29/mo', features: '25 users, 100GB' },
509
- ],
510
- faqs: [
511
- { question: 'Is there a free trial?', answer: 'Yes, 14-day free trial on all plans.' },
512
- ],
513
- }
514
-
515
- // Tools: navigate_to_section, show_pricing, open_signup, open_demo
516
- ```
517
-
518
- ## Troubleshooting
519
-
520
- ### Button only shows icon, no "Ask AI" text
521
- Your Tailwind config isn't scanning the package.
522
-
523
- **Tailwind v4**: Add to your CSS:
524
- ```css
525
- @source "../../node_modules/ai-site-pilot/dist/**/*.{js,mjs}";
526
- ```
527
-
528
- **Tailwind v3**: Add to `tailwind.config.js`:
529
- ```js
530
- content: ['./node_modules/ai-site-pilot/dist/**/*.{js,mjs}']
531
- ```
532
-
533
- ### Theme colors not working
534
- Use component props, not CSS variables:
535
- ```tsx
536
- // Good
537
- <SitePilot theme={{ accent: 'pink' }} />
538
-
539
- // Bad - don't set CSS vars directly
540
- ```
541
-
542
- ### AI gives generic responses
543
- Use `siteContent` to provide actual data about your site. The AI only knows what you tell it.
544
-
545
- ### Tools not executing
546
- 1. Check `onToolCall` is passed to SitePilot
547
- 2. Verify tool names match between API and client handler
548
- 3. Check browser console for errors
549
-
550
- ## Available Models
551
-
552
- | Model | ID | Notes |
553
- |-------|-----|-------|
554
- | Gemini 2.5 Flash-Lite | `google/gemini-2.5-flash-lite` | Fast, affordable (default) |
555
- | GPT-4o | `openai/gpt-4o` | Best overall |
556
- | Claude 3.5 Sonnet | `anthropic/claude-3.5-sonnet` | Best for coding |
557
- | Llama 3.1 70B | `meta-llama/llama-3.1-70b-instruct` | Open source |
558
-
559
- See all models at [openrouter.ai/models](https://openrouter.ai/models)
1
+ # AI Instructions for ai-site-pilot
2
+
3
+ This file helps AI coding assistants (Claude, GPT, Copilot) integrate ai-site-pilot into projects.
4
+
5
+ ## What is ai-site-pilot?
6
+
7
+ A drop-in AI chat widget that can **control and navigate websites**. The AI can execute tools to filter content, open modals, navigate sections, and more.
8
+
9
+ **Key features:**
10
+ - Works with any AI model via OpenRouter (Gemini, GPT-4, Claude, Llama)
11
+ - Fast & affordable with Gemini 2.5 Flash-Lite default
12
+ - Auto-generates system prompts from site content
13
+ - Streaming responses with tool execution
14
+
15
+ ## IMPORTANT: Keeping Chatbot in Sync with Site Content
16
+
17
+ **The chatbot must always reflect the current site content.** To achieve this:
18
+
19
+ 1. **Find where site data lives** - Look for constants files, data files, CMS exports, or API endpoints that contain the site's content (products, services, team, etc.)
20
+
21
+ 2. **Import from the same source** - The API route should import from these existing data sources, NOT duplicate the data
22
+
23
+ 3. **Maintain this pattern** - When updating site content, the chatbot automatically stays in sync
24
+
25
+ ### Example Pattern
26
+
27
+ ```typescript
28
+ // lib/data.ts - The site's single source of truth
29
+ export const CLASSES = [
30
+ { id: 'ballet', name: 'Ballet', description: 'Classical ballet', price: '$80/mo' },
31
+ { id: 'jazz', name: 'Jazz', description: 'High-energy jazz', price: '$75/mo' },
32
+ ];
33
+
34
+ export const TEACHERS = [
35
+ { id: 'sarah', name: 'Sarah Johnson', role: 'Owner', bio: '15 years experience' },
36
+ ];
37
+
38
+ export const SITE_INFO = {
39
+ name: 'Dance Studio',
40
+ email: 'info@studio.com',
41
+ phone: '555-1234',
42
+ };
43
+ ```
44
+
45
+ ```typescript
46
+ // app/api/chat/route.ts - Imports from the SAME source
47
+ import { CLASSES, TEACHERS, SITE_INFO } from '@/lib/data';
48
+ import { createHandler } from 'ai-site-pilot/api';
49
+ import { defineTool } from 'ai-site-pilot/tools';
50
+
51
+ // Define tools (plain objects work too, defineTool just adds type safety)
52
+ const navigateTool = defineTool({
53
+ name: 'navigate_to_section',
54
+ description: 'Navigate to a section of the page',
55
+ parameters: {
56
+ type: 'object',
57
+ properties: {
58
+ section: { type: 'string', enum: ['home', 'classes', 'teachers', 'contact'] },
59
+ },
60
+ required: ['section'],
61
+ },
62
+ });
63
+
64
+ export const POST = createHandler({
65
+ siteContent: {
66
+ name: SITE_INFO.name,
67
+ items: [
68
+ ...CLASSES.map(c => ({ ...c, category: 'class' })),
69
+ ...TEACHERS.map(t => ({ ...t, category: 'teacher' })),
70
+ ],
71
+ contact: {
72
+ email: SITE_INFO.email,
73
+ phone: SITE_INFO.phone,
74
+ },
75
+ },
76
+ tools: [navigateTool],
77
+ });
78
+ ```
79
+
80
+ ```tsx
81
+ // components/ClassList.tsx - Also uses the same source
82
+ import { CLASSES } from '@/lib/data';
83
+
84
+ export function ClassList() {
85
+ return CLASSES.map(c => <ClassCard key={c.id} {...c} />);
86
+ }
87
+ ```
88
+
89
+ **Update `lib/data.ts` → Both site AND chatbot update automatically.**
90
+
91
+ ### Route Discovery Checklist (CRITICAL)
92
+
93
+ Before setting up ai-site-pilot, you MUST discover all routes and content. Missing pages leads to broken navigation.
94
+
95
+ **Step 1: Enumerate ALL routes**
96
+ ```bash
97
+ # Find all page files (Next.js App Router)
98
+ find src/app -name "page.tsx" -o -name "page.js" | sort
99
+
100
+ # Or for Pages Router
101
+ find src/pages -name "*.tsx" -o -name "*.js" | grep -v "_" | sort
102
+ ```
103
+
104
+ **Step 2: Build the pages array from actual routes**
105
+ ```typescript
106
+ // Map file paths to route names
107
+ // src/app/page.tsx → 'home'
108
+ // src/app/about/page.tsx → 'about'
109
+ // src/app/classes/page.tsx → 'classes'
110
+ // src/app/contact/page.tsx → 'contact'
111
+
112
+ pages: ['home', 'about', 'classes', 'contact'] // Must match actual routes!
113
+ ```
114
+
115
+ **Step 3: Find data sources for each page**
116
+ For each page.tsx, check:
117
+ - Inline data arrays (e.g., `const classes = [...]`)
118
+ - Imported data (e.g., `import { CLASSES } from '@/lib/data'`)
119
+ - Component props passed from parent layouts
120
+ - API calls or database queries
121
+
122
+ **Step 4: Consolidate into shared data file**
123
+ If data is scattered, create a shared file:
124
+ ```typescript
125
+ // lib/data.ts - Single source of truth
126
+ export const SITE_INFO = { name: '...', email: '...', phone: '...' };
127
+ export const CLASSES = [...];
128
+ export const TEACHERS = [...];
129
+ export const FAQS = [...];
130
+ ```
131
+
132
+ **Step 5: Verify navigation tool enum matches routes**
133
+ ```typescript
134
+ const navigateTool = defineTool({
135
+ name: 'navigate_to_section',
136
+ parameters: {
137
+ properties: {
138
+ section: {
139
+ type: 'string',
140
+ // This MUST include all navigable pages/sections
141
+ enum: ['home', 'about', 'classes', 'teachers', 'schedule', 'contact'],
142
+ },
143
+ },
144
+ },
145
+ });
146
+ ```
147
+
148
+ ### Common Mistakes to Avoid
149
+
150
+ 1. **Missing subpages** - Check for nested routes like `/about/team`, `/about/history`
151
+ 2. **Hardcoded pages array** - Don't copy from templates; verify against actual routes
152
+ 3. **Stale navigation enums** - If you add a new page, update the tool enum
153
+ 4. **Duplicated data** - Always import from shared source, never copy values
154
+
155
+ ### Making Tools Execute Reliably
156
+
157
+ By default, AI models may describe where content is instead of using tools to navigate there. Add explicit instructions to make tools execute:
158
+
159
+ ```typescript
160
+ siteContent: {
161
+ // ... your content
162
+ additionalContext: `
163
+ IMPORTANT - Tool Usage:
164
+ - When users ask about classes, ALWAYS use navigate_to_section to show them, then explain.
165
+ - When users ask about teachers, ALWAYS navigate to the team section.
166
+ - DO NOT just describe where to find things - USE THE TOOLS to take users there directly.
167
+ - Be proactive: if discussing a topic, navigate to show it.
168
+ `.trim(),
169
+ }
170
+
171
+ // Or with manual systemPrompt:
172
+ systemPrompt: `...
173
+ ## CRITICAL: Tool Usage
174
+ You MUST use tools proactively. When discussing any topic:
175
+ 1. First, use the relevant tool to navigate/show/filter
176
+ 2. Then, provide your explanation
177
+ Never just describe where something is - take the user there!
178
+ ...`
179
+ ```
180
+
181
+ ## Quick Setup (Recommended)
182
+
183
+ ### 1. Install
184
+
185
+ ```bash
186
+ npm install ai-site-pilot
187
+ ```
188
+
189
+ ### 2. Configure Tailwind (Required)
190
+
191
+ **Tailwind v4** (CSS-based):
192
+ ```css
193
+ @import "tailwindcss";
194
+ @source "../../node_modules/ai-site-pilot/dist/**/*.{js,mjs}";
195
+ ```
196
+
197
+ **Tailwind v3** (JS config):
198
+ ```js
199
+ // tailwind.config.js
200
+ module.exports = {
201
+ content: [
202
+ './app/**/*.{js,ts,jsx,tsx}',
203
+ './components/**/*.{js,ts,jsx,tsx}',
204
+ './node_modules/ai-site-pilot/dist/**/*.{js,mjs}',
205
+ ],
206
+ }
207
+ ```
208
+
209
+ ### 3. Create API Route with `siteContent`
210
+
211
+ The easiest way - just pass your site's data and the prompt is auto-generated:
212
+
213
+ ```typescript
214
+ // app/api/chat/route.ts
215
+ import { createHandler } from 'ai-site-pilot/api';
216
+ import { defineTool } from 'ai-site-pilot/tools';
217
+
218
+ // Define tools the AI can use
219
+ const navigateTool = defineTool({
220
+ name: 'navigate_to_section',
221
+ description: 'Scroll to a section of the page',
222
+ parameters: {
223
+ type: 'object',
224
+ properties: {
225
+ section: {
226
+ type: 'string',
227
+ description: 'Section ID to navigate to',
228
+ enum: ['hero', 'services', 'about', 'contact'],
229
+ },
230
+ },
231
+ required: ['section'],
232
+ },
233
+ });
234
+
235
+ const showServiceTool = defineTool({
236
+ name: 'show_service',
237
+ description: 'Show details about a specific service',
238
+ parameters: {
239
+ type: 'object',
240
+ properties: {
241
+ serviceId: {
242
+ type: 'string',
243
+ description: 'The service ID',
244
+ },
245
+ },
246
+ required: ['serviceId'],
247
+ },
248
+ });
249
+
250
+ // Create handler with site content - prompt is auto-generated!
251
+ export const POST = createHandler({
252
+ model: 'google/gemini-2.5-flash-lite',
253
+ siteContent: {
254
+ name: 'Acme Dance Studio',
255
+ type: 'dance studio',
256
+ description: 'Premier dance education for all ages',
257
+ personality: 'warm, encouraging, and helpful',
258
+ pages: ['home', 'classes', 'teachers', 'schedule', 'contact'],
259
+ items: [
260
+ // Classes
261
+ { id: 'ballet', name: 'Ballet', category: 'class', description: 'Classical ballet for ages 3-adult', price: '$80/month' },
262
+ { id: 'jazz', name: 'Jazz', category: 'class', description: 'High-energy jazz for ages 6+', price: '$75/month' },
263
+ { id: 'hip-hop', name: 'Hip Hop', category: 'class', description: 'Street dance styles for ages 8+', price: '$70/month' },
264
+ // Teachers
265
+ { id: 'sarah', name: 'Sarah Johnson', category: 'teacher', description: 'Owner, 15 years experience, specializes in ballet' },
266
+ { id: 'mike', name: 'Mike Chen', category: 'teacher', description: 'Hip hop and jazz instructor, 8 years experience' },
267
+ ],
268
+ faqs: [
269
+ { question: 'What should I wear?', answer: 'Leotard and ballet slippers for ballet, athletic wear for jazz and hip hop.' },
270
+ { question: 'Do you offer trial classes?', answer: 'Yes! First class is free for new students.' },
271
+ ],
272
+ contact: {
273
+ email: 'info@acmedance.com',
274
+ phone: '555-123-4567',
275
+ address: '123 Dance Street, NYC',
276
+ hours: 'Mon-Sat 9am-8pm',
277
+ },
278
+ },
279
+ tools: [navigateTool, showServiceTool],
280
+ });
281
+ ```
282
+
283
+ **The AI now automatically knows:**
284
+ - All your classes, teachers, pricing
285
+ - FAQs and contact info
286
+ - What tools to use and when
287
+
288
+ ### 4. Add the Chat Widget
289
+
290
+ ```tsx
291
+ // components/ChatWidget.tsx
292
+ 'use client';
293
+
294
+ import { SitePilot } from 'ai-site-pilot';
295
+ import 'ai-site-pilot/styles.css';
296
+
297
+ export function ChatWidget() {
298
+ const handleToolCall = (name: string, args: Record<string, unknown>) => {
299
+ switch (name) {
300
+ case 'navigate_to_section':
301
+ document.getElementById(args.section as string)?.scrollIntoView({
302
+ behavior: 'smooth',
303
+ });
304
+ break;
305
+ case 'show_service':
306
+ // Dispatch event for your page to handle
307
+ window.dispatchEvent(new CustomEvent('show-service', {
308
+ detail: { serviceId: args.serviceId },
309
+ }));
310
+ break;
311
+ }
312
+ };
313
+
314
+ return (
315
+ <SitePilot
316
+ apiEndpoint="/api/chat"
317
+ onToolCall={handleToolCall}
318
+ suggestions={[
319
+ { text: 'What classes do you offer?', icon: '💃' },
320
+ { text: 'Meet the teachers', icon: '👩‍🏫' },
321
+ { text: 'Contact us', icon: '📞' },
322
+ ]}
323
+ theme={{ accent: 'pink' }} // or accentColor: '#ec4899'
324
+ welcomeMessage="Hi! I'm your dance studio assistant. How can I help you today?"
325
+ />
326
+ );
327
+ }
328
+ ```
329
+
330
+ ### 5. Environment Variable
331
+
332
+ ```bash
333
+ # .env.local
334
+ OPENROUTER_API_KEY=sk-or-...
335
+ ```
336
+
337
+ Get your API key at [openrouter.ai](https://openrouter.ai) and add credits to your account.
338
+
339
+ ## Alternative: Manual System Prompt
340
+
341
+ If you need full control, use `systemPrompt` instead of `siteContent`:
342
+
343
+ ```typescript
344
+ export const POST = createHandler({
345
+ model: 'google/gemini-2.5-flash-lite',
346
+ systemPrompt: `You are an assistant for Acme Dance Studio.
347
+
348
+ ## Classes
349
+ - Ballet: Ages 3-adult, $80/month
350
+ - Jazz: Ages 6+, $75/month
351
+ - Hip Hop: Ages 8+, $70/month
352
+
353
+ ## Tools
354
+ - navigate_to_section: Scroll to a section (hero, classes, teachers, contact)
355
+ - show_service: Show details about a class
356
+
357
+ When users ask about classes, provide specific details.
358
+ Use tools proactively to show relevant content.`,
359
+ tools: [navigateTool, showServiceTool],
360
+ });
361
+ ```
362
+
363
+ ## SiteContent Schema
364
+
365
+ ```typescript
366
+ interface SiteContent {
367
+ name: string; // Business name
368
+ type?: string; // Business type (e.g., 'dance studio')
369
+ description?: string; // Brief description
370
+ personality?: string; // AI personality (e.g., 'warm and helpful')
371
+ pages?: string[]; // Available navigation pages
372
+ items?: SiteContentItem[]; // Products, services, team, etc.
373
+ faqs?: Array<{ question: string; answer: string }>;
374
+ contact?: {
375
+ email?: string;
376
+ phone?: string;
377
+ address?: string;
378
+ hours?: string;
379
+ };
380
+ additionalContext?: string; // Extra info for the prompt
381
+ }
382
+
383
+ interface SiteContentItem {
384
+ id: string; // Unique identifier
385
+ name: string; // Display name
386
+ category?: string; // Category (e.g., 'class', 'teacher', 'product')
387
+ description?: string; // Description
388
+ [key: string]: unknown; // Any extra fields (price, duration, etc.)
389
+ }
390
+ ```
391
+
392
+ ## Theme Presets
393
+
394
+ Use preset names for easy theming:
395
+
396
+ ```tsx
397
+ <SitePilot theme={{ accent: 'pink' }} /> // Hot pink
398
+ <SitePilot theme={{ accent: 'amber' }} /> // Default orange/amber
399
+ <SitePilot theme={{ accent: 'blue' }} /> // Primary blue
400
+ <SitePilot theme={{ accent: 'green' }} /> // Emerald green
401
+ <SitePilot theme={{ accent: 'purple' }} /> // Violet purple
402
+ <SitePilot theme={{ accent: 'cyan' }} /> // Teal cyan
403
+ ```
404
+
405
+ Or use a custom hex color:
406
+
407
+ ```tsx
408
+ <SitePilot theme={{ accentColor: '#8b5cf6' }} />
409
+ ```
410
+
411
+ ## Tool-Only Response Handling
412
+
413
+ When the AI uses tools without text, customize the fallback message:
414
+
415
+ ```tsx
416
+ import { SitePilot, createFallbackMessageGenerator } from 'ai-site-pilot';
417
+
418
+ const generateFallback = createFallbackMessageGenerator({
419
+ navigate_to_section: (args) => `Scrolled to **${args.section}**.`,
420
+ show_service: (args) => `Showing details for **${args.serviceId}**.`,
421
+ filter_products: (args) => `Filtered to **${args.category}** products.`,
422
+ });
423
+
424
+ <SitePilot
425
+ apiEndpoint="/api/chat"
426
+ generateFallbackMessage={generateFallback}
427
+ />
428
+ ```
429
+
430
+ ## Full Props Reference
431
+
432
+ ```typescript
433
+ interface SitePilotProps {
434
+ // Required
435
+ apiEndpoint: string;
436
+
437
+ // Tool handling
438
+ onToolCall?: (name: string, args: Record<string, unknown>) => void;
439
+ generateFallbackMessage?: (toolName: string, args: Record<string, unknown>) => string;
440
+
441
+ // UI customization
442
+ suggestions?: Array<{ text: string; icon?: string }>;
443
+ welcomeMessage?: string;
444
+ placeholder?: string;
445
+ defaultOpen?: boolean;
446
+ position?: 'bottom-right' | 'bottom-left';
447
+
448
+ // Theme
449
+ theme?: {
450
+ accent?: 'amber' | 'pink' | 'blue' | 'green' | 'purple' | 'red' | 'cyan' | 'orange';
451
+ accentColor?: string; // Hex color (overrides accent)
452
+ backgroundColor?: string;
453
+ radius?: number;
454
+ };
455
+
456
+ // Features
457
+ features?: {
458
+ speech?: boolean; // Voice input
459
+ tts?: boolean; // Text-to-speech
460
+ fullscreen?: boolean; // Fullscreen toggle
461
+ };
462
+ }
463
+ ```
464
+
465
+ ## Common Patterns
466
+
467
+ ### E-commerce Site
468
+
469
+ ```typescript
470
+ siteContent: {
471
+ name: 'MyStore',
472
+ type: 'online store',
473
+ items: [
474
+ { id: 'laptop-1', name: 'MacBook Pro', category: 'product', price: '$1999', inStock: true },
475
+ { id: 'phone-1', name: 'iPhone 15', category: 'product', price: '$999', inStock: true },
476
+ ],
477
+ pages: ['home', 'products', 'cart', 'checkout'],
478
+ }
479
+
480
+ // Tools: search_products, filter_by_category, add_to_cart, open_product
481
+ ```
482
+
483
+ ### Portfolio Site
484
+
485
+ ```typescript
486
+ siteContent: {
487
+ name: 'Jane Developer',
488
+ type: 'portfolio',
489
+ items: [
490
+ { id: 'project-1', name: 'Acme Dashboard', category: 'project', status: 'Live', tech: 'React, Node' },
491
+ { id: 'project-2', name: 'FitTrack App', category: 'project', status: 'Live', tech: 'React Native' },
492
+ ],
493
+ pages: ['hero', 'projects', 'about', 'contact'],
494
+ }
495
+
496
+ // Tools: filter_projects, open_project_modal, navigate_to_section, open_contact
497
+ ```
498
+
499
+ ### SaaS Landing Page
500
+
501
+ ```typescript
502
+ siteContent: {
503
+ name: 'CloudSync',
504
+ type: 'SaaS platform',
505
+ description: 'Real-time data synchronization for teams',
506
+ items: [
507
+ { id: 'starter', name: 'Starter Plan', category: 'pricing', price: '$9/mo', features: '5 users, 10GB' },
508
+ { id: 'pro', name: 'Pro Plan', category: 'pricing', price: '$29/mo', features: '25 users, 100GB' },
509
+ ],
510
+ faqs: [
511
+ { question: 'Is there a free trial?', answer: 'Yes, 14-day free trial on all plans.' },
512
+ ],
513
+ }
514
+
515
+ // Tools: navigate_to_section, show_pricing, open_signup, open_demo
516
+ ```
517
+
518
+ ## Troubleshooting
519
+
520
+ ### Button only shows icon, no "Ask AI" text
521
+ Your Tailwind config isn't scanning the package.
522
+
523
+ **Tailwind v4**: Add to your CSS:
524
+ ```css
525
+ @source "../../node_modules/ai-site-pilot/dist/**/*.{js,mjs}";
526
+ ```
527
+
528
+ **Tailwind v3**: Add to `tailwind.config.js`:
529
+ ```js
530
+ content: ['./node_modules/ai-site-pilot/dist/**/*.{js,mjs}']
531
+ ```
532
+
533
+ ### Theme colors not working
534
+ Use component props, not CSS variables:
535
+ ```tsx
536
+ // Good
537
+ <SitePilot theme={{ accent: 'pink' }} />
538
+
539
+ // Bad - don't set CSS vars directly
540
+ ```
541
+
542
+ ### AI gives generic responses
543
+ Use `siteContent` to provide actual data about your site. The AI only knows what you tell it.
544
+
545
+ ### Tools not executing
546
+ 1. Check `onToolCall` is passed to SitePilot
547
+ 2. Verify tool names match between API and client handler
548
+ 3. Check browser console for errors
549
+
550
+ ## Available Models
551
+
552
+ | Model | ID | Notes |
553
+ |-------|-----|-------|
554
+ | Gemini 2.5 Flash-Lite | `google/gemini-2.5-flash-lite` | Fast, affordable (default) |
555
+ | GPT-4o | `openai/gpt-4o` | Best overall |
556
+ | Claude 3.5 Sonnet | `anthropic/claude-3.5-sonnet` | Best for coding |
557
+ | Llama 3.1 70B | `meta-llama/llama-3.1-70b-instruct` | Open source |
558
+
559
+ See all models at [openrouter.ai/models](https://openrouter.ai/models)