ai-site-pilot 0.5.0 → 0.5.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.
Files changed (2) hide show
  1. package/CLAUDE.md +346 -375
  2. package/package.json +1 -1
package/CLAUDE.md CHANGED
@@ -1,341 +1,196 @@
1
1
  # AI Instructions for ai-site-pilot
2
2
 
3
- This file provides instructions for AI coding assistants (Claude, GPT, Copilot, etc.) on how to integrate ai-site-pilot into projects.
3
+ This file helps AI coding assistants (Claude, GPT, Copilot) integrate ai-site-pilot into projects.
4
4
 
5
5
  ## What is ai-site-pilot?
6
6
 
7
- A drop-in AI chat widget that can **control and navigate websites**. It's not just a chatbot - the AI can execute tools to filter content, open modals, navigate sections, and more.
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
8
 
9
- ## ⚠️ IMPORTANT: How the AI Learns Your Site
9
+ **Key features:**
10
+ - Works with any AI model via OpenRouter (Gemini, GPT-4, Claude, Llama)
11
+ - Free tier available (Gemini 2.0 Flash)
12
+ - Auto-generates system prompts from site content
13
+ - Streaming responses with tool execution
10
14
 
11
- The package provides chat UI and streaming. **The AI doesn't automatically know your site structure.** You must:
15
+ ## IMPORTANT: Keeping Chatbot in Sync with Site Content
12
16
 
13
- 1. **Tell it what exists** - In the system prompt, list your sections, data, categories
14
- 2. **Define tools** - Create tools that match your site's DOM and state
15
- 3. **Write handlers** - Client-side code that executes the actual actions
17
+ **The chatbot must always reflect the current site content.** To achieve this:
16
18
 
17
- ### Example: Teaching the AI About Your Site
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.)
18
20
 
19
- ```typescript
20
- // In your API route - this is the MOST IMPORTANT part
21
- const SYSTEM_PROMPT = `You are an AI assistant for MyStore.
22
-
23
- ## SITE STRUCTURE
24
- The page has these sections (use navigate_to_section tool):
25
- - hero: Top of page with tagline
26
- - products: Product grid (id="products")
27
- - about: About us section (id="about")
28
- - contact: Contact form (id="contact")
29
-
30
- ## AVAILABLE DATA
31
- Products on this site:
32
- - Electronics: laptops, phones, tablets
33
- - Clothing: shirts, pants, shoes
34
- - Home: furniture, decor, kitchen
35
-
36
- Categories for filtering: electronics, clothing, home, all
37
-
38
- ## YOUR TOOLS
39
- - navigate_to_section: Scroll to a section by ID
40
- - filter_products: Filter the product grid by category
41
- - open_product_modal: Show details for a specific product (use product slug)
42
- - open_contact: Open the contact modal
43
-
44
- ## BEHAVIOR
45
- - When users ask about products, use filter_products to show relevant category
46
- - When users want details, use open_product_modal
47
- - When users want to buy/contact, use open_contact
48
- - Always be helpful and proactively use tools to show relevant content`;
49
- ```
50
-
51
- The system prompt teaches the AI:
52
- - What sections exist and their IDs
53
- - What data/content is available
54
- - What tools it can use and when
55
- - How to behave (proactively use tools)
21
+ 2. **Import from the same source** - The API route should import from these existing data sources, NOT duplicate the data
56
22
 
57
- ## Quick Setup (Copy-Paste Ready)
23
+ 3. **Maintain this pattern** - When updating site content, the chatbot automatically stays in sync
58
24
 
59
- ### 1. Install the package
25
+ ### Example Pattern
60
26
 
61
- ```bash
62
- npm install ai-site-pilot
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
+ };
63
43
  ```
64
44
 
65
- ### 2. Create the API route
66
-
67
- Create `app/api/chat/route.ts` (Next.js App Router):
68
-
69
45
  ```typescript
70
- import { streamText } from 'ai';
71
- import { google } from '@ai-sdk/google';
72
- // Or use any Vercel AI SDK provider:
73
- // import { openai } from '@ai-sdk/openai';
74
- // import { anthropic } from '@ai-sdk/anthropic';
75
-
76
- const SYSTEM_PROMPT = `You are a helpful AI assistant for this website. You can help users navigate and find information.
77
-
78
- ## YOUR CAPABILITIES
79
- You have access to tools that control the website:
80
- - navigate_to_section: Scroll to different sections
81
- - open_modal: Open detail modals
82
- - filter_content: Filter displayed content
83
- - search: Search the site
84
-
85
- Use these tools proactively when relevant to the user's request.`;
86
-
87
- export async function POST(req: Request) {
88
- const { messages } = await req.json();
89
-
90
- const result = streamText({
91
- model: google('gemini-2.0-flash'),
92
- system: SYSTEM_PROMPT,
93
- messages,
94
- tools: {
95
- // Define your site-specific tools here
96
- navigate_to_section: {
97
- description: 'Scroll to a section of the page',
98
- parameters: {
99
- type: 'object',
100
- properties: {
101
- section: { type: 'string', enum: ['hero', 'features', 'pricing', 'contact'] }
102
- },
103
- required: ['section']
104
- }
105
- },
106
- // Add more tools as needed
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
+
50
+ export const POST = createHandler({
51
+ siteContent: {
52
+ name: SITE_INFO.name,
53
+ items: [
54
+ ...CLASSES.map(c => ({ ...c, category: 'class' })),
55
+ ...TEACHERS.map(t => ({ ...t, category: 'teacher' })),
56
+ ],
57
+ contact: {
58
+ email: SITE_INFO.email,
59
+ phone: SITE_INFO.phone,
107
60
  },
108
- });
61
+ },
62
+ tools,
63
+ });
64
+ ```
109
65
 
110
- return result.toDataStreamResponse();
66
+ ```tsx
67
+ // components/ClassList.tsx - Also uses the same source
68
+ import { CLASSES } from '@/lib/data';
69
+
70
+ export function ClassList() {
71
+ return CLASSES.map(c => <ClassCard key={c.id} {...c} />);
111
72
  }
112
73
  ```
113
74
 
114
- ### 3. Add the chat widget
75
+ **Update `lib/data.ts` Both site AND chatbot update automatically.**
115
76
 
116
- In your layout or page component:
77
+ ### When Setting Up a New Project
117
78
 
118
- ```tsx
119
- 'use client';
79
+ As an AI assistant, you should:
120
80
 
121
- import { SitePilot } from 'ai-site-pilot';
122
- import 'ai-site-pilot/styles.css';
81
+ 1. **Scan the codebase** for existing data files:
82
+ - `constants.ts`, `data.ts`, `config.ts`
83
+ - `lib/`, `data/`, `content/` directories
84
+ - JSON files with site content
123
85
 
124
- export function ChatWidget() {
125
- const handleToolCall = (name: string, args: Record<string, unknown>) => {
126
- // Handle tool execution - this runs on the client
127
- switch (name) {
128
- case 'navigate_to_section':
129
- document.getElementById(args.section as string)?.scrollIntoView({ behavior: 'smooth' });
130
- break;
131
- case 'open_modal':
132
- // Your modal logic
133
- break;
134
- // Handle other tools
135
- }
136
- };
86
+ 2. **Identify the data structure** - What does the site display? Products? Services? Team members?
137
87
 
138
- return (
139
- <SitePilot
140
- apiEndpoint="/api/chat"
141
- onToolCall={handleToolCall}
142
- suggestions={[
143
- { text: 'Show me features', icon: '✨' },
144
- { text: 'How does pricing work?', icon: '💰' },
145
- { text: 'Contact sales', icon: '📞' },
146
- ]}
147
- welcomeMessage="Hi! I can help you explore this site. What would you like to know?"
148
- theme={{
149
- accentColor: '#3b82f6', // Your brand color
150
- backgroundColor: '#0f172a', // Dark background
151
- // See full theme options below
152
- }}
153
- />
154
- );
155
- }
156
- ```
88
+ 3. **Create the API route** that imports from these existing sources
157
89
 
158
- ## Theme Customization
90
+ 4. **Never duplicate data** - If you can't find existing data files, create ONE shared file that both the site and chatbot use
159
91
 
160
- All colors accept any CSS color value (hex, rgb, hsl, etc.):
92
+ ## Quick Setup (Recommended)
161
93
 
162
- ```tsx
163
- <SitePilot
164
- theme={{
165
- // Position
166
- position: 'bottom-right', // 'bottom-left', 'top-right', 'top-left'
167
- borderRadius: 24, // pixels
168
-
169
- // Colors
170
- accentColor: '#f59e0b', // Primary accent (buttons, highlights)
171
- accentColorDark: '#d97706', // Gradient end color
172
- backgroundColor: '#0F0720', // Panel background
173
- textColor: '#ffffff', // Primary text
174
- textMutedColor: '#a1a1aa', // Secondary text
175
- borderColor: 'rgba(255,255,255,0.1)',
176
-
177
- // Message bubbles
178
- userMessageBg: 'linear-gradient(135deg, #f59e0b, #d97706)',
179
- assistantMessageBg: 'rgba(255,255,255,0.05)',
180
- }}
181
- />
94
+ ### 1. Install
95
+
96
+ ```bash
97
+ npm install ai-site-pilot
182
98
  ```
183
99
 
184
- ## Feature Toggles
100
+ ### 2. Configure Tailwind (Required)
185
101
 
186
- ```tsx
187
- <SitePilot
188
- features={{
189
- speech: true, // Voice input (microphone)
190
- tts: true, // Text-to-speech for responses
191
- fullscreen: true, // Fullscreen toggle button
192
- suggestions: true, // Show suggestion chips
193
- }}
194
- />
102
+ Add to `tailwind.config.js`:
103
+
104
+ ```js
105
+ module.exports = {
106
+ content: [
107
+ './app/**/*.{js,ts,jsx,tsx}',
108
+ './components/**/*.{js,ts,jsx,tsx}',
109
+ './node_modules/ai-site-pilot/dist/**/*.{js,mjs}', // Required!
110
+ ],
111
+ }
195
112
  ```
196
113
 
197
- ## Tool System
114
+ ### 3. Create API Route with `siteContent`
198
115
 
199
- Define tools that the AI can call to control your site:
116
+ The easiest way - just pass your site's data and the prompt is auto-generated:
200
117
 
201
118
  ```typescript
202
- // Using the defineTool helper (optional, for type safety)
119
+ // app/api/chat/route.ts
120
+ import { createHandler } from 'ai-site-pilot/api';
203
121
  import { defineTool } from 'ai-site-pilot/tools';
204
122
 
205
- const filterProductsTool = defineTool({
206
- name: 'filter_products',
207
- description: 'Filter products by category',
123
+ // Define tools the AI can use
124
+ const navigateTool = defineTool({
125
+ name: 'navigate_to_section',
126
+ description: 'Scroll to a section of the page',
208
127
  parameters: {
209
128
  type: 'object',
210
129
  properties: {
211
- category: {
130
+ section: {
212
131
  type: 'string',
213
- description: 'Product category',
214
- enum: ['electronics', 'clothing', 'home', 'all']
215
- }
132
+ description: 'Section ID to navigate to',
133
+ enum: ['hero', 'services', 'about', 'contact'],
134
+ },
216
135
  },
217
- required: ['category']
218
- }
136
+ required: ['section'],
137
+ },
219
138
  });
220
- ```
221
-
222
- ## Environment Variables
223
-
224
- For the API route, you'll need your AI provider's API key:
225
-
226
- ```env
227
- # For Google Gemini
228
- GOOGLE_GENERATIVE_AI_API_KEY=your-key-here
229
-
230
- # Or for OpenAI
231
- OPENAI_API_KEY=your-key-here
232
-
233
- # Or for Anthropic
234
- ANTHROPIC_API_KEY=your-key-here
235
- ```
236
139
 
237
- ## Complete Real-World Example
238
-
239
- Here's a full implementation for a portfolio site showing all three parts:
240
-
241
- ### Part 1: System Prompt (teaches the AI what exists)
242
-
243
- ```typescript
244
- // app/api/chat/route.ts
245
- const PROJECTS = `
246
- Available projects (use open_project_modal with these IDs):
247
- - acme-dashboard: Acme Dashboard (SaaS, Live) - Analytics platform
248
- - mobile-app: FitTrack (Mobile, Live) - Fitness tracking app
249
- - ecommerce: ShopFlow (E-commerce, In Progress) - Online store template
250
- - api-service: DataSync API (Backend, Live) - Data synchronization service
251
-
252
- Categories: All, SaaS, Mobile, E-commerce, Backend
253
- Statuses: Live, In Progress, Concept
254
- `;
255
-
256
- const SYSTEM_PROMPT = `You are a portfolio assistant for Jane Developer.
257
-
258
- ## SITE SECTIONS
259
- - hero: Landing section with intro (id="hero")
260
- - projects: Project showcase grid (id="projects")
261
- - about: About section (id="about")
262
- - contact: Contact form (id="contact")
263
-
264
- ## PROJECT DATA
265
- ${PROJECTS}
266
-
267
- ## YOUR TOOLS
268
- - navigate_to_section: Scroll to hero, projects, about, or contact
269
- - filter_by_category: Filter projects (SaaS, Mobile, E-commerce, Backend, All)
270
- - filter_by_status: Filter by status (Live, In Progress, Concept)
271
- - open_project_modal: Open project details (use project ID like "acme-dashboard")
272
- - highlight_project: Pulse animation on a project card
273
- - open_contact: Open contact/hire modal
274
-
275
- ## WHEN TO USE TOOLS
276
- - "Show me your work" → navigate_to_section("projects")
277
- - "Any mobile apps?" → filter_by_category("Mobile")
278
- - "What's live?" → filter_by_status("Live")
279
- - "Tell me about Acme" → open_project_modal("acme-dashboard")
280
- - "I want to hire you" → open_contact()
281
-
282
- Be conversational but proactively use tools to make the site interactive.`;
283
- ```
284
-
285
- ### Part 2: Tool Definitions (what the AI can call)
286
-
287
- ```typescript
288
- // app/api/chat/route.ts (continued)
289
- export async function POST(req: Request) {
290
- const { messages } = await req.json();
291
-
292
- const result = streamText({
293
- model: google('gemini-2.0-flash'),
294
- system: SYSTEM_PROMPT,
295
- messages,
296
- tools: {
297
- navigate_to_section: {
298
- description: 'Scroll to a page section',
299
- parameters: {
300
- type: 'object',
301
- properties: {
302
- section: { type: 'string', enum: ['hero', 'projects', 'about', 'contact'] }
303
- },
304
- required: ['section']
305
- }
306
- },
307
- filter_by_category: {
308
- description: 'Filter projects by category',
309
- parameters: {
310
- type: 'object',
311
- properties: {
312
- category: { type: 'string', enum: ['All', 'SaaS', 'Mobile', 'E-commerce', 'Backend'] }
313
- },
314
- required: ['category']
315
- }
316
- },
317
- open_project_modal: {
318
- description: 'Open project detail modal',
319
- parameters: {
320
- type: 'object',
321
- properties: {
322
- projectId: { type: 'string', description: 'Project ID like acme-dashboard' }
323
- },
324
- required: ['projectId']
325
- }
140
+ const showServiceTool = defineTool({
141
+ name: 'show_service',
142
+ description: 'Show details about a specific service',
143
+ parameters: {
144
+ type: 'object',
145
+ properties: {
146
+ serviceId: {
147
+ type: 'string',
148
+ description: 'The service ID',
326
149
  },
327
- open_contact: {
328
- description: 'Open the contact/hire modal',
329
- parameters: { type: 'object', properties: {}, required: [] }
330
- }
331
150
  },
332
- });
151
+ required: ['serviceId'],
152
+ },
153
+ });
333
154
 
334
- return result.toDataStreamResponse();
335
- }
155
+ // Create handler with site content - prompt is auto-generated!
156
+ export const POST = createHandler({
157
+ model: 'google/gemini-2.0-flash-exp:free', // Free!
158
+ siteContent: {
159
+ name: 'Acme Dance Studio',
160
+ type: 'dance studio',
161
+ description: 'Premier dance education for all ages',
162
+ personality: 'warm, encouraging, and helpful',
163
+ pages: ['home', 'classes', 'teachers', 'schedule', 'contact'],
164
+ items: [
165
+ // Classes
166
+ { id: 'ballet', name: 'Ballet', category: 'class', description: 'Classical ballet for ages 3-adult', price: '$80/month' },
167
+ { id: 'jazz', name: 'Jazz', category: 'class', description: 'High-energy jazz for ages 6+', price: '$75/month' },
168
+ { id: 'hip-hop', name: 'Hip Hop', category: 'class', description: 'Street dance styles for ages 8+', price: '$70/month' },
169
+ // Teachers
170
+ { id: 'sarah', name: 'Sarah Johnson', category: 'teacher', description: 'Owner, 15 years experience, specializes in ballet' },
171
+ { id: 'mike', name: 'Mike Chen', category: 'teacher', description: 'Hip hop and jazz instructor, 8 years experience' },
172
+ ],
173
+ faqs: [
174
+ { question: 'What should I wear?', answer: 'Leotard and ballet slippers for ballet, athletic wear for jazz and hip hop.' },
175
+ { question: 'Do you offer trial classes?', answer: 'Yes! First class is free for new students.' },
176
+ ],
177
+ contact: {
178
+ email: 'info@acmedance.com',
179
+ phone: '555-123-4567',
180
+ address: '123 Dance Street, NYC',
181
+ hours: 'Mon-Sat 9am-8pm',
182
+ },
183
+ },
184
+ tools: [navigateTool, showServiceTool],
185
+ });
336
186
  ```
337
187
 
338
- ### Part 3: Client Handler (executes the actions)
188
+ **The AI now automatically knows:**
189
+ - All your classes, teachers, pricing
190
+ - FAQs and contact info
191
+ - What tools to use and when
192
+
193
+ ### 4. Add the Chat Widget
339
194
 
340
195
  ```tsx
341
196
  // components/ChatWidget.tsx
@@ -349,26 +204,15 @@ export function ChatWidget() {
349
204
  switch (name) {
350
205
  case 'navigate_to_section':
351
206
  document.getElementById(args.section as string)?.scrollIntoView({
352
- behavior: 'smooth'
207
+ behavior: 'smooth',
353
208
  });
354
209
  break;
355
-
356
- case 'filter_by_category':
357
- // Dispatch custom event for your page to handle
358
- window.dispatchEvent(new CustomEvent('filter-projects', {
359
- detail: { category: args.category }
360
- }));
361
- break;
362
-
363
- case 'open_project_modal':
364
- window.dispatchEvent(new CustomEvent('open-project', {
365
- detail: { projectId: args.projectId }
210
+ case 'show_service':
211
+ // Dispatch event for your page to handle
212
+ window.dispatchEvent(new CustomEvent('show-service', {
213
+ detail: { serviceId: args.serviceId },
366
214
  }));
367
215
  break;
368
-
369
- case 'open_contact':
370
- window.dispatchEvent(new CustomEvent('open-contact'));
371
- break;
372
216
  }
373
217
  };
374
218
 
@@ -377,110 +221,237 @@ export function ChatWidget() {
377
221
  apiEndpoint="/api/chat"
378
222
  onToolCall={handleToolCall}
379
223
  suggestions={[
380
- { text: "Show me your work", icon: "💼" },
381
- { text: "What's live?", icon: "🚀" },
382
- { text: "I want to hire you", icon: "💡" },
224
+ { text: 'What classes do you offer?', icon: '💃' },
225
+ { text: 'Meet the teachers', icon: '👩‍🏫' },
226
+ { text: 'Contact us', icon: '📞' },
383
227
  ]}
384
- theme={{
385
- accentColor: '#8b5cf6',
386
- backgroundColor: '#0f0f23',
387
- }}
228
+ theme={{ accent: 'pink' }} // or accentColor: '#ec4899'
229
+ welcomeMessage="Hi! I'm your dance studio assistant. How can I help you today?"
388
230
  />
389
231
  );
390
232
  }
391
233
  ```
392
234
 
393
- ### Part 4: Page Listens for Events
235
+ ### 5. Environment Variable
394
236
 
395
- ```tsx
396
- // app/page.tsx or components/HomePage.tsx
397
- 'use client';
237
+ ```bash
238
+ # .env.local
239
+ OPENROUTER_API_KEY=sk-or-...
240
+ ```
398
241
 
399
- import { useEffect, useState } from 'react';
242
+ Get a free key at [openrouter.ai](https://openrouter.ai) - Gemini 2.0 Flash is free!
400
243
 
401
- export function HomePage() {
402
- const [filter, setFilter] = useState('All');
403
- const [selectedProject, setSelectedProject] = useState(null);
404
- const [showContact, setShowContact] = useState(false);
244
+ ## Alternative: Manual System Prompt
405
245
 
406
- useEffect(() => {
407
- const handleFilter = (e: CustomEvent) => setFilter(e.detail.category);
408
- const handleProject = (e: CustomEvent) => setSelectedProject(e.detail.projectId);
409
- const handleContact = () => setShowContact(true);
246
+ If you need full control, use `systemPrompt` instead of `siteContent`:
410
247
 
411
- window.addEventListener('filter-projects', handleFilter as EventListener);
412
- window.addEventListener('open-project', handleProject as EventListener);
413
- window.addEventListener('open-contact', handleContact);
248
+ ```typescript
249
+ export const POST = createHandler({
250
+ model: 'google/gemini-2.0-flash-exp:free',
251
+ systemPrompt: `You are an assistant for Acme Dance Studio.
252
+
253
+ ## Classes
254
+ - Ballet: Ages 3-adult, $80/month
255
+ - Jazz: Ages 6+, $75/month
256
+ - Hip Hop: Ages 8+, $70/month
257
+
258
+ ## Tools
259
+ - navigate_to_section: Scroll to a section (hero, classes, teachers, contact)
260
+ - show_service: Show details about a class
261
+
262
+ When users ask about classes, provide specific details.
263
+ Use tools proactively to show relevant content.`,
264
+ tools: [navigateTool, showServiceTool],
265
+ });
266
+ ```
414
267
 
415
- return () => {
416
- window.removeEventListener('filter-projects', handleFilter as EventListener);
417
- window.removeEventListener('open-project', handleProject as EventListener);
418
- window.removeEventListener('open-contact', handleContact);
419
- };
420
- }, []);
268
+ ## SiteContent Schema
269
+
270
+ ```typescript
271
+ interface SiteContent {
272
+ name: string; // Business name
273
+ type?: string; // Business type (e.g., 'dance studio')
274
+ description?: string; // Brief description
275
+ personality?: string; // AI personality (e.g., 'warm and helpful')
276
+ pages?: string[]; // Available navigation pages
277
+ items?: SiteContentItem[]; // Products, services, team, etc.
278
+ faqs?: Array<{ question: string; answer: string }>;
279
+ contact?: {
280
+ email?: string;
281
+ phone?: string;
282
+ address?: string;
283
+ hours?: string;
284
+ };
285
+ additionalContext?: string; // Extra info for the prompt
286
+ }
421
287
 
422
- // Your page components use filter, selectedProject, showContact state...
288
+ interface SiteContentItem {
289
+ id: string; // Unique identifier
290
+ name: string; // Display name
291
+ category?: string; // Category (e.g., 'class', 'teacher', 'product')
292
+ description?: string; // Description
293
+ [key: string]: unknown; // Any extra fields (price, duration, etc.)
423
294
  }
424
295
  ```
425
296
 
426
- ## Common Patterns
297
+ ## Theme Presets
427
298
 
428
- ### E-commerce Site
429
- ```tsx
430
- const tools = {
431
- search_products: { /* search inventory */ },
432
- filter_by_category: { /* filter product grid */ },
433
- add_to_cart: { /* add item to cart */ },
434
- open_product: { /* show product details */ },
435
- };
436
- ```
299
+ Use preset names for easy theming:
437
300
 
438
- ### Documentation Site
439
301
  ```tsx
440
- const tools = {
441
- search_docs: { /* search documentation */ },
442
- navigate_to_page: { /* go to specific doc page */ },
443
- show_code_example: { /* display code snippet */ },
444
- };
302
+ <SitePilot theme={{ accent: 'pink' }} /> // Hot pink
303
+ <SitePilot theme={{ accent: 'amber' }} /> // Default orange/amber
304
+ <SitePilot theme={{ accent: 'blue' }} /> // Primary blue
305
+ <SitePilot theme={{ accent: 'green' }} /> // Emerald green
306
+ <SitePilot theme={{ accent: 'purple' }} /> // Violet purple
307
+ <SitePilot theme={{ accent: 'cyan' }} /> // Teal cyan
445
308
  ```
446
309
 
447
- ### Portfolio Site
310
+ Or use a custom hex color:
311
+
448
312
  ```tsx
449
- const tools = {
450
- filter_projects: { /* filter by category/status */ },
451
- open_project_modal: { /* show project details */ },
452
- navigate_to_section: { /* scroll to section */ },
453
- open_contact: { /* open contact form */ },
454
- };
313
+ <SitePilot theme={{ accentColor: '#8b5cf6' }} />
455
314
  ```
456
315
 
457
- ## Troubleshooting
316
+ ## Tool-Only Response Handling
458
317
 
459
- **Chat not appearing?**
460
- - Make sure you imported the CSS: `import 'ai-site-pilot/styles.css'`
461
- - Check that the component is rendered (use React DevTools)
318
+ When the AI uses tools without text, customize the fallback message:
462
319
 
463
- **Tools not executing?**
464
- - Verify `onToolCall` is passed to SitePilot
465
- - Check browser console for the tool calls
466
- - Make sure tool names match between API and client
320
+ ```tsx
321
+ import { SitePilot, createFallbackMessageGenerator } from 'ai-site-pilot';
467
322
 
468
- **Styling issues?**
469
- - CSS variables can be overridden in your global CSS
470
- - The component uses `z-index: 200` - adjust if needed
323
+ const generateFallback = createFallbackMessageGenerator({
324
+ navigate_to_section: (args) => `Scrolled to **${args.section}**.`,
325
+ show_service: (args) => `Showing details for **${args.serviceId}**.`,
326
+ filter_products: (args) => `Filtered to **${args.category}** products.`,
327
+ });
328
+
329
+ <SitePilot
330
+ apiEndpoint="/api/chat"
331
+ generateFallbackMessage={generateFallback}
332
+ />
333
+ ```
471
334
 
472
335
  ## Full Props Reference
473
336
 
474
337
  ```typescript
475
338
  interface SitePilotProps {
476
- apiEndpoint: string; // Required: Your chat API endpoint
477
- theme?: SitePilotTheme; // Theme customization
478
- suggestions?: Suggestion[]; // Suggestion chips
479
- features?: SitePilotFeatures; // Feature toggles
339
+ // Required
340
+ apiEndpoint: string;
341
+
342
+ // Tool handling
480
343
  onToolCall?: (name: string, args: Record<string, unknown>) => void;
481
- defaultOpen?: boolean; // Start with chat open
482
- placeholder?: string; // Input placeholder
483
- welcomeMessage?: string; // Initial greeting
484
- className?: string; // Additional CSS class
344
+ generateFallbackMessage?: (toolName: string, args: Record<string, unknown>) => string;
345
+
346
+ // UI customization
347
+ suggestions?: Array<{ text: string; icon?: string }>;
348
+ welcomeMessage?: string;
349
+ placeholder?: string;
350
+ defaultOpen?: boolean;
351
+ position?: 'bottom-right' | 'bottom-left';
352
+
353
+ // Theme
354
+ theme?: {
355
+ accent?: 'amber' | 'pink' | 'blue' | 'green' | 'purple' | 'red' | 'cyan' | 'orange';
356
+ accentColor?: string; // Hex color (overrides accent)
357
+ backgroundColor?: string;
358
+ radius?: number;
359
+ };
360
+
361
+ // Features
362
+ features?: {
363
+ speech?: boolean; // Voice input
364
+ tts?: boolean; // Text-to-speech
365
+ fullscreen?: boolean; // Fullscreen toggle
366
+ };
485
367
  }
486
368
  ```
369
+
370
+ ## Common Patterns
371
+
372
+ ### E-commerce Site
373
+
374
+ ```typescript
375
+ siteContent: {
376
+ name: 'MyStore',
377
+ type: 'online store',
378
+ items: [
379
+ { id: 'laptop-1', name: 'MacBook Pro', category: 'product', price: '$1999', inStock: true },
380
+ { id: 'phone-1', name: 'iPhone 15', category: 'product', price: '$999', inStock: true },
381
+ ],
382
+ pages: ['home', 'products', 'cart', 'checkout'],
383
+ }
384
+
385
+ // Tools: search_products, filter_by_category, add_to_cart, open_product
386
+ ```
387
+
388
+ ### Portfolio Site
389
+
390
+ ```typescript
391
+ siteContent: {
392
+ name: 'Jane Developer',
393
+ type: 'portfolio',
394
+ items: [
395
+ { id: 'project-1', name: 'Acme Dashboard', category: 'project', status: 'Live', tech: 'React, Node' },
396
+ { id: 'project-2', name: 'FitTrack App', category: 'project', status: 'Live', tech: 'React Native' },
397
+ ],
398
+ pages: ['hero', 'projects', 'about', 'contact'],
399
+ }
400
+
401
+ // Tools: filter_projects, open_project_modal, navigate_to_section, open_contact
402
+ ```
403
+
404
+ ### SaaS Landing Page
405
+
406
+ ```typescript
407
+ siteContent: {
408
+ name: 'CloudSync',
409
+ type: 'SaaS platform',
410
+ description: 'Real-time data synchronization for teams',
411
+ items: [
412
+ { id: 'starter', name: 'Starter Plan', category: 'pricing', price: '$9/mo', features: '5 users, 10GB' },
413
+ { id: 'pro', name: 'Pro Plan', category: 'pricing', price: '$29/mo', features: '25 users, 100GB' },
414
+ ],
415
+ faqs: [
416
+ { question: 'Is there a free trial?', answer: 'Yes, 14-day free trial on all plans.' },
417
+ ],
418
+ }
419
+
420
+ // Tools: navigate_to_section, show_pricing, open_signup, open_demo
421
+ ```
422
+
423
+ ## Troubleshooting
424
+
425
+ ### Button only shows icon, no "Ask AI" text
426
+ Your Tailwind config isn't scanning the package:
427
+ ```js
428
+ content: ['./node_modules/ai-site-pilot/dist/**/*.{js,mjs}']
429
+ ```
430
+
431
+ ### Theme colors not working
432
+ Use component props, not CSS variables:
433
+ ```tsx
434
+ // Good
435
+ <SitePilot theme={{ accent: 'pink' }} />
436
+
437
+ // Bad - don't set CSS vars directly
438
+ ```
439
+
440
+ ### AI gives generic responses
441
+ Use `siteContent` to provide actual data about your site. The AI only knows what you tell it.
442
+
443
+ ### Tools not executing
444
+ 1. Check `onToolCall` is passed to SitePilot
445
+ 2. Verify tool names match between API and client handler
446
+ 3. Check browser console for errors
447
+
448
+ ## Available Models
449
+
450
+ | Model | ID | Notes |
451
+ |-------|-----|-------|
452
+ | Gemini 2.0 Flash | `google/gemini-2.0-flash-exp:free` | **Free!** Default |
453
+ | GPT-4o | `openai/gpt-4o` | Best overall |
454
+ | Claude 3.5 Sonnet | `anthropic/claude-3.5-sonnet` | Best for coding |
455
+ | Llama 3.1 70B | `meta-llama/llama-3.1-70b-instruct` | Open source |
456
+
457
+ See all models at [openrouter.ai/models](https://openrouter.ai/models)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-site-pilot",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "AI chat widget that can control and navigate your website. Works with any AI model via OpenRouter.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",