ai-site-pilot 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +275 -381
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -1,121 +1,122 @@
|
|
|
1
1
|
# AI Instructions for ai-site-pilot
|
|
2
2
|
|
|
3
|
-
This file
|
|
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**.
|
|
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
|
-
|
|
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
|
-
|
|
15
|
+
## Quick Setup (Recommended)
|
|
12
16
|
|
|
13
|
-
1.
|
|
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
|
+
### 1. Install
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
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`;
|
|
19
|
+
```bash
|
|
20
|
+
npm install ai-site-pilot
|
|
49
21
|
```
|
|
50
22
|
|
|
51
|
-
|
|
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)
|
|
56
|
-
|
|
57
|
-
## Quick Setup (Copy-Paste Ready)
|
|
23
|
+
### 2. Configure Tailwind (Required)
|
|
58
24
|
|
|
59
|
-
|
|
25
|
+
Add to `tailwind.config.js`:
|
|
60
26
|
|
|
61
|
-
```
|
|
62
|
-
|
|
27
|
+
```js
|
|
28
|
+
module.exports = {
|
|
29
|
+
content: [
|
|
30
|
+
'./app/**/*.{js,ts,jsx,tsx}',
|
|
31
|
+
'./components/**/*.{js,ts,jsx,tsx}',
|
|
32
|
+
'./node_modules/ai-site-pilot/dist/**/*.{js,mjs}', // Required!
|
|
33
|
+
],
|
|
34
|
+
}
|
|
63
35
|
```
|
|
64
36
|
|
|
65
|
-
###
|
|
37
|
+
### 3. Create API Route with `siteContent`
|
|
66
38
|
|
|
67
|
-
|
|
39
|
+
The easiest way - just pass your site's data and the prompt is auto-generated:
|
|
68
40
|
|
|
69
41
|
```typescript
|
|
70
|
-
|
|
71
|
-
import {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
}
|
|
42
|
+
// app/api/chat/route.ts
|
|
43
|
+
import { createHandler } from 'ai-site-pilot/api';
|
|
44
|
+
import { defineTool } from 'ai-site-pilot/tools';
|
|
45
|
+
|
|
46
|
+
// Define tools the AI can use
|
|
47
|
+
const navigateTool = defineTool({
|
|
48
|
+
name: 'navigate_to_section',
|
|
49
|
+
description: 'Scroll to a section of the page',
|
|
50
|
+
parameters: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
section: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'Section ID to navigate to',
|
|
56
|
+
enum: ['hero', 'services', 'about', 'contact'],
|
|
105
57
|
},
|
|
106
|
-
// Add more tools as needed
|
|
107
58
|
},
|
|
108
|
-
|
|
59
|
+
required: ['section'],
|
|
60
|
+
},
|
|
61
|
+
});
|
|
109
62
|
|
|
110
|
-
|
|
111
|
-
|
|
63
|
+
const showServiceTool = defineTool({
|
|
64
|
+
name: 'show_service',
|
|
65
|
+
description: 'Show details about a specific service',
|
|
66
|
+
parameters: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {
|
|
69
|
+
serviceId: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'The service ID',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
required: ['serviceId'],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Create handler with site content - prompt is auto-generated!
|
|
79
|
+
export const POST = createHandler({
|
|
80
|
+
model: 'google/gemini-2.0-flash-exp:free', // Free!
|
|
81
|
+
siteContent: {
|
|
82
|
+
name: 'Acme Dance Studio',
|
|
83
|
+
type: 'dance studio',
|
|
84
|
+
description: 'Premier dance education for all ages',
|
|
85
|
+
personality: 'warm, encouraging, and helpful',
|
|
86
|
+
pages: ['home', 'classes', 'teachers', 'schedule', 'contact'],
|
|
87
|
+
items: [
|
|
88
|
+
// Classes
|
|
89
|
+
{ id: 'ballet', name: 'Ballet', category: 'class', description: 'Classical ballet for ages 3-adult', price: '$80/month' },
|
|
90
|
+
{ id: 'jazz', name: 'Jazz', category: 'class', description: 'High-energy jazz for ages 6+', price: '$75/month' },
|
|
91
|
+
{ id: 'hip-hop', name: 'Hip Hop', category: 'class', description: 'Street dance styles for ages 8+', price: '$70/month' },
|
|
92
|
+
// Teachers
|
|
93
|
+
{ id: 'sarah', name: 'Sarah Johnson', category: 'teacher', description: 'Owner, 15 years experience, specializes in ballet' },
|
|
94
|
+
{ id: 'mike', name: 'Mike Chen', category: 'teacher', description: 'Hip hop and jazz instructor, 8 years experience' },
|
|
95
|
+
],
|
|
96
|
+
faqs: [
|
|
97
|
+
{ question: 'What should I wear?', answer: 'Leotard and ballet slippers for ballet, athletic wear for jazz and hip hop.' },
|
|
98
|
+
{ question: 'Do you offer trial classes?', answer: 'Yes! First class is free for new students.' },
|
|
99
|
+
],
|
|
100
|
+
contact: {
|
|
101
|
+
email: 'info@acmedance.com',
|
|
102
|
+
phone: '555-123-4567',
|
|
103
|
+
address: '123 Dance Street, NYC',
|
|
104
|
+
hours: 'Mon-Sat 9am-8pm',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
tools: [navigateTool, showServiceTool],
|
|
108
|
+
});
|
|
112
109
|
```
|
|
113
110
|
|
|
114
|
-
|
|
111
|
+
**The AI now automatically knows:**
|
|
112
|
+
- All your classes, teachers, pricing
|
|
113
|
+
- FAQs and contact info
|
|
114
|
+
- What tools to use and when
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
### 4. Add the Chat Widget
|
|
117
117
|
|
|
118
118
|
```tsx
|
|
119
|
+
// components/ChatWidget.tsx
|
|
119
120
|
'use client';
|
|
120
121
|
|
|
121
122
|
import { SitePilot } from 'ai-site-pilot';
|
|
@@ -123,15 +124,18 @@ import 'ai-site-pilot/styles.css';
|
|
|
123
124
|
|
|
124
125
|
export function ChatWidget() {
|
|
125
126
|
const handleToolCall = (name: string, args: Record<string, unknown>) => {
|
|
126
|
-
// Handle tool execution - this runs on the client
|
|
127
127
|
switch (name) {
|
|
128
128
|
case 'navigate_to_section':
|
|
129
|
-
document.getElementById(args.section as string)?.scrollIntoView({
|
|
129
|
+
document.getElementById(args.section as string)?.scrollIntoView({
|
|
130
|
+
behavior: 'smooth',
|
|
131
|
+
});
|
|
130
132
|
break;
|
|
131
|
-
case '
|
|
132
|
-
//
|
|
133
|
+
case 'show_service':
|
|
134
|
+
// Dispatch event for your page to handle
|
|
135
|
+
window.dispatchEvent(new CustomEvent('show-service', {
|
|
136
|
+
detail: { serviceId: args.serviceId },
|
|
137
|
+
}));
|
|
133
138
|
break;
|
|
134
|
-
// Handle other tools
|
|
135
139
|
}
|
|
136
140
|
};
|
|
137
141
|
|
|
@@ -140,347 +144,237 @@ export function ChatWidget() {
|
|
|
140
144
|
apiEndpoint="/api/chat"
|
|
141
145
|
onToolCall={handleToolCall}
|
|
142
146
|
suggestions={[
|
|
143
|
-
{ text: '
|
|
144
|
-
{ text: '
|
|
145
|
-
{ text: 'Contact
|
|
147
|
+
{ text: 'What classes do you offer?', icon: '💃' },
|
|
148
|
+
{ text: 'Meet the teachers', icon: '👩🏫' },
|
|
149
|
+
{ text: 'Contact us', icon: '📞' },
|
|
146
150
|
]}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
accentColor: '#3b82f6', // Your brand color
|
|
150
|
-
backgroundColor: '#0f172a', // Dark background
|
|
151
|
-
// See full theme options below
|
|
152
|
-
}}
|
|
151
|
+
theme={{ accent: 'pink' }} // or accentColor: '#ec4899'
|
|
152
|
+
welcomeMessage="Hi! I'm your dance studio assistant. How can I help you today?"
|
|
153
153
|
/>
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
### 5. Environment Variable
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
/>
|
|
160
|
+
```bash
|
|
161
|
+
# .env.local
|
|
162
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
182
163
|
```
|
|
183
164
|
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
/>
|
|
195
|
-
```
|
|
165
|
+
Get a free key at [openrouter.ai](https://openrouter.ai) - Gemini 2.0 Flash is free!
|
|
196
166
|
|
|
197
|
-
##
|
|
167
|
+
## Alternative: Manual System Prompt
|
|
198
168
|
|
|
199
|
-
|
|
169
|
+
If you need full control, use `systemPrompt` instead of `siteContent`:
|
|
200
170
|
|
|
201
171
|
```typescript
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
172
|
+
export const POST = createHandler({
|
|
173
|
+
model: 'google/gemini-2.0-flash-exp:free',
|
|
174
|
+
systemPrompt: `You are an assistant for Acme Dance Studio.
|
|
175
|
+
|
|
176
|
+
## Classes
|
|
177
|
+
- Ballet: Ages 3-adult, $80/month
|
|
178
|
+
- Jazz: Ages 6+, $75/month
|
|
179
|
+
- Hip Hop: Ages 8+, $70/month
|
|
180
|
+
|
|
181
|
+
## Tools
|
|
182
|
+
- navigate_to_section: Scroll to a section (hero, classes, teachers, contact)
|
|
183
|
+
- show_service: Show details about a class
|
|
184
|
+
|
|
185
|
+
When users ask about classes, provide specific details.
|
|
186
|
+
Use tools proactively to show relevant content.`,
|
|
187
|
+
tools: [navigateTool, showServiceTool],
|
|
219
188
|
});
|
|
220
189
|
```
|
|
221
190
|
|
|
222
|
-
##
|
|
223
|
-
|
|
224
|
-
For the API route, you'll need your AI provider's API key:
|
|
191
|
+
## SiteContent Schema
|
|
225
192
|
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
193
|
+
```typescript
|
|
194
|
+
interface SiteContent {
|
|
195
|
+
name: string; // Business name
|
|
196
|
+
type?: string; // Business type (e.g., 'dance studio')
|
|
197
|
+
description?: string; // Brief description
|
|
198
|
+
personality?: string; // AI personality (e.g., 'warm and helpful')
|
|
199
|
+
pages?: string[]; // Available navigation pages
|
|
200
|
+
items?: SiteContentItem[]; // Products, services, team, etc.
|
|
201
|
+
faqs?: Array<{ question: string; answer: string }>;
|
|
202
|
+
contact?: {
|
|
203
|
+
email?: string;
|
|
204
|
+
phone?: string;
|
|
205
|
+
address?: string;
|
|
206
|
+
hours?: string;
|
|
207
|
+
};
|
|
208
|
+
additionalContext?: string; // Extra info for the prompt
|
|
209
|
+
}
|
|
232
210
|
|
|
233
|
-
|
|
234
|
-
|
|
211
|
+
interface SiteContentItem {
|
|
212
|
+
id: string; // Unique identifier
|
|
213
|
+
name: string; // Display name
|
|
214
|
+
category?: string; // Category (e.g., 'class', 'teacher', 'product')
|
|
215
|
+
description?: string; // Description
|
|
216
|
+
[key: string]: unknown; // Any extra fields (price, duration, etc.)
|
|
217
|
+
}
|
|
235
218
|
```
|
|
236
219
|
|
|
237
|
-
##
|
|
238
|
-
|
|
239
|
-
Here's a full implementation for a portfolio site showing all three parts:
|
|
220
|
+
## Theme Presets
|
|
240
221
|
|
|
241
|
-
|
|
222
|
+
Use preset names for easy theming:
|
|
242
223
|
|
|
243
|
-
```
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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.`;
|
|
224
|
+
```tsx
|
|
225
|
+
<SitePilot theme={{ accent: 'pink' }} /> // Hot pink
|
|
226
|
+
<SitePilot theme={{ accent: 'amber' }} /> // Default orange/amber
|
|
227
|
+
<SitePilot theme={{ accent: 'blue' }} /> // Primary blue
|
|
228
|
+
<SitePilot theme={{ accent: 'green' }} /> // Emerald green
|
|
229
|
+
<SitePilot theme={{ accent: 'purple' }} /> // Violet purple
|
|
230
|
+
<SitePilot theme={{ accent: 'cyan' }} /> // Teal cyan
|
|
283
231
|
```
|
|
284
232
|
|
|
285
|
-
|
|
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
|
-
}
|
|
326
|
-
},
|
|
327
|
-
open_contact: {
|
|
328
|
-
description: 'Open the contact/hire modal',
|
|
329
|
-
parameters: { type: 'object', properties: {}, required: [] }
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
});
|
|
233
|
+
Or use a custom hex color:
|
|
333
234
|
|
|
334
|
-
|
|
335
|
-
}
|
|
235
|
+
```tsx
|
|
236
|
+
<SitePilot theme={{ accentColor: '#8b5cf6' }} />
|
|
336
237
|
```
|
|
337
238
|
|
|
338
|
-
|
|
239
|
+
## Tool-Only Response Handling
|
|
240
|
+
|
|
241
|
+
When the AI uses tools without text, customize the fallback message:
|
|
339
242
|
|
|
340
243
|
```tsx
|
|
341
|
-
|
|
342
|
-
'use client';
|
|
244
|
+
import { SitePilot, createFallbackMessageGenerator } from 'ai-site-pilot';
|
|
343
245
|
|
|
344
|
-
|
|
345
|
-
|
|
246
|
+
const generateFallback = createFallbackMessageGenerator({
|
|
247
|
+
navigate_to_section: (args) => `Scrolled to **${args.section}**.`,
|
|
248
|
+
show_service: (args) => `Showing details for **${args.serviceId}**.`,
|
|
249
|
+
filter_products: (args) => `Filtered to **${args.category}** products.`,
|
|
250
|
+
});
|
|
346
251
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
behavior: 'smooth'
|
|
353
|
-
});
|
|
354
|
-
break;
|
|
252
|
+
<SitePilot
|
|
253
|
+
apiEndpoint="/api/chat"
|
|
254
|
+
generateFallbackMessage={generateFallback}
|
|
255
|
+
/>
|
|
256
|
+
```
|
|
355
257
|
|
|
356
|
-
|
|
357
|
-
// Dispatch custom event for your page to handle
|
|
358
|
-
window.dispatchEvent(new CustomEvent('filter-projects', {
|
|
359
|
-
detail: { category: args.category }
|
|
360
|
-
}));
|
|
361
|
-
break;
|
|
258
|
+
## Full Props Reference
|
|
362
259
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
break;
|
|
260
|
+
```typescript
|
|
261
|
+
interface SitePilotProps {
|
|
262
|
+
// Required
|
|
263
|
+
apiEndpoint: string;
|
|
368
264
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
265
|
+
// Tool handling
|
|
266
|
+
onToolCall?: (name: string, args: Record<string, unknown>) => void;
|
|
267
|
+
generateFallbackMessage?: (toolName: string, args: Record<string, unknown>) => string;
|
|
268
|
+
|
|
269
|
+
// UI customization
|
|
270
|
+
suggestions?: Array<{ text: string; icon?: string }>;
|
|
271
|
+
welcomeMessage?: string;
|
|
272
|
+
placeholder?: string;
|
|
273
|
+
defaultOpen?: boolean;
|
|
274
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
275
|
+
|
|
276
|
+
// Theme
|
|
277
|
+
theme?: {
|
|
278
|
+
accent?: 'amber' | 'pink' | 'blue' | 'green' | 'purple' | 'red' | 'cyan' | 'orange';
|
|
279
|
+
accentColor?: string; // Hex color (overrides accent)
|
|
280
|
+
backgroundColor?: string;
|
|
281
|
+
radius?: number;
|
|
373
282
|
};
|
|
374
283
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
{ text: "What's live?", icon: "🚀" },
|
|
382
|
-
{ text: "I want to hire you", icon: "💡" },
|
|
383
|
-
]}
|
|
384
|
-
theme={{
|
|
385
|
-
accentColor: '#8b5cf6',
|
|
386
|
-
backgroundColor: '#0f0f23',
|
|
387
|
-
}}
|
|
388
|
-
/>
|
|
389
|
-
);
|
|
284
|
+
// Features
|
|
285
|
+
features?: {
|
|
286
|
+
speech?: boolean; // Voice input
|
|
287
|
+
tts?: boolean; // Text-to-speech
|
|
288
|
+
fullscreen?: boolean; // Fullscreen toggle
|
|
289
|
+
};
|
|
390
290
|
}
|
|
391
291
|
```
|
|
392
292
|
|
|
393
|
-
|
|
293
|
+
## Common Patterns
|
|
294
|
+
|
|
295
|
+
### E-commerce Site
|
|
394
296
|
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
|
|
297
|
+
```typescript
|
|
298
|
+
siteContent: {
|
|
299
|
+
name: 'MyStore',
|
|
300
|
+
type: 'online store',
|
|
301
|
+
items: [
|
|
302
|
+
{ id: 'laptop-1', name: 'MacBook Pro', category: 'product', price: '$1999', inStock: true },
|
|
303
|
+
{ id: 'phone-1', name: 'iPhone 15', category: 'product', price: '$999', inStock: true },
|
|
304
|
+
],
|
|
305
|
+
pages: ['home', 'products', 'cart', 'checkout'],
|
|
306
|
+
}
|
|
398
307
|
|
|
399
|
-
|
|
308
|
+
// Tools: search_products, filter_by_category, add_to_cart, open_product
|
|
309
|
+
```
|
|
400
310
|
|
|
401
|
-
|
|
402
|
-
const [filter, setFilter] = useState('All');
|
|
403
|
-
const [selectedProject, setSelectedProject] = useState(null);
|
|
404
|
-
const [showContact, setShowContact] = useState(false);
|
|
311
|
+
### Portfolio Site
|
|
405
312
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
313
|
+
```typescript
|
|
314
|
+
siteContent: {
|
|
315
|
+
name: 'Jane Developer',
|
|
316
|
+
type: 'portfolio',
|
|
317
|
+
items: [
|
|
318
|
+
{ id: 'project-1', name: 'Acme Dashboard', category: 'project', status: 'Live', tech: 'React, Node' },
|
|
319
|
+
{ id: 'project-2', name: 'FitTrack App', category: 'project', status: 'Live', tech: 'React Native' },
|
|
320
|
+
],
|
|
321
|
+
pages: ['hero', 'projects', 'about', 'contact'],
|
|
322
|
+
}
|
|
410
323
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
window.addEventListener('open-contact', handleContact);
|
|
324
|
+
// Tools: filter_projects, open_project_modal, navigate_to_section, open_contact
|
|
325
|
+
```
|
|
414
326
|
|
|
415
|
-
|
|
416
|
-
window.removeEventListener('filter-projects', handleFilter as EventListener);
|
|
417
|
-
window.removeEventListener('open-project', handleProject as EventListener);
|
|
418
|
-
window.removeEventListener('open-contact', handleContact);
|
|
419
|
-
};
|
|
420
|
-
}, []);
|
|
327
|
+
### SaaS Landing Page
|
|
421
328
|
|
|
422
|
-
|
|
329
|
+
```typescript
|
|
330
|
+
siteContent: {
|
|
331
|
+
name: 'CloudSync',
|
|
332
|
+
type: 'SaaS platform',
|
|
333
|
+
description: 'Real-time data synchronization for teams',
|
|
334
|
+
items: [
|
|
335
|
+
{ id: 'starter', name: 'Starter Plan', category: 'pricing', price: '$9/mo', features: '5 users, 10GB' },
|
|
336
|
+
{ id: 'pro', name: 'Pro Plan', category: 'pricing', price: '$29/mo', features: '25 users, 100GB' },
|
|
337
|
+
],
|
|
338
|
+
faqs: [
|
|
339
|
+
{ question: 'Is there a free trial?', answer: 'Yes, 14-day free trial on all plans.' },
|
|
340
|
+
],
|
|
423
341
|
}
|
|
342
|
+
|
|
343
|
+
// Tools: navigate_to_section, show_pricing, open_signup, open_demo
|
|
424
344
|
```
|
|
425
345
|
|
|
426
|
-
##
|
|
346
|
+
## Troubleshooting
|
|
427
347
|
|
|
428
|
-
###
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
filter_by_category: { /* filter product grid */ },
|
|
433
|
-
add_to_cart: { /* add item to cart */ },
|
|
434
|
-
open_product: { /* show product details */ },
|
|
435
|
-
};
|
|
348
|
+
### Button only shows icon, no "Ask AI" text
|
|
349
|
+
Your Tailwind config isn't scanning the package:
|
|
350
|
+
```js
|
|
351
|
+
content: ['./node_modules/ai-site-pilot/dist/**/*.{js,mjs}']
|
|
436
352
|
```
|
|
437
353
|
|
|
438
|
-
###
|
|
354
|
+
### Theme colors not working
|
|
355
|
+
Use component props, not CSS variables:
|
|
439
356
|
```tsx
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
navigate_to_page: { /* go to specific doc page */ },
|
|
443
|
-
show_code_example: { /* display code snippet */ },
|
|
444
|
-
};
|
|
445
|
-
```
|
|
357
|
+
// Good
|
|
358
|
+
<SitePilot theme={{ accent: 'pink' }} />
|
|
446
359
|
|
|
447
|
-
|
|
448
|
-
```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
|
-
};
|
|
360
|
+
// Bad - don't set CSS vars directly
|
|
455
361
|
```
|
|
456
362
|
|
|
457
|
-
|
|
458
|
-
|
|
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)
|
|
363
|
+
### AI gives generic responses
|
|
364
|
+
Use `siteContent` to provide actual data about your site. The AI only knows what you tell it.
|
|
462
365
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
366
|
+
### Tools not executing
|
|
367
|
+
1. Check `onToolCall` is passed to SitePilot
|
|
368
|
+
2. Verify tool names match between API and client handler
|
|
369
|
+
3. Check browser console for errors
|
|
467
370
|
|
|
468
|
-
|
|
469
|
-
- CSS variables can be overridden in your global CSS
|
|
470
|
-
- The component uses `z-index: 200` - adjust if needed
|
|
371
|
+
## Available Models
|
|
471
372
|
|
|
472
|
-
|
|
373
|
+
| Model | ID | Notes |
|
|
374
|
+
|-------|-----|-------|
|
|
375
|
+
| Gemini 2.0 Flash | `google/gemini-2.0-flash-exp:free` | **Free!** Default |
|
|
376
|
+
| GPT-4o | `openai/gpt-4o` | Best overall |
|
|
377
|
+
| Claude 3.5 Sonnet | `anthropic/claude-3.5-sonnet` | Best for coding |
|
|
378
|
+
| Llama 3.1 70B | `meta-llama/llama-3.1-70b-instruct` | Open source |
|
|
473
379
|
|
|
474
|
-
|
|
475
|
-
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
|
|
480
|
-
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
|
|
485
|
-
}
|
|
486
|
-
```
|
|
380
|
+
See all models at [openrouter.ai/models](https://openrouter.ai/models)
|
package/package.json
CHANGED