kaddidlehopper 0.3.1 → 0.4.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.
Files changed (36) hide show
  1. package/add-ons/ai/assets/AGENTS.md.append +24 -0
  2. package/add-ons/ai/info.json +11 -17
  3. package/add-ons/db/assets/AGENTS.md.append +22 -0
  4. package/add-ons/db/info.json +10 -10
  5. package/add-ons/forms/assets/AGENTS.md.append +13 -0
  6. package/add-ons/forms/info.json +6 -10
  7. package/dist/agents-md.js +103 -0
  8. package/dist/cli.js +3 -0
  9. package/dist/types/agents-md.d.ts +5 -0
  10. package/examples/ai-chat/assets/AGENTS.md.append +24 -0
  11. package/examples/ai-chat/info.json +11 -11
  12. package/examples/blog/assets/AGENTS.md.append +18 -0
  13. package/examples/blog/info.json +25 -29
  14. package/examples/calculator/assets/AGENTS.md.append +9 -0
  15. package/examples/calculator/info.json +8 -8
  16. package/examples/dashboard/assets/AGENTS.md.append +12 -0
  17. package/examples/dashboard/info.json +7 -8
  18. package/examples/ecommerce/assets/AGENTS.md.append +22 -0
  19. package/examples/ecommerce/info.json +24 -27
  20. package/examples/events/assets/AGENTS.md.append +21 -0
  21. package/examples/events/info.json +46 -60
  22. package/examples/marketing/assets/AGENTS.md.append +15 -0
  23. package/examples/marketing/info.json +17 -23
  24. package/examples/portfolio/assets/AGENTS.md.append +21 -0
  25. package/examples/portfolio/info.json +37 -44
  26. package/examples/resume/assets/AGENTS.md.append +19 -0
  27. package/examples/resume/info.json +24 -15
  28. package/examples/saas/assets/AGENTS.md.append +9 -0
  29. package/examples/saas/info.json +9 -13
  30. package/examples/survey/assets/AGENTS.md.append +9 -0
  31. package/examples/survey/info.json +7 -8
  32. package/package.json +1 -1
  33. package/project/base/AGENTS.md +86 -0
  34. package/project/info.json +17 -0
  35. package/src/agents-md.ts +139 -0
  36. package/src/cli.ts +4 -0
@@ -0,0 +1,24 @@
1
+ ### AI Integration
2
+
3
+ Multi-provider AI chat with fallback chain:
4
+
5
+ 1. Anthropic Claude (preferred)
6
+ 2. OpenAI GPT-4o
7
+ 3. Google Gemini
8
+ 4. Ollama (local)
9
+
10
+ **Tools available to AI:**
11
+ - `getWeather` - Get the current weather for a city. Returns temperature, condition, and humidity.
12
+
13
+ ## Environment Variables
14
+
15
+ For AI functionality, set one or more:
16
+
17
+ ```
18
+ ANTHROPIC_API_KEY=...
19
+ OPENAI_API_KEY=...
20
+ GOOGLE_GENERATIVE_AI_API_KEY=...
21
+ OLLAMA_BASE_URL=...
22
+ ```
23
+
24
+ The application uses the first available provider in the fallback chain.
@@ -6,22 +6,16 @@
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
8
  "priority": 20,
9
- "routes": [
10
- {
11
- "icon": "MessagesSquare",
12
- "url": "/chat",
13
- "name": "Chat",
14
- "path": "src/routes/chat.tsx",
15
- "jsName": "ChatPage"
16
- }
17
- ],
18
- "integrations": [
19
- {
20
- "type": "header-user",
21
- "path": "src/components/AIAssistant.tsx",
22
- "jsName": "AIAssistant"
23
- }
24
- ],
9
+ "routes": [{"icon": "MessagesSquare", "url": "/chat", "name": "Chat", "path": "src/routes/chat.tsx", "jsName": "ChatPage"}],
10
+ "integrations": [{"type": "header-user", "path": "src/components/AIAssistant.tsx", "jsName": "AIAssistant"}],
25
11
  "dependsOn": [],
26
- "variables": []
12
+ "variables": [],
13
+ "packageFileDescriptions": {
14
+ "src/lib/ai-hook.ts": "useAIChat hook: useChat with fetchServerSentEvents connection to /api/chat.",
15
+ "src/routes/chat.tsx": "Chat page route (/chat): Weather Chat UI with messages, input form, send/stop.",
16
+ "src/routes/api.chat.ts": "POST handler for /api/chat: multi-provider AI (Anthropic, OpenAI, Gemini, Ollama) with getWeather tool and SSE streaming.",
17
+ "src/lib/weather-tools.ts": "TanStack AI getWeather tool definition; server returns mock temperature, condition, humidity for a city.",
18
+ "src/routes/chat.css": "Chat page styles: prose/markdown, scrollbar, message animations.",
19
+ "src/components/AIAssistant.tsx": "Pop-up AI assistant component for header; toggleable chat panel with useAIChat."
20
+ }
27
21
  }
@@ -0,0 +1,22 @@
1
+ ### Netlify DB Integration
2
+
3
+ Guestbook demo powered by Netlify DB (Neon Postgres) with Drizzle ORM.
4
+
5
+ **Setup:**
6
+ 1. Link project: `netlify login` then `netlify init`
7
+ 2. Provision database: `netlify db init` (creates Neon Postgres, sets `DATABASE_URL`)
8
+ 3. Push schema: `npx drizzle-kit push` (creates `guestbook` table from `src/db/schema.ts`)
9
+ 4. Run locally: `netlify dev` (visit `/db-example`)
10
+
11
+ **Key files:**
12
+ - `src/db/schema.ts` - Guestbook table (id, name, message, createdAt)
13
+ - `src/server/guestbook.functions.ts` - Server functions: `getEntries`, `addEntry`
14
+ - `drizzle.config.ts` - Drizzle Kit config for migrations
15
+
16
+ **Dependencies:** drizzle-orm, @neondatabase/serverless, drizzle-kit
17
+
18
+ ## Environment Variables
19
+
20
+ ```
21
+ DATABASE_URL=... # Auto-set by netlify db init; pull with netlify env:pull
22
+ ```
@@ -6,16 +6,16 @@
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
8
  "priority": 20,
9
- "routes": [
10
- {
11
- "icon": "Database",
12
- "url": "/db-example",
13
- "name": "DB Example",
14
- "path": "src/routes/db-example.tsx",
15
- "jsName": "DBExample"
16
- }
17
- ],
9
+ "routes": [{"icon": "Database", "url": "/db-example", "name": "DB Example", "path": "src/routes/db-example.tsx", "jsName": "DBExample"}],
18
10
  "integrations": [],
19
11
  "dependsOn": [],
20
- "variables": []
12
+ "variables": [],
13
+ "packageFileDescriptions": {
14
+ "DB-SETUP.md": "Setup guide: link to Netlify, run netlify db init, configure DATABASE_URL.",
15
+ "src/routes/db-example.tsx": "Guestbook route (/db-example): form to add entries, list from getEntries/addEntry.",
16
+ "src/server/guestbook.functions.ts": "Server functions: getEntries (list), addEntry (create) for guestbook via Drizzle.",
17
+ "src/db/index.ts": "Drizzle + Neon client; exports db and schema.",
18
+ "src/db/schema.ts": "Guestbook table schema: id, name, message, createdAt.",
19
+ "drizzle.config.ts": "Drizzle Kit config for migrations; postgres, schema path, DATABASE_URL."
20
+ }
21
21
  }
@@ -0,0 +1,13 @@
1
+ ### Netlify Forms Integration
2
+
3
+ Signup form powered by Netlify Forms with honeypot spam protection. No server-side code required.
4
+
5
+ **How it works:**
6
+ - Form submissions are handled by Netlify at build/deploy
7
+ - Add `data-netlify="true"` to the form
8
+ - Spam protection: `netlify-honeypot="bot-field"` + hidden input with `name="bot-field"`
9
+ - `public/form-example.html` declares the form (hidden) so Netlify detects it during build
10
+
11
+ **Route:** `/form-example` - Signup form (name, email)
12
+
13
+ No environment variables required. Works after deploy to Netlify.
@@ -6,16 +6,12 @@
6
6
  "modes": ["file-router"],
7
7
  "type": "add-on",
8
8
  "priority": 20,
9
- "routes": [
10
- {
11
- "icon": "FormInput",
12
- "url": "/form-example",
13
- "name": "Form Example",
14
- "path": "src/routes/form-example.tsx",
15
- "jsName": "FormExample"
16
- }
17
- ],
9
+ "routes": [{"icon": "FormInput", "url": "/form-example", "name": "Form Example", "path": "src/routes/form-example.tsx", "jsName": "FormExample"}],
18
10
  "integrations": [],
19
11
  "dependsOn": [],
20
- "variables": []
12
+ "variables": [],
13
+ "packageFileDescriptions": {
14
+ "src/routes/form-example.tsx": "Form example route (/form-example): Netlify Forms signup with honeypot spam protection.",
15
+ "public/form-example.html": "Static HTML form declaration for Netlify Forms; name, email, bot-field."
16
+ }
21
17
  }
@@ -0,0 +1,103 @@
1
+ import { dirname, join, relative } from 'node:path';
2
+ import { readdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { fileURLToPath } from 'node:url';
4
+ const PLACEHOLDER = '[[[DIRECTORY STRUCTURE]]]';
5
+ const IGNORED_DIRS = new Set([
6
+ 'node_modules',
7
+ '.git',
8
+ 'dist',
9
+ 'dist-ssr',
10
+ '.netlify',
11
+ '.tanstack',
12
+ '.DS_Store',
13
+ ]);
14
+ function buildDescriptionLookup(descriptions) {
15
+ const lookup = new Map();
16
+ for (const [key, desc] of Object.entries(descriptions)) {
17
+ const normalizedKey = key.replace(/\\/g, '/');
18
+ lookup.set(normalizedKey, desc);
19
+ if (normalizedKey.endsWith('.ejs')) {
20
+ lookup.set(normalizedKey.slice(0, -4), desc);
21
+ }
22
+ if (normalizedKey.startsWith('_dot_')) {
23
+ lookup.set('.' + normalizedKey.slice(5), desc);
24
+ }
25
+ }
26
+ return lookup;
27
+ }
28
+ async function loadFileDescriptions(addOnDescriptions) {
29
+ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
30
+ const infoPath = join(packageRoot, 'project', 'info.json');
31
+ const lookup = new Map();
32
+ try {
33
+ const info = await readFile(infoPath, 'utf-8');
34
+ const { packageFileDescriptions } = JSON.parse(info);
35
+ if (packageFileDescriptions) {
36
+ for (const [key, desc] of buildDescriptionLookup(packageFileDescriptions)) {
37
+ lookup.set(key, desc);
38
+ }
39
+ }
40
+ }
41
+ catch {
42
+ // No info.json or invalid, continue
43
+ }
44
+ if (addOnDescriptions) {
45
+ for (const addOn of addOnDescriptions) {
46
+ if (addOn.packageFileDescriptions) {
47
+ for (const [key, desc] of buildDescriptionLookup(addOn.packageFileDescriptions)) {
48
+ lookup.set(key, desc);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ return lookup;
54
+ }
55
+ async function buildFileTree(dirPath, rootPath, descriptions, prefix = '') {
56
+ const entries = await readdir(dirPath, { withFileTypes: true });
57
+ const filtered = entries
58
+ .filter((e) => !e.name.startsWith('.') || e.name === '.gitignore')
59
+ .filter((e) => !IGNORED_DIRS.has(e.name))
60
+ .sort((a, b) => {
61
+ // Directories first, then files; alphabetically within each
62
+ if (a.isDirectory() !== b.isDirectory()) {
63
+ return a.isDirectory() ? -1 : 1;
64
+ }
65
+ return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
66
+ });
67
+ const lines = [];
68
+ for (let i = 0; i < filtered.length; i++) {
69
+ const entry = filtered[i];
70
+ const isLastEntry = i === filtered.length - 1;
71
+ const connector = isLastEntry ? '└── ' : '├── ';
72
+ const fullPath = join(dirPath, entry.name);
73
+ const relPath = relative(rootPath, fullPath).replace(/\\/g, '/');
74
+ const description = descriptions.get(relPath);
75
+ const suffix = description ? ` # ${description}` : '';
76
+ lines.push(`${prefix}${connector}${entry.name}${suffix}`);
77
+ if (entry.isDirectory()) {
78
+ const childPrefix = prefix + (isLastEntry ? ' ' : '│ ');
79
+ const childLines = await buildFileTree(join(dirPath, entry.name), rootPath, descriptions, childPrefix);
80
+ lines.push(...childLines);
81
+ }
82
+ }
83
+ return lines;
84
+ }
85
+ export async function generateAgentsMd(targetDir, _projectName, chosenAddOns) {
86
+ const agentsMdPath = join(targetDir, 'AGENTS.md');
87
+ let content;
88
+ try {
89
+ content = await readFile(agentsMdPath, 'utf-8');
90
+ }
91
+ catch {
92
+ // No AGENTS.md template, skip
93
+ return;
94
+ }
95
+ if (!content.includes(PLACEHOLDER)) {
96
+ return;
97
+ }
98
+ const descriptions = await loadFileDescriptions(chosenAddOns);
99
+ const treeLines = await buildFileTree(targetDir, targetDir, descriptions);
100
+ const tree = treeLines.length > 0 ? treeLines.join('\n') : '(empty)';
101
+ const updatedContent = content.replace(PLACEHOLDER, tree);
102
+ await writeFile(agentsMdPath, updatedContent, 'utf-8');
103
+ }
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import { Command, InvalidArgumentError } from 'commander';
4
4
  import chalk from 'chalk';
5
5
  import validatePackageName from 'validate-npm-package-name';
6
6
  import { SUPPORTED_PACKAGE_MANAGERS, createApp, createDefaultEnvironment, finalizeAddOns, getAllAddOns, getFrameworkByName, getPackageManager, DEFAULT_PACKAGE_MANAGER, populateAddOnOptionsDefaults, } from '@tanstack/cta-engine';
7
+ import { generateAgentsMd } from './agents-md.js';
7
8
  // Utility functions
8
9
  function sanitizePackageName(name) {
9
10
  return name
@@ -248,6 +249,8 @@ export function cli({ name, appName, defaultFramework, forcedMode, forcedAddOns
248
249
  }
249
250
  }
250
251
  }
252
+ // Generate an AGENTS.md file in the root of the project
253
+ await generateAgentsMd(targetDir, resolvedProjectName, chosenAddOns);
251
254
  });
252
255
  program.parse();
253
256
  }
@@ -0,0 +1,5 @@
1
+ type FileDescriptions = Record<string, string>;
2
+ export declare function generateAgentsMd(targetDir: string, _projectName: string, chosenAddOns?: Array<{
3
+ packageFileDescriptions?: FileDescriptions;
4
+ }>): Promise<void>;
5
+ export {};
@@ -0,0 +1,24 @@
1
+ ### AI Integration
2
+
3
+ Multi-provider AI chat with fallback chain:
4
+
5
+ 1. Anthropic Claude (preferred)
6
+ 2. OpenAI GPT-4o
7
+ 3. Google Gemini
8
+ 4. Ollama (local)
9
+
10
+ **Tools available to AI:**
11
+ - `getWeather` - Get the current weather for a city. Returns temperature, condition, and humidity.
12
+
13
+ ## Environment Variables
14
+
15
+ For AI functionality, set one or more:
16
+
17
+ ```
18
+ ANTHROPIC_API_KEY=...
19
+ OPENAI_API_KEY=...
20
+ GOOGLE_GENERATIVE_AI_API_KEY=...
21
+ OLLAMA_BASE_URL=...
22
+ ```
23
+
24
+ The application uses the first available provider in the fallback chain.
@@ -7,18 +7,18 @@
7
7
  "priority": 10,
8
8
  "link": "",
9
9
  "routes": [
10
- {
11
- "url": "/",
12
- "path": "src/routes/index.tsx",
13
- "jsName": "Home"
14
- },
15
- {
16
- "url": "/api/chat",
17
- "path": "src/routes/api.chat.ts",
18
- "jsName": "ChatAPI"
19
- }
10
+ {"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"},
11
+ {"url": "/api/chat", "path": "src/routes/api.chat.ts", "jsName": "ChatAPI"}
20
12
  ],
21
13
  "integrations": [],
22
14
  "dependsOn": [],
23
- "variables": []
15
+ "variables": [],
16
+ "packageFileDescriptions": {
17
+ "src/styles.css": "Global styles: Tailwind, highlight.js theme, custom scrollbar, prose/markdown styles for chat UI.",
18
+ "src/lib/weather-tools.ts": "TanStack AI tool definition for getWeather; server implementation returns mock temperature, condition, humidity for a city.",
19
+ "src/lib/ai-hook.ts": "useAIChat hook: useChat with fetchServerSentEvents connection to /api/chat.",
20
+ "src/routes/api.chat.ts": "POST handler for /api/chat: multi-provider AI (Anthropic, OpenAI, Gemini, Ollama) with getWeather tool and SSE streaming.",
21
+ "src/routes/index.tsx": "Home route: Weather Chat UI with messages list, input form, send/stop, Streamdown markdown rendering.",
22
+ "src/routes/__root.tsx": "Root layout: HTML shell, Weather Chat header, styles, TanStack Devtools."
23
+ }
24
24
  }
@@ -0,0 +1,18 @@
1
+ ### Content Collections
2
+
3
+ Markdown files in `content/posts/` are type-safe blog posts:
4
+
5
+ - Frontmatter validated against Zod schemas in `content-collections.ts`
6
+ - Imported as typed array: `import { allPosts } from 'content-collections'`
7
+ - Each post has: `title`, `summary`, `categories[]`, `slug`, `image`, `date`, `content`
8
+
9
+ ### VacayAssistant AI Integration
10
+
11
+ **Tools available to AI:**
12
+ - `getCurrentBlogPost` - Get full content and metadata of the current blog post by slug
13
+ - `getAllBlogPosts` - List all posts with titles, summaries, categories
14
+ - `searchBlogPosts` - Search posts by title, summary, or categories
15
+
16
+ ## Environment Variables
17
+
18
+ For AI: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, or OLLAMA_BASE_URL (same as ai add-on).
@@ -7,37 +7,33 @@
7
7
  "priority": 10,
8
8
  "link": "",
9
9
  "routes": [
10
- {
11
- "url": "/",
12
- "path": "src/routes/index.tsx",
13
- "jsName": "BlogHome"
14
- },
15
- {
16
- "url": "/posts/$slug",
17
- "path": "src/routes/posts.$slug.tsx",
18
- "jsName": "BlogPost"
19
- },
20
- {
21
- "url": "/category/$category",
22
- "path": "src/routes/category.$category.tsx",
23
- "jsName": "BlogCategory"
24
- }
25
- ],
26
- "integrations": [
27
- {
28
- "type": "vite-plugin",
29
- "import": "import contentCollections from '@content-collections/vite'",
30
- "code": "contentCollections()"
31
- }
10
+ {"url": "/", "path": "src/routes/index.tsx", "jsName": "BlogHome"},
11
+ {"url": "/posts/$slug", "path": "src/routes/posts.$slug.tsx", "jsName": "BlogPost"},
12
+ {"url": "/category/$category", "path": "src/routes/category.$category.tsx", "jsName": "BlogCategory"}
32
13
  ],
14
+ "integrations": [{"type": "vite-plugin", "import": "import contentCollections from '@content-collections/vite'", "code": "contentCollections()"}],
33
15
  "dependsOn": [],
34
16
  "variables": [],
35
- "bareBones": {
36
- "deleteFiles": [
37
- "public/jungle.jpg",
38
- "public/mountains.jpg",
39
- "public/snorkeling.jpg",
40
- "public/waterfall.jpg"
41
- ]
17
+ "bareBones": {"deleteFiles": ["public/jungle.jpg", "public/mountains.jpg", "public/snorkeling.jpg", "public/waterfall.jpg"]},
18
+ "packageFileDescriptions": {
19
+ "content-collections.ts": "Content Collections config: posts schema (title, summary, categories, slug, image, date).",
20
+ "content/posts/beach.md": "Blog post: beach adventure.",
21
+ "content/posts/jungle.md.ejs": "Blog post template: jungle adventure.",
22
+ "content/posts/mountains.md.ejs": "Blog post template: mountains adventure.",
23
+ "content/posts/snorkeling.md.ejs": "Blog post template: snorkeling adventure.",
24
+ "content/posts/waterfall.md.ejs": "Blog post template: waterfall adventure.",
25
+ "src/styles.css": "Global styles: Tailwind, prose, highlight.js.",
26
+ "src/routes/index.tsx": "Blog home: post list, VacayAssistant.",
27
+ "src/routes/posts.$slug.tsx": "Post detail route: single post by slug.",
28
+ "src/routes/category.$category.tsx": "Category route: posts filtered by category.",
29
+ "src/routes/api.blog-chat.ts": "POST handler for blog AI chat with getPostBySlug, getAllBlogPosts tools.",
30
+ "src/routes/__root.tsx": "Root layout: Header, styles, TanStack Devtools.",
31
+ "src/lib/utils.ts": "cn() helper for conditional Tailwind class merging.",
32
+ "src/lib/blog-tools.ts": "AI tools: getPostBySlug, getAllBlogPosts, getPostsByCategory for VacayAssistant.",
33
+ "src/lib/blog-ai-hook.ts": "useBlogChat hook for /api/blog-chat.",
34
+ "src/components/ui/card.tsx": "Card UI component.",
35
+ "src/components/blog-posts.tsx": "Blog post list/card display component.",
36
+ "src/components/VacayAssistant.tsx": "AI assistant for blog Q&A.",
37
+ "src/components/Header.tsx": "Site header with nav."
42
38
  }
43
39
  }
@@ -0,0 +1,9 @@
1
+ ### Calculator Component
2
+
3
+ iOS-style calculator built with React `useReducer` for state management.
4
+
5
+ **State pattern:** `display`, `previousValue`, `operation`, `overwrite`
6
+
7
+ **Actions:** ADD_DIGIT, CHOOSE_OPERATION, EVALUATE, CLEAR, DELETE_DIGIT, PERCENT, TOGGLE_SIGN
8
+
9
+ No special dependencies beyond base TanStack Start. Pure React + Tailwind CSS.
@@ -6,14 +6,14 @@
6
6
  "type": "example",
7
7
  "priority": 10,
8
8
  "link": "",
9
- "routes": [
10
- {
11
- "url": "/",
12
- "path": "src/routes/index.tsx",
13
- "jsName": "Home"
14
- }
15
- ],
9
+ "routes": [{"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"}],
16
10
  "integrations": [],
17
11
  "dependsOn": [],
18
- "variables": []
12
+ "variables": [],
13
+ "packageFileDescriptions": {
14
+ "src/routes/index.tsx": "Home route: renders Calculator component.",
15
+ "src/routes/__root.tsx": "Root layout: HTML shell, styles.",
16
+ "src/components/Calculator.tsx": "iOS-style calculator: digits, operations, evaluate, clear, percent.",
17
+ "src/components/Header.tsx": "Header component."
18
+ }
19
19
  }
@@ -0,0 +1,12 @@
1
+ ### Chart.js Dashboard
2
+
3
+ Analytics dashboard with Chart.js and react-chartjs-2.
4
+
5
+ **Dependencies:** chart.js, react-chartjs-2
6
+
7
+ **Chart types:**
8
+ - Bar - Revenue by month
9
+ - Line - User growth
10
+ - Doughnut - Sales by category
11
+
12
+ **Setup:** Register Chart.js components before use (CategoryScale, LinearScale, BarElement, LineElement, PointElement, ArcElement, Title, Tooltip, Legend, Filler).
@@ -6,14 +6,13 @@
6
6
  "type": "example",
7
7
  "priority": 10,
8
8
  "link": "",
9
- "routes": [
10
- {
11
- "url": "/",
12
- "path": "src/routes/index.tsx",
13
- "jsName": "Home"
14
- }
15
- ],
9
+ "routes": [{"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"}],
16
10
  "integrations": [],
17
11
  "dependsOn": [],
18
- "variables": []
12
+ "variables": [],
13
+ "packageFileDescriptions": {
14
+ "src/routes/index.tsx": "Dashboard home: Bar, Line, Doughnut charts (revenue, users, sales).",
15
+ "src/routes/__root.tsx": "Root layout: Header, styles.",
16
+ "src/components/Header.tsx": "Header component."
17
+ }
19
18
  }
@@ -0,0 +1,22 @@
1
+ ### Ecommerce Integration
2
+
3
+ Motorcycle ecommerce site with Stripe checkout and AI shopping assistant.
4
+
5
+ **Stripe checkout:**
6
+ - `createCheckoutSession` server function in `src/lib/stripe.server.ts`
7
+ - BuyButton component redirects to Stripe Checkout
8
+ - Routes: `/checkout/success`, `/checkout/cancel`
9
+
10
+ **AI tools available:**
11
+ - `getMotorcycles` - Get all motorcycles from catalog
12
+ - `recommendMotorcycle` - Display motorcycle recommendation card (MUST use for recommendations; do not write recommendations manually)
13
+
14
+ **Dependencies:** stripe, @tanstack/ai, streamdown
15
+
16
+ ## Environment Variables
17
+
18
+ ```
19
+ STRIPE_SECRET_KEY=... # Required for checkout
20
+ ```
21
+
22
+ For AI assistant: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, or OLLAMA_BASE_URL (same as ai add-on).
@@ -7,34 +7,31 @@
7
7
  "priority": 10,
8
8
  "link": "",
9
9
  "routes": [
10
- {
11
- "url": "/",
12
- "name": "Home",
13
- "path": "src/routes/index.tsx",
14
- "jsName": "MotorcyclesIndex"
15
- },
16
- {
17
- "url": "/motorcycles/$motorcycleId",
18
- "path": "src/routes/motorcycles/$motorcycleId.tsx",
19
- "jsName": "MotorcycleDetail"
20
- },
21
- {
22
- "url": "/checkout/success",
23
- "path": "src/routes/checkout/success.tsx",
24
- "jsName": "CheckoutSuccess"
25
- },
26
- {
27
- "url": "/checkout/cancel",
28
- "path": "src/routes/checkout/cancel.tsx",
29
- "jsName": "CheckoutCancel"
30
- },
31
- {
32
- "url": "/api/motorcycle-chat",
33
- "path": "src/routes/api.motorcycle-chat.ts",
34
- "jsName": "MotorcycleChatAPI"
35
- }
10
+ {"url": "/", "name": "Home", "path": "src/routes/index.tsx", "jsName": "MotorcyclesIndex"},
11
+ {"url": "/motorcycles/$motorcycleId", "path": "src/routes/motorcycles/$motorcycleId.tsx", "jsName": "MotorcycleDetail"},
12
+ {"url": "/checkout/success", "path": "src/routes/checkout/success.tsx", "jsName": "CheckoutSuccess"},
13
+ {"url": "/checkout/cancel", "path": "src/routes/checkout/cancel.tsx", "jsName": "CheckoutCancel"},
14
+ {"url": "/api/motorcycle-chat", "path": "src/routes/api.motorcycle-chat.ts", "jsName": "MotorcycleChatAPI"}
36
15
  ],
37
16
  "integrations": [],
38
17
  "dependsOn": [],
39
- "variables": []
18
+ "variables": [],
19
+ "packageFileDescriptions": {
20
+ "src/routes/index.tsx": "Motorcycle catalog home with MotorcycleAIAssistant.",
21
+ "src/routes/motorcycles/$motorcycleId.tsx": "Motorcycle detail page with BuyButton, recommendation.",
22
+ "src/routes/checkout/success.tsx": "Stripe checkout success page.",
23
+ "src/routes/checkout/cancel.tsx": "Stripe checkout cancel page.",
24
+ "src/routes/api.motorcycle-chat.ts": "POST handler for motorcycle AI chat with getMotorcycles, recommendMotorcycle tools.",
25
+ "src/routes/__root.tsx": "Root layout: Header, styles.",
26
+ "src/styles.css": "Global styles: Tailwind, prose.",
27
+ "src/data/motorcycles.ts": "Motorcycle catalog data.",
28
+ "src/lib/motorcycle-tools.ts": "AI tools: getMotorcycles, recommendMotorcycle.",
29
+ "src/lib/motorcycle-ai-hook.ts": "useMotorcycleChat hook for /api/motorcycle-chat.",
30
+ "src/lib/stripe.server.ts": "Stripe server utilities for checkout.",
31
+ "src/store/motorcycle-assistant.ts": "Zustand store for assistant open state.",
32
+ "src/components/Header.tsx": "Header with nav.",
33
+ "src/components/MotorcycleAIAssistant.tsx": "AI shopping assistant component.",
34
+ "src/components/MotorcycleRecommendation.tsx": "Motorcycle recommendation card display.",
35
+ "src/components/BuyButton.tsx": "Stripe checkout button component."
36
+ }
40
37
  }
@@ -0,0 +1,21 @@
1
+ ### Conference Site Integration
2
+
3
+ Pastry conference website with Content Collections (speakers, talks) and Remy AI assistant.
4
+
5
+ **Content Collections:**
6
+ - `speakers` - name, title, specialty, restaurant, headshot, awards
7
+ - `talks` - title, speaker, duration, topics, image
8
+ - Schemas in `content-collections.ts`
9
+
10
+ **AI tools available (RemyAssistant):**
11
+ - `getSpeakerBySlug` - Get speaker profile by slug
12
+ - `getTalkBySlug` - Get talk details by slug
13
+ - `getAllSpeakers` - List all speakers
14
+ - `getAllTalks` - List all talks
15
+ - `getSchedule` - Get full schedule
16
+
17
+ **Components:** HeroCarousel (background images), RemyAssistant (conference Q&A)
18
+
19
+ ## Environment Variables
20
+
21
+ For AI: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, or OLLAMA_BASE_URL (same as ai add-on).