kaddidlehopper 0.1.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 (183) hide show
  1. package/CONTEXT.md +139 -0
  2. package/README.md +47 -0
  3. package/add-ons/ai/README.md +34 -0
  4. package/add-ons/ai/assets/_dot_env.local.append +13 -0
  5. package/add-ons/ai/assets/src/components/AIAssistant.tsx +149 -0
  6. package/add-ons/ai/assets/src/lib/ai-hook.ts +21 -0
  7. package/add-ons/ai/assets/src/lib/weather-tools.ts +30 -0
  8. package/add-ons/ai/assets/src/routes/api.chat.ts +94 -0
  9. package/add-ons/ai/assets/src/routes/chat.css +175 -0
  10. package/add-ons/ai/assets/src/routes/chat.tsx +141 -0
  11. package/add-ons/ai/info.json +27 -0
  12. package/add-ons/ai/package.json +17 -0
  13. package/add-ons/ai/small-logo.svg +8 -0
  14. package/dist/cli.js +251 -0
  15. package/dist/index.js +33 -0
  16. package/dist/types/cli.d.ts +8 -0
  17. package/dist/types/index.d.ts +2 -0
  18. package/dist/types/types.d.ts +14 -0
  19. package/dist/types.js +1 -0
  20. package/examples/blog/README.md +60 -0
  21. package/examples/blog/assets/content/posts/beach.md +12 -0
  22. package/examples/blog/assets/content/posts/jungle.md.ejs +12 -0
  23. package/examples/blog/assets/content/posts/mountains.md.ejs +12 -0
  24. package/examples/blog/assets/content/posts/snorkeling.md.ejs +12 -0
  25. package/examples/blog/assets/content/posts/waterfall.md.ejs +12 -0
  26. package/examples/blog/assets/content-collections.ts +30 -0
  27. package/examples/blog/assets/public/beach.jpg +0 -0
  28. package/examples/blog/assets/public/jungle.jpg +0 -0
  29. package/examples/blog/assets/public/mountains.jpg +0 -0
  30. package/examples/blog/assets/public/snorkeling.jpg +0 -0
  31. package/examples/blog/assets/public/waterfall.jpg +0 -0
  32. package/examples/blog/assets/src/components/Header.tsx +52 -0
  33. package/examples/blog/assets/src/components/VacayAssistant.tsx +205 -0
  34. package/examples/blog/assets/src/components/blog-posts.tsx +78 -0
  35. package/examples/blog/assets/src/components/ui/card.tsx +92 -0
  36. package/examples/blog/assets/src/lib/blog-ai-hook.ts +25 -0
  37. package/examples/blog/assets/src/lib/blog-tools.ts +111 -0
  38. package/examples/blog/assets/src/lib/utils.ts +6 -0
  39. package/examples/blog/assets/src/routes/__root.tsx +57 -0
  40. package/examples/blog/assets/src/routes/api.blog-chat.ts +117 -0
  41. package/examples/blog/assets/src/routes/category.$category.tsx +19 -0
  42. package/examples/blog/assets/src/routes/index.tsx +19 -0
  43. package/examples/blog/assets/src/routes/posts.$slug.tsx +63 -0
  44. package/examples/blog/assets/src/styles.css +138 -0
  45. package/examples/blog/info.json +43 -0
  46. package/examples/blog/package.json +23 -0
  47. package/examples/events/README.md +110 -0
  48. package/examples/events/assets/content/speakers/andre-costa.md +22 -0
  49. package/examples/events/assets/content/speakers/hans-mueller.md.ejs +22 -0
  50. package/examples/events/assets/content/speakers/isabella-martinez.md.ejs +22 -0
  51. package/examples/events/assets/content/speakers/kenji-nakamura.md.ejs +22 -0
  52. package/examples/events/assets/content/speakers/marie-dubois.md.ejs +20 -0
  53. package/examples/events/assets/content/speakers/priya-sharma.md.ejs +22 -0
  54. package/examples/events/assets/content/talks/croissant-lamination-secrets.md +39 -0
  55. package/examples/events/assets/content/talks/french-macaron-mastery.md.ejs +39 -0
  56. package/examples/events/assets/content/talks/neapolitan-pizza-tradition-meets-innovation.md.ejs +39 -0
  57. package/examples/events/assets/content/talks/savory-breads-of-the-mediterranean.md.ejs +39 -0
  58. package/examples/events/assets/content/talks/sourdough-from-starter-to-masterpiece.md.ejs +36 -0
  59. package/examples/events/assets/content/talks/the-art-of-the-perfect-tart.md.ejs +32 -0
  60. package/examples/events/assets/content/talks/the-science-of-sugar.md.ejs +39 -0
  61. package/examples/events/assets/content/talks/umami-in-pastry-east-meets-west.md.ejs +39 -0
  62. package/examples/events/assets/content-collections.ts +56 -0
  63. package/examples/events/assets/public/background-1.jpg +0 -0
  64. package/examples/events/assets/public/background-2.jpg +0 -0
  65. package/examples/events/assets/public/background-3.jpg +0 -0
  66. package/examples/events/assets/public/background-4.jpg +0 -0
  67. package/examples/events/assets/public/conference-logo.png +0 -0
  68. package/examples/events/assets/public/favicon.ico +0 -0
  69. package/examples/events/assets/public/speakers/andre-costa.jpg +0 -0
  70. package/examples/events/assets/public/speakers/hans-mueller.jpg +0 -0
  71. package/examples/events/assets/public/speakers/isabella-martinez.jpg +0 -0
  72. package/examples/events/assets/public/speakers/kenji-nakamura.jpg +0 -0
  73. package/examples/events/assets/public/speakers/marie-dubois.jpg +0 -0
  74. package/examples/events/assets/public/speakers/priya-sharma.jpg +0 -0
  75. package/examples/events/assets/public/talks/croissant-lamination-secrets.jpg +0 -0
  76. package/examples/events/assets/public/talks/french-macaron-mastery.jpg +0 -0
  77. package/examples/events/assets/public/talks/neapolitan-pizza-tradition-meets-innovation.jpg +0 -0
  78. package/examples/events/assets/public/talks/savory-breads-of-the-mediterranean.jpg +0 -0
  79. package/examples/events/assets/public/talks/sourdough-from-starter-to-masterpiece.jpg +0 -0
  80. package/examples/events/assets/public/talks/the-art-of-the-perfect-tart.jpg +0 -0
  81. package/examples/events/assets/public/talks/the-science-of-sugar.jpg +0 -0
  82. package/examples/events/assets/public/talks/umami-in-pastry-east-meets-west.jpg +0 -0
  83. package/examples/events/assets/public/tanstack-circle-logo.png +0 -0
  84. package/examples/events/assets/public/tanstack-word-logo-white.svg +1 -0
  85. package/examples/events/assets/src/components/Header.tsx +59 -0
  86. package/examples/events/assets/src/components/HeaderNav.tsx +67 -0
  87. package/examples/events/assets/src/components/HeroCarousel.tsx +61 -0
  88. package/examples/events/assets/src/components/RemyAssistant.tsx +207 -0
  89. package/examples/events/assets/src/components/SpeakerCard.tsx +67 -0
  90. package/examples/events/assets/src/components/TalkCard.tsx +77 -0
  91. package/examples/events/assets/src/components/ui/card.tsx +92 -0
  92. package/examples/events/assets/src/lib/conference-ai-hook.ts +26 -0
  93. package/examples/events/assets/src/lib/conference-tools.ts +210 -0
  94. package/examples/events/assets/src/lib/model-selection.ts +1 -0
  95. package/examples/events/assets/src/lib/utils.ts +6 -0
  96. package/examples/events/assets/src/routes/__root.tsx +70 -0
  97. package/examples/events/assets/src/routes/api.remy-chat.ts +119 -0
  98. package/examples/events/assets/src/routes/index.tsx +192 -0
  99. package/examples/events/assets/src/routes/schedule.index.tsx +274 -0
  100. package/examples/events/assets/src/routes/speakers.$slug.tsx +122 -0
  101. package/examples/events/assets/src/routes/speakers.index.tsx +40 -0
  102. package/examples/events/assets/src/routes/talks.$slug.tsx +116 -0
  103. package/examples/events/assets/src/routes/talks.index.tsx +40 -0
  104. package/examples/events/assets/src/styles.css +182 -0
  105. package/examples/events/info.json +74 -0
  106. package/examples/events/package.json +23 -0
  107. package/examples/marketing/README.md +60 -0
  108. package/examples/marketing/assets/public/logo.png +0 -0
  109. package/examples/marketing/assets/public/motorcycle-adventure.jpg +0 -0
  110. package/examples/marketing/assets/public/motorcycle-cruiser.jpg +0 -0
  111. package/examples/marketing/assets/public/motorcycle-scooter.jpg +0 -0
  112. package/examples/marketing/assets/public/motorcycle-sport.jpg +0 -0
  113. package/examples/marketing/assets/public/motorcycle-supersport.jpg +0 -0
  114. package/examples/marketing/assets/src/components/Header.tsx +36 -0
  115. package/examples/marketing/assets/src/components/MotorcycleAIAssistant.tsx +162 -0
  116. package/examples/marketing/assets/src/components/MotorcycleRecommendation.tsx +53 -0
  117. package/examples/marketing/assets/src/data/motorcycles.ts.ejs +77 -0
  118. package/examples/marketing/assets/src/lib/motorcycle-ai-hook.ts +24 -0
  119. package/examples/marketing/assets/src/lib/motorcycle-tools.ts +42 -0
  120. package/examples/marketing/assets/src/routes/__root.tsx +57 -0
  121. package/examples/marketing/assets/src/routes/api.motorcycle-chat.ts +78 -0
  122. package/examples/marketing/assets/src/routes/index.tsx +72 -0
  123. package/examples/marketing/assets/src/routes/motorcycles/$motorcycleId.tsx +56 -0
  124. package/examples/marketing/assets/src/store/motorcycle-assistant.ts +3 -0
  125. package/examples/marketing/assets/src/styles.css +212 -0
  126. package/examples/marketing/info.json +38 -0
  127. package/examples/marketing/package.json +14 -0
  128. package/examples/resume/README.md +82 -0
  129. package/examples/resume/assets/content/education/code-school.md +17 -0
  130. package/examples/resume/assets/content/jobs/freelance.md.ejs +13 -0
  131. package/examples/resume/assets/content/jobs/initech-junior.md +20 -0
  132. package/examples/resume/assets/content/jobs/initech-lead.md.ejs +29 -0
  133. package/examples/resume/assets/content/jobs/initrode-senior.md.ejs +28 -0
  134. package/examples/resume/assets/content-collections.ts +36 -0
  135. package/examples/resume/assets/public/headshot-on-white.jpg +0 -0
  136. package/examples/resume/assets/src/components/Header.tsx +33 -0
  137. package/examples/resume/assets/src/components/ResumeAssistant.tsx +193 -0
  138. package/examples/resume/assets/src/components/ui/badge.tsx +46 -0
  139. package/examples/resume/assets/src/components/ui/card.tsx +92 -0
  140. package/examples/resume/assets/src/components/ui/checkbox.tsx +30 -0
  141. package/examples/resume/assets/src/components/ui/hover-card.tsx +44 -0
  142. package/examples/resume/assets/src/components/ui/separator.tsx +26 -0
  143. package/examples/resume/assets/src/lib/resume-ai-hook.ts +21 -0
  144. package/examples/resume/assets/src/lib/resume-tools.ts +165 -0
  145. package/examples/resume/assets/src/lib/utils.ts +6 -0
  146. package/examples/resume/assets/src/routes/api.resume-chat.ts +110 -0
  147. package/examples/resume/assets/src/routes/index.tsx +220 -0
  148. package/examples/resume/assets/src/styles.css +138 -0
  149. package/examples/resume/info.json +25 -0
  150. package/examples/resume/package.json +26 -0
  151. package/package.json +39 -0
  152. package/project/base/_dot_claude/skills/content-collections/SKILL.md +505 -0
  153. package/project/base/_dot_claude/skills/netlify-blobs/SKILL.md +410 -0
  154. package/project/base/_dot_claude/skills/netlify-db/SKILL.md +424 -0
  155. package/project/base/_dot_claude/skills/netlify-debugging/SKILL.md +419 -0
  156. package/project/base/_dot_claude/skills/netlify-forms/SKILL.md +243 -0
  157. package/project/base/_dot_claude/skills/netlify-functions/SKILL.md +372 -0
  158. package/project/base/_dot_claude/skills/tanstack-start-api-routes/SKILL.md +421 -0
  159. package/project/base/_dot_claude/skills/tanstack-start-loaders/SKILL.md +426 -0
  160. package/project/base/_dot_claude/skills/tanstack-start-project-setup/SKILL.md +493 -0
  161. package/project/base/_dot_claude/skills/tanstack-start-routes/SKILL.md +430 -0
  162. package/project/base/_dot_claude/skills/tanstack-start-server-functions/SKILL.md +445 -0
  163. package/project/base/_dot_claude/skills/tanstack-start-typesafe-routing/SKILL.md +494 -0
  164. package/project/base/_dot_gitignore +8 -0
  165. package/project/base/netlify.toml +7 -0
  166. package/project/base/package.json +33 -0
  167. package/project/base/public/favicon.ico +0 -0
  168. package/project/base/public/tanstack-circle-logo.png +0 -0
  169. package/project/base/public/tanstack-word-logo-white.svg +1 -0
  170. package/project/base/src/components/Header.tsx +17 -0
  171. package/project/base/src/components/HeaderNav.tsx.ejs +179 -0
  172. package/project/base/src/router.tsx +15 -0
  173. package/project/base/src/routes/__root.tsx +57 -0
  174. package/project/base/src/routes/index.tsx +48 -0
  175. package/project/base/src/styles.css +15 -0
  176. package/project/base/tsconfig.json +28 -0
  177. package/project/base/vite.config.ts.ejs +25 -0
  178. package/project/packages.json +22 -0
  179. package/scripts/check-outdated-packages.js +421 -0
  180. package/src/cli.ts +343 -0
  181. package/src/index.ts +49 -0
  182. package/src/types.ts +15 -0
  183. package/tsconfig.json +17 -0
@@ -0,0 +1,116 @@
1
+ import { createFileRoute, Link } from '@tanstack/react-router'
2
+ import { marked } from 'marked'
3
+ import { Clock, User, ArrowLeft, Tag } from 'lucide-react'
4
+
5
+ import { allTalks, allSpeakers } from 'content-collections'
6
+
7
+ import RemyAssistant from '@/components/RemyAssistant'
8
+
9
+ export const Route = createFileRoute('/talks/$slug')({
10
+ loader: async ({ params }) => {
11
+ const talk = allTalks.find((t) => t.slug === params.slug)
12
+ if (!talk) {
13
+ throw new Error('Talk not found')
14
+ }
15
+ const speaker = allSpeakers.find((s) => s.name === talk.speaker)
16
+ return { talk, speaker }
17
+ },
18
+ component: TalkDetailPage,
19
+ })
20
+
21
+ function TalkDetailPage() {
22
+ const { talk, speaker } = Route.useLoaderData()
23
+
24
+ return (
25
+ <div className="min-h-screen">
26
+ <RemyAssistant />
27
+
28
+ {/* Back navigation */}
29
+ <div className="max-w-7xl mx-auto px-6 py-4">
30
+ <Link
31
+ to="/talks"
32
+ className="inline-flex items-center gap-2 text-cream/60 hover:text-gold transition-colors"
33
+ >
34
+ <ArrowLeft className="w-4 h-4" />
35
+ <span>All Sessions</span>
36
+ </Link>
37
+ </div>
38
+
39
+ {/* Hero image */}
40
+ <div className="relative h-[40vh] max-w-7xl mx-auto px-6 mb-8">
41
+ <div className="w-full h-full rounded-2xl overflow-hidden border border-border/50">
42
+ <img
43
+ src={`/${talk.image}`}
44
+ alt={talk.title}
45
+ className="w-full h-full object-cover"
46
+ />
47
+ </div>
48
+ <div className="absolute inset-6 bg-gradient-to-t from-charcoal/60 to-transparent rounded-2xl pointer-events-none" />
49
+ </div>
50
+
51
+ {/* Content */}
52
+ <div className="max-w-4xl mx-auto px-6">
53
+ {/* Topics */}
54
+ <div className="flex flex-wrap gap-2 mb-6">
55
+ {talk.topics.map((topic) => (
56
+ <span
57
+ key={topic}
58
+ className="inline-flex items-center gap-1.5 px-3 py-1 text-sm font-medium tracking-wide uppercase bg-gold/15 text-gold border border-gold/30 rounded-full"
59
+ >
60
+ <Tag className="w-3 h-3" />
61
+ {topic}
62
+ </span>
63
+ ))}
64
+ </div>
65
+
66
+ {/* Title */}
67
+ <h1 className="font-display text-4xl md:text-5xl font-bold text-cream mb-6 leading-tight">
68
+ {talk.title}
69
+ </h1>
70
+
71
+ {/* Meta info */}
72
+ <div className="flex flex-wrap items-center gap-6 mb-10 pb-10 border-b border-border/50">
73
+ {/* Speaker link */}
74
+ {speaker ? (
75
+ <Link
76
+ to={`/speakers/${speaker.slug}`}
77
+ className="flex items-center gap-3 group"
78
+ >
79
+ <div className="w-12 h-12 rounded-full overflow-hidden border border-border/50">
80
+ <img
81
+ src={`/${speaker.headshot}`}
82
+ alt={speaker.name}
83
+ className="w-full h-full object-cover"
84
+ />
85
+ </div>
86
+ <div>
87
+ <p className="text-cream group-hover:text-gold transition-colors font-medium">
88
+ {talk.speaker}
89
+ </p>
90
+ <p className="text-cream/50 text-sm">{speaker.restaurant}</p>
91
+ </div>
92
+ </Link>
93
+ ) : (
94
+ <div className="flex items-center gap-2 text-cream/70">
95
+ <User className="w-5 h-5 text-copper" />
96
+ <span>{talk.speaker}</span>
97
+ </div>
98
+ )}
99
+
100
+ {/* Duration */}
101
+ <div className="flex items-center gap-2 text-cream/60">
102
+ <Clock className="w-5 h-5 text-copper" />
103
+ <span className="text-lg">{talk.duration}</span>
104
+ </div>
105
+ </div>
106
+
107
+ {/* Description content */}
108
+ <div className="prose prose-lg max-w-none prose-invert prose-p:text-cream/80 prose-headings:text-cream prose-headings:font-display prose-strong:text-cream prose-a:text-gold prose-li:text-cream/80 prose-ul:text-cream/80 font-body text-lg leading-relaxed pb-20">
109
+ <div
110
+ dangerouslySetInnerHTML={{ __html: marked(talk.content) }}
111
+ />
112
+ </div>
113
+ </div>
114
+ </div>
115
+ )
116
+ }
@@ -0,0 +1,40 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+
3
+ import { allTalks } from 'content-collections'
4
+
5
+ import TalkCard from '@/components/TalkCard'
6
+ import RemyAssistant from '@/components/RemyAssistant'
7
+
8
+ export const Route = createFileRoute('/talks/')({
9
+ component: TalksPage,
10
+ })
11
+
12
+ function TalksPage() {
13
+ return (
14
+ <>
15
+ <RemyAssistant />
16
+ <div className="min-h-screen">
17
+ {/* Hero section */}
18
+ <div className="relative py-16 px-6">
19
+ <div className="max-w-7xl mx-auto text-center">
20
+ <h1 className="font-display text-5xl md:text-6xl font-bold text-cream mb-4">
21
+ Conference <span className="text-gold italic">Sessions</span>
22
+ </h1>
23
+ <p className="text-xl text-cream/70 max-w-2xl mx-auto font-body">
24
+ Immerse yourself in masterclasses and demonstrations covering every aspect of artisan baking and pastry.
25
+ </p>
26
+ </div>
27
+ </div>
28
+
29
+ {/* Talks grid */}
30
+ <div className="max-w-7xl mx-auto px-6 pb-20">
31
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
32
+ {allTalks.map((talk) => (
33
+ <TalkCard key={talk.slug} talk={talk} />
34
+ ))}
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </>
39
+ )
40
+ }
@@ -0,0 +1,182 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,600;0,700;0,800;0,900;1,400;1,500;1,600;1,700&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500&display=swap');
2
+ @import 'tailwindcss';
3
+
4
+ @plugin "tailwindcss-animate";
5
+
6
+ @custom-variant dark (&:is(.dark *));
7
+
8
+ body {
9
+ @apply m-0;
10
+ font-family: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ }
14
+
15
+ code {
16
+ font-family:
17
+ source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
18
+ }
19
+
20
+ /* Haute Patisserie Dark Theme */
21
+ :root {
22
+ /* Core colors - Dark elegant bakery */
23
+ --background: oklch(0.13 0.01 60);
24
+ --foreground: oklch(0.93 0.02 85);
25
+
26
+ /* Warm cream for cards */
27
+ --card: oklch(0.17 0.015 55);
28
+ --card-foreground: oklch(0.93 0.02 85);
29
+
30
+ /* Copper accent */
31
+ --primary: oklch(0.65 0.14 55);
32
+ --primary-foreground: oklch(0.13 0.01 60);
33
+
34
+ /* Antique gold */
35
+ --secondary: oklch(0.72 0.12 85);
36
+ --secondary-foreground: oklch(0.13 0.01 60);
37
+
38
+ /* Muted warm tones */
39
+ --muted: oklch(0.22 0.02 55);
40
+ --muted-foreground: oklch(0.65 0.03 85);
41
+
42
+ /* Accent - rich copper */
43
+ --accent: oklch(0.55 0.15 45);
44
+ --accent-foreground: oklch(0.95 0.02 85);
45
+
46
+ /* Destructive */
47
+ --destructive: oklch(0.55 0.2 25);
48
+ --destructive-foreground: oklch(0.95 0.02 85);
49
+
50
+ /* Borders and inputs */
51
+ --border: oklch(0.28 0.03 55);
52
+ --input: oklch(0.22 0.02 55);
53
+ --ring: oklch(0.65 0.14 55);
54
+
55
+ /* Chart colors - pastry inspired */
56
+ --chart-1: oklch(0.65 0.14 55);
57
+ --chart-2: oklch(0.72 0.12 85);
58
+ --chart-3: oklch(0.55 0.15 45);
59
+ --chart-4: oklch(0.60 0.10 30);
60
+ --chart-5: oklch(0.50 0.08 150);
61
+
62
+ --radius: 0.625rem;
63
+
64
+ /* Popover */
65
+ --popover: oklch(0.17 0.015 55);
66
+ --popover-foreground: oklch(0.93 0.02 85);
67
+
68
+ /* Sidebar */
69
+ --sidebar: oklch(0.15 0.01 55);
70
+ --sidebar-foreground: oklch(0.93 0.02 85);
71
+ --sidebar-primary: oklch(0.65 0.14 55);
72
+ --sidebar-primary-foreground: oklch(0.95 0.02 85);
73
+ --sidebar-accent: oklch(0.22 0.02 55);
74
+ --sidebar-accent-foreground: oklch(0.93 0.02 85);
75
+ --sidebar-border: oklch(0.28 0.03 55);
76
+ --sidebar-ring: oklch(0.65 0.14 55);
77
+ }
78
+
79
+ @theme inline {
80
+ --font-display: 'Playfair Display', Georgia, serif;
81
+ --font-body: 'Cormorant Garamond', Georgia, serif;
82
+
83
+ --color-background: var(--background);
84
+ --color-foreground: var(--foreground);
85
+ --color-card: var(--card);
86
+ --color-card-foreground: var(--card-foreground);
87
+ --color-popover: var(--popover);
88
+ --color-popover-foreground: var(--popover-foreground);
89
+ --color-primary: var(--primary);
90
+ --color-primary-foreground: var(--primary-foreground);
91
+ --color-secondary: var(--secondary);
92
+ --color-secondary-foreground: var(--secondary-foreground);
93
+ --color-muted: var(--muted);
94
+ --color-muted-foreground: var(--muted-foreground);
95
+ --color-accent: var(--accent);
96
+ --color-accent-foreground: var(--accent-foreground);
97
+ --color-destructive: var(--destructive);
98
+ --color-destructive-foreground: var(--destructive-foreground);
99
+ --color-border: var(--border);
100
+ --color-input: var(--input);
101
+ --color-ring: var(--ring);
102
+ --color-chart-1: var(--chart-1);
103
+ --color-chart-2: var(--chart-2);
104
+ --color-chart-3: var(--chart-3);
105
+ --color-chart-4: var(--chart-4);
106
+ --color-chart-5: var(--chart-5);
107
+ --radius-sm: calc(var(--radius) - 4px);
108
+ --radius-md: calc(var(--radius) - 2px);
109
+ --radius-lg: var(--radius);
110
+ --radius-xl: calc(var(--radius) + 4px);
111
+ --color-sidebar: var(--sidebar);
112
+ --color-sidebar-foreground: var(--sidebar-foreground);
113
+ --color-sidebar-primary: var(--sidebar-primary);
114
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
115
+ --color-sidebar-accent: var(--sidebar-accent);
116
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
117
+ --color-sidebar-border: var(--sidebar-border);
118
+ --color-sidebar-ring: var(--sidebar-ring);
119
+
120
+ /* Custom colors for the theme */
121
+ --color-copper: oklch(0.65 0.14 55);
122
+ --color-copper-light: oklch(0.75 0.12 55);
123
+ --color-copper-dark: oklch(0.50 0.15 50);
124
+ --color-gold: oklch(0.72 0.12 85);
125
+ --color-gold-light: oklch(0.82 0.10 85);
126
+ --color-cream: oklch(0.93 0.02 85);
127
+ --color-cream-dark: oklch(0.85 0.03 80);
128
+ --color-charcoal: oklch(0.13 0.01 60);
129
+ --color-charcoal-light: oklch(0.20 0.015 55);
130
+ }
131
+
132
+ @layer base {
133
+ * {
134
+ @apply border-border outline-ring/50;
135
+ }
136
+ body {
137
+ @apply bg-background text-foreground;
138
+ }
139
+ }
140
+
141
+ /* Custom utilities for the theme */
142
+ .font-display {
143
+ font-family: 'Playfair Display', Georgia, serif;
144
+ }
145
+
146
+ .font-body {
147
+ font-family: 'Cormorant Garamond', Georgia, serif;
148
+ }
149
+
150
+ /* Elegant grain texture overlay */
151
+ .grain-texture {
152
+ position: relative;
153
+ }
154
+
155
+ .grain-texture::after {
156
+ content: '';
157
+ position: absolute;
158
+ inset: 0;
159
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%' height='100%' filter='url(%23noise)' opacity='0.08'/%3E%3C/svg%3E");
160
+ pointer-events: none;
161
+ opacity: 0.4;
162
+ }
163
+
164
+ /* Golden border accent */
165
+ .border-gold-accent {
166
+ border-image: linear-gradient(135deg, oklch(0.72 0.12 85), oklch(0.65 0.14 55), oklch(0.72 0.12 85)) 1;
167
+ }
168
+
169
+ /* Copper glow effect */
170
+ .glow-copper {
171
+ box-shadow: 0 0 20px oklch(0.65 0.14 55 / 0.3), 0 0 40px oklch(0.65 0.14 55 / 0.1);
172
+ }
173
+
174
+ /* Elegant card hover effect */
175
+ .card-hover {
176
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
177
+ }
178
+
179
+ .card-hover:hover {
180
+ transform: translateY(-4px);
181
+ box-shadow: 0 12px 40px oklch(0 0 0 / 0.4), 0 0 20px oklch(0.65 0.14 55 / 0.15);
182
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "Events",
3
+ "description": "A pastry conference website with speakers, sessions, schedule, and AI assistant built with content-collections and TanStack Start for Netlify.",
4
+ "phase": "example",
5
+ "modes": ["file-router"],
6
+ "type": "example",
7
+ "priority": 10,
8
+ "link": "",
9
+ "routes": [
10
+ {
11
+ "url": "/",
12
+ "path": "src/routes/index.tsx",
13
+ "jsName": "EventsHome"
14
+ },
15
+ {
16
+ "url": "/schedule",
17
+ "path": "src/routes/schedule.index.tsx",
18
+ "jsName": "SchedulePage"
19
+ },
20
+ {
21
+ "url": "/speakers",
22
+ "path": "src/routes/speakers.index.tsx",
23
+ "jsName": "SpeakersPage"
24
+ },
25
+ {
26
+ "url": "/speakers/$slug",
27
+ "path": "src/routes/speakers.$slug.tsx",
28
+ "jsName": "SpeakerDetail"
29
+ },
30
+ {
31
+ "url": "/talks",
32
+ "path": "src/routes/talks.index.tsx",
33
+ "jsName": "TalksPage"
34
+ },
35
+ {
36
+ "url": "/talks/$slug",
37
+ "path": "src/routes/talks.$slug.tsx",
38
+ "jsName": "TalkDetail"
39
+ },
40
+ {
41
+ "url": "/api/remy-chat",
42
+ "path": "src/routes/api.remy-chat.ts",
43
+ "jsName": "RemyChatAPI"
44
+ }
45
+ ],
46
+ "integrations": [
47
+ {
48
+ "type": "vite-plugin",
49
+ "import": "import contentCollections from '@content-collections/vite'",
50
+ "code": "contentCollections()"
51
+ }
52
+ ],
53
+ "dependsOn": [],
54
+ "variables": [],
55
+ "bareBones": {
56
+ "deleteFiles": [
57
+ "public/background-2.jpg",
58
+ "public/background-3.jpg",
59
+ "public/background-4.jpg",
60
+ "public/speakers/hans-mueller.jpg",
61
+ "public/speakers/isabella-martinez.jpg",
62
+ "public/speakers/kenji-nakamura.jpg",
63
+ "public/speakers/marie-dubois.jpg",
64
+ "public/speakers/priya-sharma.jpg",
65
+ "public/talks/french-macaron-mastery.jpg",
66
+ "public/talks/neapolitan-pizza-tradition-meets-innovation.jpg",
67
+ "public/talks/savory-breads-of-the-mediterranean.jpg",
68
+ "public/talks/sourdough-from-starter-to-masterpiece.jpg",
69
+ "public/talks/the-art-of-the-perfect-tart.jpg",
70
+ "public/talks/the-science-of-sugar.jpg",
71
+ "public/talks/umami-in-pastry-east-meets-west.jpg"
72
+ ]
73
+ }
74
+ }
@@ -0,0 +1,23 @@
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-gemini": "0.3.2",
7
+ "@tanstack/ai-ollama": "0.3.0",
8
+ "@tanstack/ai-openai": "0.3.0",
9
+ "@tanstack/ai-react": "0.2.2",
10
+ "@tanstack/store": "^0.8.0",
11
+ "class-variance-authority": "^0.7.1",
12
+ "clsx": "^2.1.1",
13
+ "marked": "^17.0.1",
14
+ "streamdown": "^2.1.0",
15
+ "tailwind-merge": "^3.0.2",
16
+ "tailwindcss-animate": "^1.0.7",
17
+ "zod": "^4.3.5"
18
+ },
19
+ "devDependencies": {
20
+ "@content-collections/core": "^0.13.1",
21
+ "@content-collections/vite": "^0.2.8"
22
+ }
23
+ }
@@ -0,0 +1,60 @@
1
+ # E-commerce Example
2
+
3
+ An AI-powered motorcycle e-commerce store built with TanStack Start and TanStack AI for Netlify deployment.
4
+
5
+ ## Features
6
+
7
+ - **AI Chat Assistant**: Powered by TanStack AI with Anthropic Claude
8
+ - **Product Catalog**: Browse Luna-C motorcycle inventory
9
+ - **Smart Recommendations**: AI can recommend motorcycles based on your needs
10
+ - **SSR Ready**: Full server-side rendering with TanStack Start
11
+
12
+ ## Project Structure
13
+
14
+ ```
15
+ ├── src/
16
+ │ ├── components/
17
+ │ │ ├── AIAssistant.tsx # Chat panel component
18
+ │ │ ├── Header.tsx # Navigation with AI button
19
+ │ │ └── MotorcycleRecommendation.tsx # Product card for AI
20
+ │ ├── data/
21
+ │ │ └── motorcycles.ts # Product inventory
22
+ │ ├── lib/
23
+ │ │ ├── ai-hook.ts # useMotorcycleChat hook
24
+ │ │ └── motorcycle-tools.ts # AI tool definitions
25
+ │ ├── store/
26
+ │ │ └── assistant.ts # UI state with TanStack Store
27
+ │ └── routes/
28
+ │ ├── __root.tsx # Root layout
29
+ │ ├── index.tsx # Product listing
30
+ │ ├── motorcycles/$motorcycleId.tsx # Product detail
31
+ │ └── api.motorcycle-chat.ts # Chat API endpoint
32
+ └── public/
33
+ └── *.jpg # Product images
34
+ ```
35
+
36
+ ## AI Chat Features
37
+
38
+ The AI assistant can:
39
+ - Answer questions about motorcycles
40
+ - Recommend bikes based on your preferences (budget, experience level, riding style)
41
+ - Display product cards directly in the chat
42
+ - Help you find the perfect motorcycle
43
+
44
+ ## Environment Variables
45
+
46
+ Create a `.env.local` file with your Anthropic API key:
47
+
48
+ ```
49
+ ANTHROPIC_API_KEY=your_api_key_here
50
+ ```
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ # Start development server
56
+ npm run dev
57
+
58
+ # Build for production
59
+ npm run build
60
+ ```
@@ -0,0 +1,36 @@
1
+ import { Link } from '@tanstack/react-router'
2
+
3
+ import HeaderNav from './HeaderNav'
4
+
5
+ import MotorcycleAIAssistant from '@/components/MotorcycleAIAssistant'
6
+
7
+ export default function Header() {
8
+ return (
9
+ <>
10
+ <div className="z-40">
11
+ <HeaderNav />
12
+ </div>
13
+ <header className="p-4 flex gap-2 bg-black/30 text-white border-b border-orange-500/20 backdrop-blur-md sticky top-0 z-40">
14
+ <nav className="flex flex-row items-center">
15
+ <div className="px-4 font-extrabold text-lg">
16
+ <Link
17
+ to="/"
18
+ className="hover:text-orange-400 transition-colors flex flex-row items-center"
19
+ >
20
+ <img
21
+ src="/logo.png"
22
+ alt="Luna-C Motorcycles"
23
+ className="w-20 h-20"
24
+ />
25
+ <span className="text-2xl font-bold">Luna-C Motorcycles</span>
26
+ </Link>
27
+ </div>
28
+ </nav>
29
+
30
+ <div className="ml-auto">
31
+ <MotorcycleAIAssistant />
32
+ </div>
33
+ </header>
34
+ </>
35
+ )
36
+ }