kaddidlehopper 0.5.0 → 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/dist/cli.js +104 -208
- package/dist/index.js +1 -31
- package/dist/types/cli.d.ts +1 -8
- package/dist/types/types.d.ts +7 -12
- package/package.json +1 -2
- package/src/cli.ts +129 -271
- package/src/index.ts +1 -47
- package/src/types.ts +7 -13
- package/CONTEXT.md +0 -139
- package/add-ons/ai/README.md +0 -34
- package/add-ons/ai/assets/AGENTS.md.append +0 -24
- package/add-ons/ai/assets/_dot_env.local.append +0 -13
- package/add-ons/ai/assets/src/components/AIAssistant.tsx +0 -149
- package/add-ons/ai/assets/src/lib/ai-hook.ts +0 -21
- package/add-ons/ai/assets/src/lib/weather-tools.ts +0 -30
- package/add-ons/ai/assets/src/routes/api.chat.ts +0 -94
- package/add-ons/ai/assets/src/routes/chat.css +0 -175
- package/add-ons/ai/assets/src/routes/chat.tsx +0 -141
- package/add-ons/ai/info.json +0 -22
- package/add-ons/ai/package.json +0 -17
- package/add-ons/ai/small-logo.svg +0 -8
- package/add-ons/db/assets/AGENTS.md.append +0 -22
- package/add-ons/db/assets/DB-SETUP.md +0 -65
- package/add-ons/db/assets/_dot_env.local.append +0 -2
- package/add-ons/db/assets/drizzle.config.ts +0 -10
- package/add-ons/db/assets/src/db/index.ts +0 -8
- package/add-ons/db/assets/src/db/schema.ts +0 -8
- package/add-ons/db/assets/src/routes/db-example.tsx +0 -118
- package/add-ons/db/assets/src/server/guestbook.functions.ts +0 -23
- package/add-ons/db/info.json +0 -22
- package/add-ons/db/package.json +0 -10
- package/add-ons/forms/assets/AGENTS.md.append +0 -13
- package/add-ons/forms/assets/public/form-example.html +0 -14
- package/add-ons/forms/assets/src/routes/form-example.tsx +0 -76
- package/add-ons/forms/info.json +0 -18
- package/add-ons/forms/package.json +0 -3
- package/examples/ai-chat/README.md +0 -36
- package/examples/ai-chat/assets/AGENTS.md.append +0 -24
- package/examples/ai-chat/assets/src/lib/ai-hook.ts +0 -21
- package/examples/ai-chat/assets/src/lib/weather-tools.ts +0 -30
- package/examples/ai-chat/assets/src/routes/__root.tsx +0 -57
- package/examples/ai-chat/assets/src/routes/api.chat.ts +0 -94
- package/examples/ai-chat/assets/src/routes/index.tsx +0 -141
- package/examples/ai-chat/assets/src/styles.css +0 -165
- package/examples/ai-chat/info.json +0 -25
- package/examples/ai-chat/package.json +0 -14
- package/examples/blog/README.md +0 -60
- package/examples/blog/assets/AGENTS.md.append +0 -18
- package/examples/blog/assets/content/posts/beach.md +0 -12
- package/examples/blog/assets/content/posts/jungle.md.ejs +0 -12
- package/examples/blog/assets/content/posts/mountains.md.ejs +0 -12
- package/examples/blog/assets/content/posts/snorkeling.md.ejs +0 -12
- package/examples/blog/assets/content/posts/waterfall.md.ejs +0 -12
- package/examples/blog/assets/content-collections.ts +0 -30
- package/examples/blog/assets/public/beach.jpg +0 -0
- package/examples/blog/assets/public/jungle.jpg +0 -0
- package/examples/blog/assets/public/mountains.jpg +0 -0
- package/examples/blog/assets/public/snorkeling.jpg +0 -0
- package/examples/blog/assets/public/waterfall.jpg +0 -0
- package/examples/blog/assets/src/components/Header.tsx +0 -52
- package/examples/blog/assets/src/components/VacayAssistant.tsx +0 -205
- package/examples/blog/assets/src/components/blog-posts.tsx +0 -78
- package/examples/blog/assets/src/components/ui/card.tsx +0 -92
- package/examples/blog/assets/src/lib/blog-ai-hook.ts +0 -25
- package/examples/blog/assets/src/lib/blog-tools.ts +0 -111
- package/examples/blog/assets/src/lib/utils.ts +0 -6
- package/examples/blog/assets/src/routes/__root.tsx +0 -57
- package/examples/blog/assets/src/routes/api.blog-chat.ts +0 -117
- package/examples/blog/assets/src/routes/category.$category.tsx +0 -19
- package/examples/blog/assets/src/routes/index.tsx +0 -19
- package/examples/blog/assets/src/routes/posts.$slug.tsx +0 -63
- package/examples/blog/assets/src/styles.css +0 -138
- package/examples/blog/info.json +0 -40
- package/examples/blog/package.json +0 -23
- package/examples/calculator/README.md +0 -16
- package/examples/calculator/assets/AGENTS.md.append +0 -9
- package/examples/calculator/assets/src/components/Calculator.tsx +0 -238
- package/examples/calculator/assets/src/components/Header.tsx +0 -17
- package/examples/calculator/assets/src/routes/__root.tsx +0 -57
- package/examples/calculator/assets/src/routes/index.tsx +0 -14
- package/examples/calculator/info.json +0 -20
- package/examples/calculator/package.json +0 -1
- package/examples/dashboard/README.md +0 -17
- package/examples/dashboard/assets/AGENTS.md.append +0 -12
- package/examples/dashboard/assets/src/components/Header.tsx +0 -17
- package/examples/dashboard/assets/src/routes/__root.tsx +0 -57
- package/examples/dashboard/assets/src/routes/index.tsx +0 -158
- package/examples/dashboard/info.json +0 -19
- package/examples/dashboard/package.json +0 -6
- package/examples/ecommerce/README.md +0 -48
- package/examples/ecommerce/assets/AGENTS.md.append +0 -22
- package/examples/ecommerce/assets/public/logo.png +0 -0
- package/examples/ecommerce/assets/public/motorcycle-scooter.jpg +0 -0
- package/examples/ecommerce/assets/src/components/BuyButton.tsx +0 -35
- package/examples/ecommerce/assets/src/components/Header.tsx +0 -36
- package/examples/ecommerce/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
- package/examples/ecommerce/assets/src/components/MotorcycleRecommendation.tsx +0 -53
- package/examples/ecommerce/assets/src/data/motorcycles.ts +0 -27
- package/examples/ecommerce/assets/src/lib/motorcycle-ai-hook.ts +0 -24
- package/examples/ecommerce/assets/src/lib/motorcycle-tools.ts +0 -42
- package/examples/ecommerce/assets/src/lib/stripe.server.ts +0 -39
- package/examples/ecommerce/assets/src/routes/__root.tsx +0 -57
- package/examples/ecommerce/assets/src/routes/api.motorcycle-chat.ts +0 -78
- package/examples/ecommerce/assets/src/routes/checkout/cancel.tsx +0 -25
- package/examples/ecommerce/assets/src/routes/checkout/success.tsx +0 -25
- package/examples/ecommerce/assets/src/routes/index.tsx +0 -76
- package/examples/ecommerce/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -55
- package/examples/ecommerce/assets/src/store/motorcycle-assistant.ts +0 -3
- package/examples/ecommerce/assets/src/styles.css +0 -212
- package/examples/ecommerce/info.json +0 -38
- package/examples/ecommerce/package.json +0 -13
- package/examples/events/README.md +0 -110
- package/examples/events/assets/AGENTS.md.append +0 -21
- package/examples/events/assets/content/speakers/andre-costa.md +0 -22
- package/examples/events/assets/content/speakers/hans-mueller.md.ejs +0 -22
- package/examples/events/assets/content/speakers/isabella-martinez.md.ejs +0 -22
- package/examples/events/assets/content/speakers/kenji-nakamura.md.ejs +0 -22
- package/examples/events/assets/content/speakers/marie-dubois.md.ejs +0 -20
- package/examples/events/assets/content/speakers/priya-sharma.md.ejs +0 -22
- package/examples/events/assets/content/talks/croissant-lamination-secrets.md +0 -39
- package/examples/events/assets/content/talks/french-macaron-mastery.md.ejs +0 -39
- package/examples/events/assets/content/talks/neapolitan-pizza-tradition-meets-innovation.md.ejs +0 -39
- package/examples/events/assets/content/talks/savory-breads-of-the-mediterranean.md.ejs +0 -39
- package/examples/events/assets/content/talks/sourdough-from-starter-to-masterpiece.md.ejs +0 -36
- package/examples/events/assets/content/talks/the-art-of-the-perfect-tart.md.ejs +0 -32
- package/examples/events/assets/content/talks/the-science-of-sugar.md.ejs +0 -39
- package/examples/events/assets/content/talks/umami-in-pastry-east-meets-west.md.ejs +0 -39
- package/examples/events/assets/content-collections.ts +0 -56
- package/examples/events/assets/public/background-1.jpg +0 -0
- package/examples/events/assets/public/background-2.jpg +0 -0
- package/examples/events/assets/public/background-3.jpg +0 -0
- package/examples/events/assets/public/background-4.jpg +0 -0
- package/examples/events/assets/public/conference-logo.png +0 -0
- package/examples/events/assets/public/favicon.ico +0 -0
- package/examples/events/assets/public/speakers/andre-costa.jpg +0 -0
- package/examples/events/assets/public/speakers/hans-mueller.jpg +0 -0
- package/examples/events/assets/public/speakers/isabella-martinez.jpg +0 -0
- package/examples/events/assets/public/speakers/kenji-nakamura.jpg +0 -0
- package/examples/events/assets/public/speakers/marie-dubois.jpg +0 -0
- package/examples/events/assets/public/speakers/priya-sharma.jpg +0 -0
- package/examples/events/assets/public/talks/croissant-lamination-secrets.jpg +0 -0
- package/examples/events/assets/public/talks/french-macaron-mastery.jpg +0 -0
- package/examples/events/assets/public/talks/neapolitan-pizza-tradition-meets-innovation.jpg +0 -0
- package/examples/events/assets/public/talks/savory-breads-of-the-mediterranean.jpg +0 -0
- package/examples/events/assets/public/talks/sourdough-from-starter-to-masterpiece.jpg +0 -0
- package/examples/events/assets/public/talks/the-art-of-the-perfect-tart.jpg +0 -0
- package/examples/events/assets/public/talks/the-science-of-sugar.jpg +0 -0
- package/examples/events/assets/public/talks/umami-in-pastry-east-meets-west.jpg +0 -0
- package/examples/events/assets/public/tanstack-circle-logo.png +0 -0
- package/examples/events/assets/public/tanstack-word-logo-white.svg +0 -1
- package/examples/events/assets/src/components/Header.tsx +0 -59
- package/examples/events/assets/src/components/HeaderNav.tsx +0 -67
- package/examples/events/assets/src/components/HeroCarousel.tsx +0 -61
- package/examples/events/assets/src/components/RemyAssistant.tsx +0 -207
- package/examples/events/assets/src/components/SpeakerCard.tsx +0 -67
- package/examples/events/assets/src/components/TalkCard.tsx +0 -77
- package/examples/events/assets/src/components/ui/card.tsx +0 -92
- package/examples/events/assets/src/lib/conference-ai-hook.ts +0 -26
- package/examples/events/assets/src/lib/conference-tools.ts +0 -210
- package/examples/events/assets/src/lib/model-selection.ts +0 -1
- package/examples/events/assets/src/lib/utils.ts +0 -6
- package/examples/events/assets/src/routes/__root.tsx +0 -70
- package/examples/events/assets/src/routes/api.remy-chat.ts +0 -119
- package/examples/events/assets/src/routes/index.tsx +0 -192
- package/examples/events/assets/src/routes/schedule.index.tsx +0 -274
- package/examples/events/assets/src/routes/speakers.$slug.tsx +0 -122
- package/examples/events/assets/src/routes/speakers.index.tsx +0 -40
- package/examples/events/assets/src/routes/talks.$slug.tsx +0 -116
- package/examples/events/assets/src/routes/talks.index.tsx +0 -40
- package/examples/events/assets/src/styles.css +0 -182
- package/examples/events/info.json +0 -61
- package/examples/events/package.json +0 -23
- package/examples/marketing/README.md +0 -60
- package/examples/marketing/assets/AGENTS.md.append +0 -15
- package/examples/marketing/assets/public/logo.png +0 -0
- package/examples/marketing/assets/public/motorcycle-adventure.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-cruiser.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-scooter.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-sport.jpg +0 -0
- package/examples/marketing/assets/public/motorcycle-supersport.jpg +0 -0
- package/examples/marketing/assets/src/components/Header.tsx +0 -36
- package/examples/marketing/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
- package/examples/marketing/assets/src/components/MotorcycleRecommendation.tsx +0 -53
- package/examples/marketing/assets/src/data/motorcycles.ts.ejs +0 -77
- package/examples/marketing/assets/src/lib/motorcycle-ai-hook.ts +0 -24
- package/examples/marketing/assets/src/lib/motorcycle-tools.ts +0 -42
- package/examples/marketing/assets/src/routes/__root.tsx +0 -57
- package/examples/marketing/assets/src/routes/api.motorcycle-chat.ts +0 -78
- package/examples/marketing/assets/src/routes/index.tsx +0 -72
- package/examples/marketing/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -56
- package/examples/marketing/assets/src/store/motorcycle-assistant.ts +0 -3
- package/examples/marketing/assets/src/styles.css +0 -212
- package/examples/marketing/info.json +0 -33
- package/examples/marketing/package.json +0 -14
- package/examples/portfolio/README.md +0 -49
- package/examples/portfolio/assets/AGENTS.md.append +0 -21
- package/examples/portfolio/assets/content/blog/getting-started-with-tanstack.md +0 -53
- package/examples/portfolio/assets/content/blog/react-19-features.md +0 -78
- package/examples/portfolio/assets/content/blog/tailwind-css-v4-guide.md +0 -60
- package/examples/portfolio/assets/content/education/code-school.md +0 -17
- package/examples/portfolio/assets/content/jobs/initech-junior.md +0 -20
- package/examples/portfolio/assets/content/projects/portfolio-site.md +0 -15
- package/examples/portfolio/assets/content/projects/task-manager.md +0 -15
- package/examples/portfolio/assets/content-collections.ts +0 -65
- package/examples/portfolio/assets/public/contact.html +0 -6
- package/examples/portfolio/assets/public/headshot-on-white.jpg +0 -0
- package/examples/portfolio/assets/src/components/Header.tsx +0 -33
- package/examples/portfolio/assets/src/components/ResumeAssistant.tsx +0 -193
- package/examples/portfolio/assets/src/components/ui/badge.tsx +0 -46
- package/examples/portfolio/assets/src/components/ui/card.tsx +0 -92
- package/examples/portfolio/assets/src/components/ui/checkbox.tsx +0 -30
- package/examples/portfolio/assets/src/components/ui/hover-card.tsx +0 -44
- package/examples/portfolio/assets/src/components/ui/separator.tsx +0 -26
- package/examples/portfolio/assets/src/lib/resume-ai-hook.ts +0 -21
- package/examples/portfolio/assets/src/lib/resume-tools.ts +0 -165
- package/examples/portfolio/assets/src/lib/utils.ts +0 -6
- package/examples/portfolio/assets/src/routes/__root.tsx +0 -57
- package/examples/portfolio/assets/src/routes/api.resume-chat.ts +0 -116
- package/examples/portfolio/assets/src/routes/blog/$slug.tsx +0 -73
- package/examples/portfolio/assets/src/routes/contact.tsx +0 -121
- package/examples/portfolio/assets/src/routes/index.tsx +0 -55
- package/examples/portfolio/assets/src/routes/projects.tsx +0 -62
- package/examples/portfolio/assets/src/routes/resume.tsx +0 -220
- package/examples/portfolio/assets/src/styles.css +0 -138
- package/examples/portfolio/info.json +0 -50
- package/examples/portfolio/package.json +0 -26
- package/examples/resume/README.md +0 -82
- package/examples/resume/assets/AGENTS.md.append +0 -19
- package/examples/resume/assets/content/education/code-school.md +0 -17
- package/examples/resume/assets/content/jobs/freelance.md.ejs +0 -13
- package/examples/resume/assets/content/jobs/initech-junior.md +0 -20
- package/examples/resume/assets/content/jobs/initech-lead.md.ejs +0 -29
- package/examples/resume/assets/content/jobs/initrode-senior.md.ejs +0 -28
- package/examples/resume/assets/content-collections.ts +0 -36
- package/examples/resume/assets/public/headshot-on-white.jpg +0 -0
- package/examples/resume/assets/src/components/Header.tsx +0 -33
- package/examples/resume/assets/src/components/ResumeAssistant.tsx +0 -193
- package/examples/resume/assets/src/components/ui/badge.tsx +0 -46
- package/examples/resume/assets/src/components/ui/card.tsx +0 -92
- package/examples/resume/assets/src/components/ui/checkbox.tsx +0 -30
- package/examples/resume/assets/src/components/ui/hover-card.tsx +0 -44
- package/examples/resume/assets/src/components/ui/separator.tsx +0 -26
- package/examples/resume/assets/src/lib/resume-ai-hook.ts +0 -21
- package/examples/resume/assets/src/lib/resume-tools.ts +0 -165
- package/examples/resume/assets/src/lib/utils.ts +0 -6
- package/examples/resume/assets/src/routes/api.resume-chat.ts +0 -110
- package/examples/resume/assets/src/routes/index.tsx +0 -220
- package/examples/resume/assets/src/styles.css +0 -138
- package/examples/resume/info.json +0 -35
- package/examples/resume/package.json +0 -26
- package/examples/saas/README.md +0 -16
- package/examples/saas/assets/AGENTS.md.append +0 -9
- package/examples/saas/assets/src/components/Header.tsx +0 -17
- package/examples/saas/assets/src/routes/__root.tsx +0 -57
- package/examples/saas/assets/src/routes/faq.tsx +0 -94
- package/examples/saas/assets/src/routes/index.tsx +0 -197
- package/examples/saas/info.json +0 -23
- package/examples/saas/package.json +0 -1
- package/examples/survey/README.md +0 -20
- package/examples/survey/assets/AGENTS.md.append +0 -9
- package/examples/survey/assets/public/form-survey.html +0 -15
- package/examples/survey/assets/src/components/SurveyForm.tsx +0 -128
- package/examples/survey/assets/src/routes/index.tsx +0 -14
- package/examples/survey/info.json +0 -19
- package/examples/survey/package.json +0 -1
- package/project/base/AGENTS.md +0 -86
- package/project/base/_dot_claude/skills/content-collections/SKILL.md +0 -505
- package/project/base/_dot_claude/skills/netlify-blobs/SKILL.md +0 -410
- package/project/base/_dot_claude/skills/netlify-db/SKILL.md +0 -424
- package/project/base/_dot_claude/skills/netlify-debugging/SKILL.md +0 -419
- package/project/base/_dot_claude/skills/netlify-forms/SKILL.md +0 -243
- package/project/base/_dot_claude/skills/netlify-functions/SKILL.md +0 -372
- package/project/base/_dot_claude/skills/tanstack-start-api-routes/SKILL.md +0 -421
- package/project/base/_dot_claude/skills/tanstack-start-loaders/SKILL.md +0 -426
- package/project/base/_dot_claude/skills/tanstack-start-project-setup/SKILL.md +0 -493
- package/project/base/_dot_claude/skills/tanstack-start-routes/SKILL.md +0 -430
- package/project/base/_dot_claude/skills/tanstack-start-server-functions/SKILL.md +0 -445
- package/project/base/_dot_claude/skills/tanstack-start-typesafe-routing/SKILL.md +0 -494
- package/project/base/_dot_gitignore +0 -8
- package/project/base/netlify.toml +0 -7
- package/project/base/package.json +0 -33
- package/project/base/public/favicon.ico +0 -0
- package/project/base/public/tanstack-circle-logo.png +0 -0
- package/project/base/public/tanstack-word-logo-white.svg +0 -1
- package/project/base/src/components/Header.tsx +0 -17
- package/project/base/src/components/HeaderNav.tsx.ejs +0 -179
- package/project/base/src/router.tsx +0 -15
- package/project/base/src/routes/__root.tsx +0 -57
- package/project/base/src/routes/index.tsx +0 -48
- package/project/base/src/styles.css +0 -15
- package/project/base/tsconfig.json +0 -28
- package/project/base/vite.config.ts.ejs +0 -25
- package/project/info.json +0 -17
- package/project/packages.json +0 -22
- package/scripts/check-outdated-packages.js +0 -421
- package/src/agents-md.ts +0 -139
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export interface Motorcycle {
|
|
2
|
-
id: number;
|
|
3
|
-
name: string;
|
|
4
|
-
image: string;
|
|
5
|
-
description: string;
|
|
6
|
-
shortDescription: string;
|
|
7
|
-
price: number;
|
|
8
|
-
engineSize: number; // in CCs
|
|
9
|
-
type: "scooter" | "cruiser" | "adventure" | "sport" | "supersport";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const motorcycles: Array<Motorcycle> = [
|
|
13
|
-
{
|
|
14
|
-
id: 1,
|
|
15
|
-
name: "Luna-C Urbanite",
|
|
16
|
-
image: "/motorcycle-scooter.jpg",
|
|
17
|
-
description:
|
|
18
|
-
"The Luna-C Urbanite is the perfect city companion, combining style and practicality in a compact package. With its 125cc engine, it delivers excellent fuel efficiency while maintaining enough power for urban commuting. The comfortable seating position and lightweight frame make it easy to maneuver through city traffic, while the under-seat storage provides ample space for your daily essentials.",
|
|
19
|
-
shortDescription:
|
|
20
|
-
"A stylish and practical 125cc scooter perfect for urban commuting with excellent fuel efficiency.",
|
|
21
|
-
price: 3000,
|
|
22
|
-
engineSize: 125,
|
|
23
|
-
type: "scooter",
|
|
24
|
-
},
|
|
25
|
-
<% if (!addOnOption.project?.bareBones) { %>
|
|
26
|
-
{
|
|
27
|
-
id: 2,
|
|
28
|
-
name: "Luna-C Voyager",
|
|
29
|
-
image: "/motorcycle-cruiser.jpg",
|
|
30
|
-
description:
|
|
31
|
-
"The Luna-C Voyager is a classic cruiser that combines comfort with style. Its 750cc engine provides smooth, reliable power for long-distance rides, while the ergonomic design ensures comfort even on extended journeys. The classic cruiser styling with modern touches makes it stand out on any road.",
|
|
32
|
-
shortDescription:
|
|
33
|
-
"A comfortable 750cc cruiser perfect for long-distance rides with classic styling.",
|
|
34
|
-
price: 12000,
|
|
35
|
-
engineSize: 750,
|
|
36
|
-
type: "cruiser",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: 3,
|
|
40
|
-
name: "Luna-C Explorer",
|
|
41
|
-
image: "/motorcycle-adventure.jpg",
|
|
42
|
-
description:
|
|
43
|
-
"The Luna-C Explorer is built for adventure, whether you're tackling city streets or exploring off-road trails. Its 850cc engine provides the perfect balance of power and control, while the dual-sport suspension system ensures a smooth ride in any condition. The upright riding position and comfortable seat make it ideal for long journeys.",
|
|
44
|
-
shortDescription:
|
|
45
|
-
"An 850cc adventure bike designed for both on-road and off-road exploration.",
|
|
46
|
-
price: 15000,
|
|
47
|
-
engineSize: 850,
|
|
48
|
-
type: "adventure",
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: 4,
|
|
52
|
-
name: "Luna-C Velocity",
|
|
53
|
-
image: "/motorcycle-sport.jpg",
|
|
54
|
-
description:
|
|
55
|
-
"The Luna-C Velocity is a high-performance sport bike that delivers thrilling acceleration and precise handling. Its 1000cc engine provides exceptional power, while the aerodynamic design and advanced suspension system ensure optimal performance on the track or the open road. The aggressive styling and premium components make it a true performance machine.",
|
|
56
|
-
shortDescription:
|
|
57
|
-
"A high-performance 1000cc sport bike with exceptional power and handling.",
|
|
58
|
-
price: 20000,
|
|
59
|
-
engineSize: 1000,
|
|
60
|
-
type: "sport",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: 5,
|
|
64
|
-
name: "Luna-C Supersport",
|
|
65
|
-
image: "/motorcycle-supersport.jpg",
|
|
66
|
-
description:
|
|
67
|
-
"The Luna-C Supersport represents the pinnacle of motorcycle engineering. Its 1300cc engine delivers breathtaking power and acceleration, while the cutting-edge aerodynamics and race-inspired components ensure maximum performance. This machine is designed for experienced riders who demand the ultimate in speed and handling.",
|
|
68
|
-
shortDescription:
|
|
69
|
-
"The ultimate 1300cc supersport machine with race-inspired performance and aerodynamics.",
|
|
70
|
-
price: 25000,
|
|
71
|
-
engineSize: 1300,
|
|
72
|
-
type: "supersport",
|
|
73
|
-
},
|
|
74
|
-
<% } %>
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
export default motorcycles;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
fetchServerSentEvents,
|
|
3
|
-
useChat,
|
|
4
|
-
createChatClientOptions,
|
|
5
|
-
} from "@tanstack/ai-react";
|
|
6
|
-
import type { InferChatMessages } from "@tanstack/ai-react";
|
|
7
|
-
import { clientTools } from "@tanstack/ai-client";
|
|
8
|
-
|
|
9
|
-
import { recommendMotorcycleToolDef } from "@/lib/motorcycle-tools";
|
|
10
|
-
|
|
11
|
-
const recommendMotorcycleToolClient = recommendMotorcycleToolDef.client(
|
|
12
|
-
({ id }) => ({
|
|
13
|
-
id: +id,
|
|
14
|
-
})
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
const chatOptions = createChatClientOptions({
|
|
18
|
-
connection: fetchServerSentEvents("/api/motorcycle-chat"),
|
|
19
|
-
tools: clientTools(recommendMotorcycleToolClient),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
export type ChatMessages = InferChatMessages<typeof chatOptions>;
|
|
23
|
-
|
|
24
|
-
export const useMotorcycleChat = () => useChat(chatOptions);
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { toolDefinition } from "@tanstack/ai";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import motorcycles from "@/data/motorcycles";
|
|
4
|
-
|
|
5
|
-
// Tool definition for getting motorcycles
|
|
6
|
-
export const getMotorcyclesToolDef = toolDefinition({
|
|
7
|
-
name: "getMotorcycles",
|
|
8
|
-
description: "Get all motorcycles from the database",
|
|
9
|
-
inputSchema: z.object({}),
|
|
10
|
-
outputSchema: z.array(
|
|
11
|
-
z.object({
|
|
12
|
-
id: z.number(),
|
|
13
|
-
name: z.string(),
|
|
14
|
-
image: z.string(),
|
|
15
|
-
description: z.string(),
|
|
16
|
-
shortDescription: z.string(),
|
|
17
|
-
price: z.number(),
|
|
18
|
-
engineSize: z.number(),
|
|
19
|
-
type: z.enum(["scooter", "cruiser", "adventure", "sport", "supersport"]),
|
|
20
|
-
})
|
|
21
|
-
),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Server implementation
|
|
25
|
-
export const getMotorcycles = getMotorcyclesToolDef.server(() => motorcycles);
|
|
26
|
-
|
|
27
|
-
// Tool definition for motorcycle recommendation
|
|
28
|
-
export const recommendMotorcycleToolDef = toolDefinition({
|
|
29
|
-
name: "recommendMotorcycle",
|
|
30
|
-
description:
|
|
31
|
-
"REQUIRED tool to display a motorcycle recommendation to the user. This tool MUST be used whenever recommending a motorcycle - do NOT write recommendations yourself. This displays the motorcycle in a special appealing format with a view details button.",
|
|
32
|
-
inputSchema: z.object({
|
|
33
|
-
id: z
|
|
34
|
-
.union([z.string(), z.number()])
|
|
35
|
-
.describe(
|
|
36
|
-
"The ID of the motorcycle to recommend (from the getMotorcycles results)"
|
|
37
|
-
),
|
|
38
|
-
}),
|
|
39
|
-
outputSchema: z.object({
|
|
40
|
-
id: z.number(),
|
|
41
|
-
}),
|
|
42
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
|
|
2
|
-
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
|
|
3
|
-
import { TanStackDevtools } from '@tanstack/react-devtools'
|
|
4
|
-
|
|
5
|
-
import Header from '@/components/Header'
|
|
6
|
-
|
|
7
|
-
import appCss from '@/styles.css?url'
|
|
8
|
-
|
|
9
|
-
export const Route = createRootRoute({
|
|
10
|
-
head: () => ({
|
|
11
|
-
meta: [
|
|
12
|
-
{
|
|
13
|
-
charSet: 'utf-8',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
name: 'viewport',
|
|
17
|
-
content: 'width=device-width, initial-scale=1',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
title: 'Luna-C Motorcycles',
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
links: [
|
|
24
|
-
{
|
|
25
|
-
rel: 'stylesheet',
|
|
26
|
-
href: appCss,
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
}),
|
|
30
|
-
shellComponent: RootDocument,
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
function RootDocument({ children }: { children: React.ReactNode }) {
|
|
34
|
-
return (
|
|
35
|
-
<html lang="en">
|
|
36
|
-
<head>
|
|
37
|
-
<HeadContent />
|
|
38
|
-
</head>
|
|
39
|
-
<body className="bg-black">
|
|
40
|
-
<Header />
|
|
41
|
-
{children}
|
|
42
|
-
<TanStackDevtools
|
|
43
|
-
config={{
|
|
44
|
-
position: 'bottom-right',
|
|
45
|
-
}}
|
|
46
|
-
plugins={[
|
|
47
|
-
{
|
|
48
|
-
name: 'Tanstack Router',
|
|
49
|
-
render: <TanStackRouterDevtoolsPanel />,
|
|
50
|
-
},
|
|
51
|
-
]}
|
|
52
|
-
/>
|
|
53
|
-
<Scripts />
|
|
54
|
-
</body>
|
|
55
|
-
</html>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
import { chat, maxIterations, toServerSentEventsResponse } from "@tanstack/ai";
|
|
3
|
-
import { anthropicText } from "@tanstack/ai-anthropic";
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
getMotorcycles,
|
|
7
|
-
recommendMotorcycleToolDef,
|
|
8
|
-
} from "@/lib/motorcycle-tools";
|
|
9
|
-
|
|
10
|
-
const SYSTEM_PROMPT = `You are a helpful assistant for a store that sells motorcycles.
|
|
11
|
-
|
|
12
|
-
You are also a motorcycle enthusiast who is passionate about our products and how they can bring joy to people's lives, the excitement of the open road and adventure. Emphasize these aspects in your responses.
|
|
13
|
-
|
|
14
|
-
CRITICAL INSTRUCTIONS - YOU MUST FOLLOW THIS EXACT WORKFLOW:
|
|
15
|
-
|
|
16
|
-
When a user asks for a motorcycle recommendation:
|
|
17
|
-
1. FIRST: Use the getMotorcycles tool (no parameters needed)
|
|
18
|
-
2. SECOND: Use the recommendMotorcycle tool with the ID of the motorcycle you want to recommend
|
|
19
|
-
3. NEVER write a recommendation directly - ALWAYS use the recommendMotorcycle tool
|
|
20
|
-
|
|
21
|
-
IMPORTANT:
|
|
22
|
-
- The recommendMotorcycle tool will display the motorcycle in a special, appealing format
|
|
23
|
-
- You MUST use recommendMotorcycle for ANY motorcycle recommendation
|
|
24
|
-
- ONLY recommend motorcycles from our inventory (use getMotorcycles first)
|
|
25
|
-
- The recommendMotorcycle tool has a view details button - this is how customers can learn more
|
|
26
|
-
- Do NOT describe the motorcycle yourself - let the recommendMotorcycle tool do it
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
|
-
export const Route = createFileRoute("/api/motorcycle-chat")({
|
|
30
|
-
server: {
|
|
31
|
-
handlers: {
|
|
32
|
-
POST: async ({ request }) => {
|
|
33
|
-
// Capture request signal before reading body (it may be aborted after body is consumed)
|
|
34
|
-
const requestSignal = request.signal;
|
|
35
|
-
|
|
36
|
-
// If request is already aborted, return early
|
|
37
|
-
if (requestSignal.aborted) {
|
|
38
|
-
return new Response(null, { status: 499 }); // 499 = Client Closed Request
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const abortController = new AbortController();
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const body = await request.json();
|
|
45
|
-
const { messages } = body;
|
|
46
|
-
|
|
47
|
-
const adapter = anthropicText("claude-haiku-4-5");
|
|
48
|
-
|
|
49
|
-
const stream = chat({
|
|
50
|
-
adapter,
|
|
51
|
-
tools: [
|
|
52
|
-
getMotorcycles, // Server tool
|
|
53
|
-
recommendMotorcycleToolDef, // No server execute - client will handle
|
|
54
|
-
],
|
|
55
|
-
systemPrompts: [SYSTEM_PROMPT],
|
|
56
|
-
agentLoopStrategy: maxIterations(5),
|
|
57
|
-
messages,
|
|
58
|
-
abortController,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
return toServerSentEventsResponse(stream, { abortController });
|
|
62
|
-
} catch (error: any) {
|
|
63
|
-
// If request was aborted, return early (don't send error response)
|
|
64
|
-
if (error.name === "AbortError" || abortController.signal.aborted) {
|
|
65
|
-
return new Response(null, { status: 499 }); // 499 = Client Closed Request
|
|
66
|
-
}
|
|
67
|
-
return new Response(
|
|
68
|
-
JSON.stringify({ error: "Failed to process chat request" }),
|
|
69
|
-
{
|
|
70
|
-
status: 500,
|
|
71
|
-
headers: { "Content-Type": "application/json" },
|
|
72
|
-
}
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
});
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { Link, createFileRoute } from '@tanstack/react-router'
|
|
2
|
-
import motorcycles from '@/data/motorcycles'
|
|
3
|
-
|
|
4
|
-
export const Route = createFileRoute('/')({
|
|
5
|
-
component: MotorcyclesIndex,
|
|
6
|
-
})
|
|
7
|
-
|
|
8
|
-
function MotorcyclesIndex() {
|
|
9
|
-
return (
|
|
10
|
-
<div className="bg-black text-white p-5">
|
|
11
|
-
<h1 className="text-3xl font-bold mb-16 text-center">
|
|
12
|
-
Luna-C Motorcycles
|
|
13
|
-
</h1>
|
|
14
|
-
<div className="max-w-7xl mx-auto">
|
|
15
|
-
{motorcycles.map((motorcycle, index) => (
|
|
16
|
-
<div
|
|
17
|
-
key={motorcycle.id}
|
|
18
|
-
className={`relative flex flex-col md:flex-row items-stretch gap-8 mb-32 ${
|
|
19
|
-
index % 2 === 1 ? 'md:flex-row-reverse' : ''
|
|
20
|
-
}`}
|
|
21
|
-
>
|
|
22
|
-
<div className="w-full md:w-[60%] relative">
|
|
23
|
-
<Link
|
|
24
|
-
to="/motorcycles/$motorcycleId"
|
|
25
|
-
params={{
|
|
26
|
-
motorcycleId: motorcycle.id.toString(),
|
|
27
|
-
}}
|
|
28
|
-
className="group block relative"
|
|
29
|
-
>
|
|
30
|
-
<div className="relative z-0 w-full aspect-[4/3]">
|
|
31
|
-
<div className="w-full h-full overflow-hidden rounded-2xl border border-gray-800/50 shadow-2xl">
|
|
32
|
-
<img
|
|
33
|
-
src={motorcycle.image}
|
|
34
|
-
alt={motorcycle.name}
|
|
35
|
-
className="w-full h-full object-cover motorcycle-image group-hover:scale-105 transition-transform duration-500"
|
|
36
|
-
/>
|
|
37
|
-
<div className="absolute inset-0 bg-linear-to-t from-black/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
|
38
|
-
</div>
|
|
39
|
-
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 bg-emerald-500/80 text-white px-4 py-2 rounded-full text-sm font-medium opacity-0 group-hover:opacity-100 transition-opacity duration-300 backdrop-blur-sm">
|
|
40
|
-
View Details
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
</Link>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
<div
|
|
47
|
-
className={`w-full md:w-[50%] relative ${index % 2 === 0 ? 'md:-ml-24' : 'md:-mr-24'} md:my-12`}
|
|
48
|
-
>
|
|
49
|
-
<div className="bg-gray-900/40 backdrop-blur-xl rounded-2xl p-8 border border-gray-500/20 shadow-2xl relative z-10">
|
|
50
|
-
<div className="absolute inset-0 rounded-2xl bg-linear-to-br from-white/5 to-white/0"></div>
|
|
51
|
-
<div className="relative z-10">
|
|
52
|
-
<h2 className="text-2xl font-bold mb-3">{motorcycle.name}</h2>
|
|
53
|
-
<p className="text-gray-300 mb-2 font-medium">
|
|
54
|
-
{motorcycle.engineSize}cc •{' '}
|
|
55
|
-
{motorcycle.type.charAt(0).toUpperCase() +
|
|
56
|
-
motorcycle.type.slice(1)}
|
|
57
|
-
</p>
|
|
58
|
-
<p className="text-gray-100 mb-4 leading-relaxed">
|
|
59
|
-
{motorcycle.shortDescription}
|
|
60
|
-
</p>
|
|
61
|
-
<div className="text-2xl font-bold text-emerald-400">
|
|
62
|
-
${motorcycle.price.toLocaleString()}
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
))}
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
)
|
|
72
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Link, createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
import motorcycles from "../../data/motorcycles";
|
|
3
|
-
|
|
4
|
-
export const Route = createFileRoute("/motorcycles/$motorcycleId")({
|
|
5
|
-
component: RouteComponent,
|
|
6
|
-
loader: async ({ params }) => {
|
|
7
|
-
const motorcycle = motorcycles.find(
|
|
8
|
-
(motorcycle) => motorcycle.id === +params.motorcycleId
|
|
9
|
-
);
|
|
10
|
-
if (!motorcycle) {
|
|
11
|
-
throw new Error("Motorcycle not found");
|
|
12
|
-
}
|
|
13
|
-
return motorcycle;
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
function RouteComponent() {
|
|
18
|
-
const motorcycle = Route.useLoaderData();
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<div className="relative min-h-[100vh] flex items-center bg-black text-white p-5">
|
|
22
|
-
<div className="relative z-10 w-[60%] bg-gray-900/60 backdrop-blur-md rounded-2xl p-8 border border-gray-800/50 shadow-xl">
|
|
23
|
-
<Link
|
|
24
|
-
to="/"
|
|
25
|
-
className="inline-block mb-4 text-emerald-400 hover:text-emerald-300"
|
|
26
|
-
>
|
|
27
|
-
← Back to all motorcycles
|
|
28
|
-
</Link>
|
|
29
|
-
<h1 className="text-3xl font-bold mb-2">{motorcycle.name}</h1>
|
|
30
|
-
<p className="text-gray-400 mb-2">
|
|
31
|
-
{motorcycle.engineSize}cc •{" "}
|
|
32
|
-
{motorcycle.type.charAt(0).toUpperCase() + motorcycle.type.slice(1)}
|
|
33
|
-
</p>
|
|
34
|
-
<p className="text-gray-300 mb-6">{motorcycle.description}</p>
|
|
35
|
-
<div className="flex items-center justify-between">
|
|
36
|
-
<div className="text-2xl font-bold text-emerald-400">
|
|
37
|
-
${motorcycle.price.toLocaleString()}
|
|
38
|
-
</div>
|
|
39
|
-
<button className="bg-emerald-600 hover:bg-emerald-500 text-white px-6 py-2 rounded-lg transition-colors">
|
|
40
|
-
Add to Cart
|
|
41
|
-
</button>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div className="absolute top-0 right-0 w-[55%] h-full z-0">
|
|
46
|
-
<div className="w-full h-full overflow-hidden rounded-2xl border-4 border-gray-800 shadow-2xl">
|
|
47
|
-
<img
|
|
48
|
-
src={motorcycle.image}
|
|
49
|
-
alt={motorcycle.name}
|
|
50
|
-
className="w-full h-full object-cover motorcycle-image"
|
|
51
|
-
/>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "highlight.js/styles/github-dark.css";
|
|
3
|
-
|
|
4
|
-
/* Custom scrollbar styles */
|
|
5
|
-
::-webkit-scrollbar {
|
|
6
|
-
width: 8px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
::-webkit-scrollbar-track {
|
|
10
|
-
background: transparent;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
::-webkit-scrollbar-thumb {
|
|
14
|
-
background-color: rgba(156, 163, 175, 0.5);
|
|
15
|
-
border-radius: 4px;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
::-webkit-scrollbar-thumb:hover {
|
|
19
|
-
background-color: rgba(156, 163, 175, 0.7);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/* Smooth transitions for dark mode */
|
|
23
|
-
html {
|
|
24
|
-
transition: background-color 0.3s ease;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/* Markdown content styles */
|
|
28
|
-
.prose {
|
|
29
|
-
max-width: none;
|
|
30
|
-
color: #e5e7eb; /* text-gray-200 */
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.prose code {
|
|
34
|
-
color: #e5e7eb;
|
|
35
|
-
background-color: rgba(31, 41, 55, 0.5);
|
|
36
|
-
padding: 0.2em 0.4em;
|
|
37
|
-
border-radius: 0.375rem;
|
|
38
|
-
font-size: 0.875em;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.prose pre {
|
|
42
|
-
background-color: rgba(31, 41, 55, 0.5);
|
|
43
|
-
border-radius: 0.5rem;
|
|
44
|
-
padding: 1rem;
|
|
45
|
-
margin: 1.25em 0;
|
|
46
|
-
overflow-x: auto;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.prose pre code {
|
|
50
|
-
background-color: transparent;
|
|
51
|
-
padding: 0;
|
|
52
|
-
border-radius: 0;
|
|
53
|
-
color: inherit;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.prose h1, .prose h2, .prose h3, .prose h4 {
|
|
57
|
-
color: #f9fafb; /* text-gray-50 */
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.prose ul, .prose ol {
|
|
61
|
-
margin-top: 1.25em;
|
|
62
|
-
margin-bottom: 1.25em;
|
|
63
|
-
padding-left: 1.625em;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.prose li {
|
|
67
|
-
margin-top: 0.5em;
|
|
68
|
-
margin-bottom: 0.5em;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.prose blockquote {
|
|
72
|
-
border-left-color: #f97316; /* orange-500 */
|
|
73
|
-
background-color: rgba(249, 115, 22, 0.1);
|
|
74
|
-
padding: 1em;
|
|
75
|
-
margin: 1.25em 0;
|
|
76
|
-
border-radius: 0.5rem;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.prose hr {
|
|
80
|
-
border-color: rgba(249, 115, 22, 0.2);
|
|
81
|
-
margin: 2em 0;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.prose a {
|
|
85
|
-
color: #f97316; /* orange-500 */
|
|
86
|
-
text-decoration: underline;
|
|
87
|
-
text-decoration-thickness: 0.1em;
|
|
88
|
-
text-underline-offset: 0.2em;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.prose a:hover {
|
|
92
|
-
color: #fb923c; /* orange-400 */
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.prose table {
|
|
96
|
-
width: 100%;
|
|
97
|
-
border-collapse: collapse;
|
|
98
|
-
margin: 1.25em 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.prose th, .prose td {
|
|
102
|
-
padding: 0.75em;
|
|
103
|
-
border: 1px solid rgba(249, 115, 22, 0.2);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.prose th {
|
|
107
|
-
background-color: rgba(249, 115, 22, 0.1);
|
|
108
|
-
font-weight: 600;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/* Message transition animations */
|
|
112
|
-
.message-enter {
|
|
113
|
-
opacity: 0;
|
|
114
|
-
transform: translateY(10px);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.message-enter-active {
|
|
118
|
-
opacity: 1;
|
|
119
|
-
transform: translateY(0);
|
|
120
|
-
transition: opacity 300ms, transform 300ms;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.message-exit {
|
|
124
|
-
opacity: 1;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.message-exit-active {
|
|
128
|
-
opacity: 0;
|
|
129
|
-
transition: opacity 300ms;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* Add/update these styles to match AI formatting capabilities */
|
|
133
|
-
.prose h1 {
|
|
134
|
-
font-size: 2em;
|
|
135
|
-
margin-bottom: 0.5em;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.prose h2 {
|
|
139
|
-
font-size: 1.5em;
|
|
140
|
-
margin-top: 1em;
|
|
141
|
-
margin-bottom: 0.5em;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.prose h3 {
|
|
145
|
-
font-size: 1.25em;
|
|
146
|
-
margin-top: 1em;
|
|
147
|
-
margin-bottom: 0.5em;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.prose ul {
|
|
151
|
-
list-style-type: disc;
|
|
152
|
-
padding-left: 1.5em;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.prose ol {
|
|
156
|
-
list-style-type: decimal;
|
|
157
|
-
padding-left: 1.5em;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.prose table {
|
|
161
|
-
width: 100%;
|
|
162
|
-
border-collapse: collapse;
|
|
163
|
-
margin: 1em 0;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
.prose th,
|
|
167
|
-
.prose td {
|
|
168
|
-
border: 1px solid rgba(249, 115, 22, 0.2);
|
|
169
|
-
padding: 0.5em;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.prose th {
|
|
173
|
-
background-color: rgba(249, 115, 22, 0.1);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.prose strong {
|
|
177
|
-
color: #f9fafb; /* text-gray-50 */
|
|
178
|
-
font-weight: 600;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.prose em {
|
|
182
|
-
font-style: italic;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.prose blockquote {
|
|
186
|
-
border-left: 4px solid #f97316; /* orange-500 */
|
|
187
|
-
padding-left: 1em;
|
|
188
|
-
margin: 1em 0;
|
|
189
|
-
color: #d1d5db; /* text-gray-300 */
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/* Ensure code blocks match the AI's formatting */
|
|
193
|
-
.prose code {
|
|
194
|
-
color: #e5e7eb;
|
|
195
|
-
background-color: rgba(31, 41, 55, 0.5);
|
|
196
|
-
padding: 0.2em 0.4em;
|
|
197
|
-
border-radius: 0.375rem;
|
|
198
|
-
font-size: 0.875em;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.prose pre {
|
|
202
|
-
background-color: rgba(31, 41, 55, 0.5);
|
|
203
|
-
border-radius: 0.5rem;
|
|
204
|
-
padding: 1rem;
|
|
205
|
-
margin: 1em 0;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.prose pre code {
|
|
209
|
-
background-color: transparent;
|
|
210
|
-
padding: 0;
|
|
211
|
-
border-radius: 0;
|
|
212
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Marketing",
|
|
3
|
-
"description": "AI-powered motorcycle marketing site with TanStack AI chat assistant for Netlify.",
|
|
4
|
-
"phase": "example",
|
|
5
|
-
"modes": ["file-router"],
|
|
6
|
-
"type": "example",
|
|
7
|
-
"priority": 10,
|
|
8
|
-
"link": "",
|
|
9
|
-
"routes": [
|
|
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": "/api/motorcycle-chat", "path": "src/routes/api.motorcycle-chat.ts", "jsName": "MotorcycleChatAPI"}
|
|
13
|
-
],
|
|
14
|
-
"features": ["tanstack-start", "tanstack-ai"],
|
|
15
|
-
"integrations": [],
|
|
16
|
-
"dependsOn": [],
|
|
17
|
-
"variables": [],
|
|
18
|
-
"bareBones": {"deleteFiles": ["public/motorcycle-adventure.jpg", "public/motorcycle-cruiser.jpg", "public/motorcycle-sport.jpg", "public/motorcycle-supersport.jpg"]},
|
|
19
|
-
"packageFileDescriptions": {
|
|
20
|
-
"src/routes/index.tsx": "Marketing home: motorcycle showcase, MotorcycleAIAssistant.",
|
|
21
|
-
"src/routes/motorcycles/$motorcycleId.tsx": "Motorcycle detail page with recommendation.",
|
|
22
|
-
"src/routes/api.motorcycle-chat.ts": "POST handler for motorcycle AI chat.",
|
|
23
|
-
"src/routes/__root.tsx": "Root layout: Header, styles.",
|
|
24
|
-
"src/styles.css": "Global styles.",
|
|
25
|
-
"src/data/motorcycles.ts.ejs": "Motorcycle catalog data template.",
|
|
26
|
-
"src/lib/motorcycle-tools.ts": "AI tools: getMotorcycles, recommendMotorcycle.",
|
|
27
|
-
"src/lib/motorcycle-ai-hook.ts": "useMotorcycleChat hook.",
|
|
28
|
-
"src/store/motorcycle-assistant.ts": "Zustand store for assistant state.",
|
|
29
|
-
"src/components/Header.tsx": "Header.",
|
|
30
|
-
"src/components/MotorcycleAIAssistant.tsx": "AI marketing assistant.",
|
|
31
|
-
"src/components/MotorcycleRecommendation.tsx": "Motorcycle recommendation card."
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"dependencies": {
|
|
3
|
-
"@tanstack/ai": "0.2.2",
|
|
4
|
-
"@tanstack/ai-anthropic": "0.2.0",
|
|
5
|
-
"@tanstack/ai-client": "0.2.2",
|
|
6
|
-
"@tanstack/ai-react": "0.2.2",
|
|
7
|
-
"@tanstack/react-ai-devtools": "0.2.1",
|
|
8
|
-
"@tanstack/react-store": "^0.8.0",
|
|
9
|
-
"@tanstack/store": "^0.8.0",
|
|
10
|
-
"highlight.js": "^11.11.1",
|
|
11
|
-
"streamdown": "^2.1.0",
|
|
12
|
-
"zod": "^4.3.6"
|
|
13
|
-
}
|
|
14
|
-
}
|