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 +559 -559
- package/README.md +387 -387
- package/dist/api/index.d.mts +22 -12
- package/dist/api/index.d.ts +22 -12
- package/dist/api/index.js +212 -85
- package/dist/api/index.js.map +1 -1
- package/dist/api/index.mjs +212 -85
- package/dist/api/index.mjs.map +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +5 -23
- package/dist/index.d.ts +5 -23
- package/dist/index.js +156 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +157 -69
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +380 -255
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/index.mjs.map +1 -1
- package/dist/{types-DPBZM89d.d.mts → types-CyWrTpQK.d.mts} +12 -0
- package/dist/{types-DPBZM89d.d.ts → types-CyWrTpQK.d.ts} +12 -0
- package/package.json +87 -86
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)
|