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.
Files changed (296) hide show
  1. package/dist/cli.js +104 -208
  2. package/dist/index.js +1 -31
  3. package/dist/types/cli.d.ts +1 -8
  4. package/dist/types/types.d.ts +7 -12
  5. package/package.json +1 -2
  6. package/src/cli.ts +129 -271
  7. package/src/index.ts +1 -47
  8. package/src/types.ts +7 -13
  9. package/CONTEXT.md +0 -139
  10. package/add-ons/ai/README.md +0 -34
  11. package/add-ons/ai/assets/AGENTS.md.append +0 -24
  12. package/add-ons/ai/assets/_dot_env.local.append +0 -13
  13. package/add-ons/ai/assets/src/components/AIAssistant.tsx +0 -149
  14. package/add-ons/ai/assets/src/lib/ai-hook.ts +0 -21
  15. package/add-ons/ai/assets/src/lib/weather-tools.ts +0 -30
  16. package/add-ons/ai/assets/src/routes/api.chat.ts +0 -94
  17. package/add-ons/ai/assets/src/routes/chat.css +0 -175
  18. package/add-ons/ai/assets/src/routes/chat.tsx +0 -141
  19. package/add-ons/ai/info.json +0 -22
  20. package/add-ons/ai/package.json +0 -17
  21. package/add-ons/ai/small-logo.svg +0 -8
  22. package/add-ons/db/assets/AGENTS.md.append +0 -22
  23. package/add-ons/db/assets/DB-SETUP.md +0 -65
  24. package/add-ons/db/assets/_dot_env.local.append +0 -2
  25. package/add-ons/db/assets/drizzle.config.ts +0 -10
  26. package/add-ons/db/assets/src/db/index.ts +0 -8
  27. package/add-ons/db/assets/src/db/schema.ts +0 -8
  28. package/add-ons/db/assets/src/routes/db-example.tsx +0 -118
  29. package/add-ons/db/assets/src/server/guestbook.functions.ts +0 -23
  30. package/add-ons/db/info.json +0 -22
  31. package/add-ons/db/package.json +0 -10
  32. package/add-ons/forms/assets/AGENTS.md.append +0 -13
  33. package/add-ons/forms/assets/public/form-example.html +0 -14
  34. package/add-ons/forms/assets/src/routes/form-example.tsx +0 -76
  35. package/add-ons/forms/info.json +0 -18
  36. package/add-ons/forms/package.json +0 -3
  37. package/examples/ai-chat/README.md +0 -36
  38. package/examples/ai-chat/assets/AGENTS.md.append +0 -24
  39. package/examples/ai-chat/assets/src/lib/ai-hook.ts +0 -21
  40. package/examples/ai-chat/assets/src/lib/weather-tools.ts +0 -30
  41. package/examples/ai-chat/assets/src/routes/__root.tsx +0 -57
  42. package/examples/ai-chat/assets/src/routes/api.chat.ts +0 -94
  43. package/examples/ai-chat/assets/src/routes/index.tsx +0 -141
  44. package/examples/ai-chat/assets/src/styles.css +0 -165
  45. package/examples/ai-chat/info.json +0 -25
  46. package/examples/ai-chat/package.json +0 -14
  47. package/examples/blog/README.md +0 -60
  48. package/examples/blog/assets/AGENTS.md.append +0 -18
  49. package/examples/blog/assets/content/posts/beach.md +0 -12
  50. package/examples/blog/assets/content/posts/jungle.md.ejs +0 -12
  51. package/examples/blog/assets/content/posts/mountains.md.ejs +0 -12
  52. package/examples/blog/assets/content/posts/snorkeling.md.ejs +0 -12
  53. package/examples/blog/assets/content/posts/waterfall.md.ejs +0 -12
  54. package/examples/blog/assets/content-collections.ts +0 -30
  55. package/examples/blog/assets/public/beach.jpg +0 -0
  56. package/examples/blog/assets/public/jungle.jpg +0 -0
  57. package/examples/blog/assets/public/mountains.jpg +0 -0
  58. package/examples/blog/assets/public/snorkeling.jpg +0 -0
  59. package/examples/blog/assets/public/waterfall.jpg +0 -0
  60. package/examples/blog/assets/src/components/Header.tsx +0 -52
  61. package/examples/blog/assets/src/components/VacayAssistant.tsx +0 -205
  62. package/examples/blog/assets/src/components/blog-posts.tsx +0 -78
  63. package/examples/blog/assets/src/components/ui/card.tsx +0 -92
  64. package/examples/blog/assets/src/lib/blog-ai-hook.ts +0 -25
  65. package/examples/blog/assets/src/lib/blog-tools.ts +0 -111
  66. package/examples/blog/assets/src/lib/utils.ts +0 -6
  67. package/examples/blog/assets/src/routes/__root.tsx +0 -57
  68. package/examples/blog/assets/src/routes/api.blog-chat.ts +0 -117
  69. package/examples/blog/assets/src/routes/category.$category.tsx +0 -19
  70. package/examples/blog/assets/src/routes/index.tsx +0 -19
  71. package/examples/blog/assets/src/routes/posts.$slug.tsx +0 -63
  72. package/examples/blog/assets/src/styles.css +0 -138
  73. package/examples/blog/info.json +0 -40
  74. package/examples/blog/package.json +0 -23
  75. package/examples/calculator/README.md +0 -16
  76. package/examples/calculator/assets/AGENTS.md.append +0 -9
  77. package/examples/calculator/assets/src/components/Calculator.tsx +0 -238
  78. package/examples/calculator/assets/src/components/Header.tsx +0 -17
  79. package/examples/calculator/assets/src/routes/__root.tsx +0 -57
  80. package/examples/calculator/assets/src/routes/index.tsx +0 -14
  81. package/examples/calculator/info.json +0 -20
  82. package/examples/calculator/package.json +0 -1
  83. package/examples/dashboard/README.md +0 -17
  84. package/examples/dashboard/assets/AGENTS.md.append +0 -12
  85. package/examples/dashboard/assets/src/components/Header.tsx +0 -17
  86. package/examples/dashboard/assets/src/routes/__root.tsx +0 -57
  87. package/examples/dashboard/assets/src/routes/index.tsx +0 -158
  88. package/examples/dashboard/info.json +0 -19
  89. package/examples/dashboard/package.json +0 -6
  90. package/examples/ecommerce/README.md +0 -48
  91. package/examples/ecommerce/assets/AGENTS.md.append +0 -22
  92. package/examples/ecommerce/assets/public/logo.png +0 -0
  93. package/examples/ecommerce/assets/public/motorcycle-scooter.jpg +0 -0
  94. package/examples/ecommerce/assets/src/components/BuyButton.tsx +0 -35
  95. package/examples/ecommerce/assets/src/components/Header.tsx +0 -36
  96. package/examples/ecommerce/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
  97. package/examples/ecommerce/assets/src/components/MotorcycleRecommendation.tsx +0 -53
  98. package/examples/ecommerce/assets/src/data/motorcycles.ts +0 -27
  99. package/examples/ecommerce/assets/src/lib/motorcycle-ai-hook.ts +0 -24
  100. package/examples/ecommerce/assets/src/lib/motorcycle-tools.ts +0 -42
  101. package/examples/ecommerce/assets/src/lib/stripe.server.ts +0 -39
  102. package/examples/ecommerce/assets/src/routes/__root.tsx +0 -57
  103. package/examples/ecommerce/assets/src/routes/api.motorcycle-chat.ts +0 -78
  104. package/examples/ecommerce/assets/src/routes/checkout/cancel.tsx +0 -25
  105. package/examples/ecommerce/assets/src/routes/checkout/success.tsx +0 -25
  106. package/examples/ecommerce/assets/src/routes/index.tsx +0 -76
  107. package/examples/ecommerce/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -55
  108. package/examples/ecommerce/assets/src/store/motorcycle-assistant.ts +0 -3
  109. package/examples/ecommerce/assets/src/styles.css +0 -212
  110. package/examples/ecommerce/info.json +0 -38
  111. package/examples/ecommerce/package.json +0 -13
  112. package/examples/events/README.md +0 -110
  113. package/examples/events/assets/AGENTS.md.append +0 -21
  114. package/examples/events/assets/content/speakers/andre-costa.md +0 -22
  115. package/examples/events/assets/content/speakers/hans-mueller.md.ejs +0 -22
  116. package/examples/events/assets/content/speakers/isabella-martinez.md.ejs +0 -22
  117. package/examples/events/assets/content/speakers/kenji-nakamura.md.ejs +0 -22
  118. package/examples/events/assets/content/speakers/marie-dubois.md.ejs +0 -20
  119. package/examples/events/assets/content/speakers/priya-sharma.md.ejs +0 -22
  120. package/examples/events/assets/content/talks/croissant-lamination-secrets.md +0 -39
  121. package/examples/events/assets/content/talks/french-macaron-mastery.md.ejs +0 -39
  122. package/examples/events/assets/content/talks/neapolitan-pizza-tradition-meets-innovation.md.ejs +0 -39
  123. package/examples/events/assets/content/talks/savory-breads-of-the-mediterranean.md.ejs +0 -39
  124. package/examples/events/assets/content/talks/sourdough-from-starter-to-masterpiece.md.ejs +0 -36
  125. package/examples/events/assets/content/talks/the-art-of-the-perfect-tart.md.ejs +0 -32
  126. package/examples/events/assets/content/talks/the-science-of-sugar.md.ejs +0 -39
  127. package/examples/events/assets/content/talks/umami-in-pastry-east-meets-west.md.ejs +0 -39
  128. package/examples/events/assets/content-collections.ts +0 -56
  129. package/examples/events/assets/public/background-1.jpg +0 -0
  130. package/examples/events/assets/public/background-2.jpg +0 -0
  131. package/examples/events/assets/public/background-3.jpg +0 -0
  132. package/examples/events/assets/public/background-4.jpg +0 -0
  133. package/examples/events/assets/public/conference-logo.png +0 -0
  134. package/examples/events/assets/public/favicon.ico +0 -0
  135. package/examples/events/assets/public/speakers/andre-costa.jpg +0 -0
  136. package/examples/events/assets/public/speakers/hans-mueller.jpg +0 -0
  137. package/examples/events/assets/public/speakers/isabella-martinez.jpg +0 -0
  138. package/examples/events/assets/public/speakers/kenji-nakamura.jpg +0 -0
  139. package/examples/events/assets/public/speakers/marie-dubois.jpg +0 -0
  140. package/examples/events/assets/public/speakers/priya-sharma.jpg +0 -0
  141. package/examples/events/assets/public/talks/croissant-lamination-secrets.jpg +0 -0
  142. package/examples/events/assets/public/talks/french-macaron-mastery.jpg +0 -0
  143. package/examples/events/assets/public/talks/neapolitan-pizza-tradition-meets-innovation.jpg +0 -0
  144. package/examples/events/assets/public/talks/savory-breads-of-the-mediterranean.jpg +0 -0
  145. package/examples/events/assets/public/talks/sourdough-from-starter-to-masterpiece.jpg +0 -0
  146. package/examples/events/assets/public/talks/the-art-of-the-perfect-tart.jpg +0 -0
  147. package/examples/events/assets/public/talks/the-science-of-sugar.jpg +0 -0
  148. package/examples/events/assets/public/talks/umami-in-pastry-east-meets-west.jpg +0 -0
  149. package/examples/events/assets/public/tanstack-circle-logo.png +0 -0
  150. package/examples/events/assets/public/tanstack-word-logo-white.svg +0 -1
  151. package/examples/events/assets/src/components/Header.tsx +0 -59
  152. package/examples/events/assets/src/components/HeaderNav.tsx +0 -67
  153. package/examples/events/assets/src/components/HeroCarousel.tsx +0 -61
  154. package/examples/events/assets/src/components/RemyAssistant.tsx +0 -207
  155. package/examples/events/assets/src/components/SpeakerCard.tsx +0 -67
  156. package/examples/events/assets/src/components/TalkCard.tsx +0 -77
  157. package/examples/events/assets/src/components/ui/card.tsx +0 -92
  158. package/examples/events/assets/src/lib/conference-ai-hook.ts +0 -26
  159. package/examples/events/assets/src/lib/conference-tools.ts +0 -210
  160. package/examples/events/assets/src/lib/model-selection.ts +0 -1
  161. package/examples/events/assets/src/lib/utils.ts +0 -6
  162. package/examples/events/assets/src/routes/__root.tsx +0 -70
  163. package/examples/events/assets/src/routes/api.remy-chat.ts +0 -119
  164. package/examples/events/assets/src/routes/index.tsx +0 -192
  165. package/examples/events/assets/src/routes/schedule.index.tsx +0 -274
  166. package/examples/events/assets/src/routes/speakers.$slug.tsx +0 -122
  167. package/examples/events/assets/src/routes/speakers.index.tsx +0 -40
  168. package/examples/events/assets/src/routes/talks.$slug.tsx +0 -116
  169. package/examples/events/assets/src/routes/talks.index.tsx +0 -40
  170. package/examples/events/assets/src/styles.css +0 -182
  171. package/examples/events/info.json +0 -61
  172. package/examples/events/package.json +0 -23
  173. package/examples/marketing/README.md +0 -60
  174. package/examples/marketing/assets/AGENTS.md.append +0 -15
  175. package/examples/marketing/assets/public/logo.png +0 -0
  176. package/examples/marketing/assets/public/motorcycle-adventure.jpg +0 -0
  177. package/examples/marketing/assets/public/motorcycle-cruiser.jpg +0 -0
  178. package/examples/marketing/assets/public/motorcycle-scooter.jpg +0 -0
  179. package/examples/marketing/assets/public/motorcycle-sport.jpg +0 -0
  180. package/examples/marketing/assets/public/motorcycle-supersport.jpg +0 -0
  181. package/examples/marketing/assets/src/components/Header.tsx +0 -36
  182. package/examples/marketing/assets/src/components/MotorcycleAIAssistant.tsx +0 -162
  183. package/examples/marketing/assets/src/components/MotorcycleRecommendation.tsx +0 -53
  184. package/examples/marketing/assets/src/data/motorcycles.ts.ejs +0 -77
  185. package/examples/marketing/assets/src/lib/motorcycle-ai-hook.ts +0 -24
  186. package/examples/marketing/assets/src/lib/motorcycle-tools.ts +0 -42
  187. package/examples/marketing/assets/src/routes/__root.tsx +0 -57
  188. package/examples/marketing/assets/src/routes/api.motorcycle-chat.ts +0 -78
  189. package/examples/marketing/assets/src/routes/index.tsx +0 -72
  190. package/examples/marketing/assets/src/routes/motorcycles/$motorcycleId.tsx +0 -56
  191. package/examples/marketing/assets/src/store/motorcycle-assistant.ts +0 -3
  192. package/examples/marketing/assets/src/styles.css +0 -212
  193. package/examples/marketing/info.json +0 -33
  194. package/examples/marketing/package.json +0 -14
  195. package/examples/portfolio/README.md +0 -49
  196. package/examples/portfolio/assets/AGENTS.md.append +0 -21
  197. package/examples/portfolio/assets/content/blog/getting-started-with-tanstack.md +0 -53
  198. package/examples/portfolio/assets/content/blog/react-19-features.md +0 -78
  199. package/examples/portfolio/assets/content/blog/tailwind-css-v4-guide.md +0 -60
  200. package/examples/portfolio/assets/content/education/code-school.md +0 -17
  201. package/examples/portfolio/assets/content/jobs/initech-junior.md +0 -20
  202. package/examples/portfolio/assets/content/projects/portfolio-site.md +0 -15
  203. package/examples/portfolio/assets/content/projects/task-manager.md +0 -15
  204. package/examples/portfolio/assets/content-collections.ts +0 -65
  205. package/examples/portfolio/assets/public/contact.html +0 -6
  206. package/examples/portfolio/assets/public/headshot-on-white.jpg +0 -0
  207. package/examples/portfolio/assets/src/components/Header.tsx +0 -33
  208. package/examples/portfolio/assets/src/components/ResumeAssistant.tsx +0 -193
  209. package/examples/portfolio/assets/src/components/ui/badge.tsx +0 -46
  210. package/examples/portfolio/assets/src/components/ui/card.tsx +0 -92
  211. package/examples/portfolio/assets/src/components/ui/checkbox.tsx +0 -30
  212. package/examples/portfolio/assets/src/components/ui/hover-card.tsx +0 -44
  213. package/examples/portfolio/assets/src/components/ui/separator.tsx +0 -26
  214. package/examples/portfolio/assets/src/lib/resume-ai-hook.ts +0 -21
  215. package/examples/portfolio/assets/src/lib/resume-tools.ts +0 -165
  216. package/examples/portfolio/assets/src/lib/utils.ts +0 -6
  217. package/examples/portfolio/assets/src/routes/__root.tsx +0 -57
  218. package/examples/portfolio/assets/src/routes/api.resume-chat.ts +0 -116
  219. package/examples/portfolio/assets/src/routes/blog/$slug.tsx +0 -73
  220. package/examples/portfolio/assets/src/routes/contact.tsx +0 -121
  221. package/examples/portfolio/assets/src/routes/index.tsx +0 -55
  222. package/examples/portfolio/assets/src/routes/projects.tsx +0 -62
  223. package/examples/portfolio/assets/src/routes/resume.tsx +0 -220
  224. package/examples/portfolio/assets/src/styles.css +0 -138
  225. package/examples/portfolio/info.json +0 -50
  226. package/examples/portfolio/package.json +0 -26
  227. package/examples/resume/README.md +0 -82
  228. package/examples/resume/assets/AGENTS.md.append +0 -19
  229. package/examples/resume/assets/content/education/code-school.md +0 -17
  230. package/examples/resume/assets/content/jobs/freelance.md.ejs +0 -13
  231. package/examples/resume/assets/content/jobs/initech-junior.md +0 -20
  232. package/examples/resume/assets/content/jobs/initech-lead.md.ejs +0 -29
  233. package/examples/resume/assets/content/jobs/initrode-senior.md.ejs +0 -28
  234. package/examples/resume/assets/content-collections.ts +0 -36
  235. package/examples/resume/assets/public/headshot-on-white.jpg +0 -0
  236. package/examples/resume/assets/src/components/Header.tsx +0 -33
  237. package/examples/resume/assets/src/components/ResumeAssistant.tsx +0 -193
  238. package/examples/resume/assets/src/components/ui/badge.tsx +0 -46
  239. package/examples/resume/assets/src/components/ui/card.tsx +0 -92
  240. package/examples/resume/assets/src/components/ui/checkbox.tsx +0 -30
  241. package/examples/resume/assets/src/components/ui/hover-card.tsx +0 -44
  242. package/examples/resume/assets/src/components/ui/separator.tsx +0 -26
  243. package/examples/resume/assets/src/lib/resume-ai-hook.ts +0 -21
  244. package/examples/resume/assets/src/lib/resume-tools.ts +0 -165
  245. package/examples/resume/assets/src/lib/utils.ts +0 -6
  246. package/examples/resume/assets/src/routes/api.resume-chat.ts +0 -110
  247. package/examples/resume/assets/src/routes/index.tsx +0 -220
  248. package/examples/resume/assets/src/styles.css +0 -138
  249. package/examples/resume/info.json +0 -35
  250. package/examples/resume/package.json +0 -26
  251. package/examples/saas/README.md +0 -16
  252. package/examples/saas/assets/AGENTS.md.append +0 -9
  253. package/examples/saas/assets/src/components/Header.tsx +0 -17
  254. package/examples/saas/assets/src/routes/__root.tsx +0 -57
  255. package/examples/saas/assets/src/routes/faq.tsx +0 -94
  256. package/examples/saas/assets/src/routes/index.tsx +0 -197
  257. package/examples/saas/info.json +0 -23
  258. package/examples/saas/package.json +0 -1
  259. package/examples/survey/README.md +0 -20
  260. package/examples/survey/assets/AGENTS.md.append +0 -9
  261. package/examples/survey/assets/public/form-survey.html +0 -15
  262. package/examples/survey/assets/src/components/SurveyForm.tsx +0 -128
  263. package/examples/survey/assets/src/routes/index.tsx +0 -14
  264. package/examples/survey/info.json +0 -19
  265. package/examples/survey/package.json +0 -1
  266. package/project/base/AGENTS.md +0 -86
  267. package/project/base/_dot_claude/skills/content-collections/SKILL.md +0 -505
  268. package/project/base/_dot_claude/skills/netlify-blobs/SKILL.md +0 -410
  269. package/project/base/_dot_claude/skills/netlify-db/SKILL.md +0 -424
  270. package/project/base/_dot_claude/skills/netlify-debugging/SKILL.md +0 -419
  271. package/project/base/_dot_claude/skills/netlify-forms/SKILL.md +0 -243
  272. package/project/base/_dot_claude/skills/netlify-functions/SKILL.md +0 -372
  273. package/project/base/_dot_claude/skills/tanstack-start-api-routes/SKILL.md +0 -421
  274. package/project/base/_dot_claude/skills/tanstack-start-loaders/SKILL.md +0 -426
  275. package/project/base/_dot_claude/skills/tanstack-start-project-setup/SKILL.md +0 -493
  276. package/project/base/_dot_claude/skills/tanstack-start-routes/SKILL.md +0 -430
  277. package/project/base/_dot_claude/skills/tanstack-start-server-functions/SKILL.md +0 -445
  278. package/project/base/_dot_claude/skills/tanstack-start-typesafe-routing/SKILL.md +0 -494
  279. package/project/base/_dot_gitignore +0 -8
  280. package/project/base/netlify.toml +0 -7
  281. package/project/base/package.json +0 -33
  282. package/project/base/public/favicon.ico +0 -0
  283. package/project/base/public/tanstack-circle-logo.png +0 -0
  284. package/project/base/public/tanstack-word-logo-white.svg +0 -1
  285. package/project/base/src/components/Header.tsx +0 -17
  286. package/project/base/src/components/HeaderNav.tsx.ejs +0 -179
  287. package/project/base/src/router.tsx +0 -15
  288. package/project/base/src/routes/__root.tsx +0 -57
  289. package/project/base/src/routes/index.tsx +0 -48
  290. package/project/base/src/styles.css +0 -15
  291. package/project/base/tsconfig.json +0 -28
  292. package/project/base/vite.config.ts.ejs +0 -25
  293. package/project/info.json +0 -17
  294. package/project/packages.json +0 -22
  295. package/scripts/check-outdated-packages.js +0 -421
  296. package/src/agents-md.ts +0 -139
@@ -1,94 +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
- import { openaiText } from '@tanstack/ai-openai'
5
- import { geminiText } from '@tanstack/ai-gemini'
6
- import { ollamaText } from '@tanstack/ai-ollama'
7
-
8
- import { getWeather } from '@/lib/weather-tools'
9
-
10
- const SYSTEM_PROMPT = `You are a helpful weather assistant. You can check the weather for any city using the getWeather tool.
11
-
12
- CAPABILITIES:
13
- 1. Use getWeather to get the current weather for any city
14
-
15
- INSTRUCTIONS:
16
- - When users ask about weather, use the getWeather tool to get the information
17
- - Provide friendly, conversational responses about the weather
18
- - You can give advice based on weather conditions (e.g., "bring an umbrella" if rainy)
19
- - Keep responses concise but helpful`
20
-
21
- export const Route = createFileRoute('/api/chat')({
22
- server: {
23
- handlers: {
24
- POST: async ({ request }) => {
25
- const requestSignal = request.signal
26
-
27
- if (requestSignal.aborted) {
28
- return new Response(null, { status: 499 })
29
- }
30
-
31
- const abortController = new AbortController()
32
-
33
- try {
34
- const body = await request.json()
35
- const { messages } = body
36
- const data = body.data || {}
37
-
38
- // Determine the best available provider
39
- let provider: 'anthropic' | 'openai' | 'gemini' | 'ollama' =
40
- data.provider || 'ollama'
41
- let model: string = data.model || 'mistral:7b'
42
-
43
- // Use the first available provider with an API key, fallback to ollama
44
- if (process.env.ANTHROPIC_API_KEY) {
45
- provider = 'anthropic'
46
- model = 'claude-haiku-4-5'
47
- } else if (process.env.OPENAI_API_KEY) {
48
- provider = 'openai'
49
- model = 'gpt-4o'
50
- } else if (process.env.GEMINI_API_KEY) {
51
- provider = 'gemini'
52
- model = 'gemini-2.0-flash-exp'
53
- }
54
-
55
- const adapterConfig = {
56
- anthropic: () =>
57
- anthropicText((model || 'claude-haiku-4-5') as any),
58
- openai: () => openaiText((model || 'gpt-4o') as any),
59
- gemini: () => geminiText((model || 'gemini-2.0-flash-exp') as any),
60
- ollama: () => ollamaText((model || 'mistral:7b') as any),
61
- }
62
-
63
- const adapter = adapterConfig[provider]()
64
-
65
- const stream = chat({
66
- adapter,
67
- tools: [getWeather],
68
- systemPrompts: [SYSTEM_PROMPT],
69
- agentLoopStrategy: maxIterations(5),
70
- messages,
71
- abortController,
72
- })
73
-
74
- return toServerSentEventsResponse(stream, { abortController })
75
- } catch (error: any) {
76
- console.error('Chat error:', error)
77
- if (error.name === 'AbortError' || abortController.signal.aborted) {
78
- return new Response(null, { status: 499 })
79
- }
80
- return new Response(
81
- JSON.stringify({
82
- error: 'Failed to process chat request',
83
- message: error.message,
84
- }),
85
- {
86
- status: 500,
87
- headers: { 'Content-Type': 'application/json' },
88
- },
89
- )
90
- }
91
- },
92
- },
93
- },
94
- })
@@ -1,141 +0,0 @@
1
- import { useEffect, useRef, useState } from 'react'
2
- import { createFileRoute } from '@tanstack/react-router'
3
- import { Send, Square } from 'lucide-react'
4
- import { Streamdown } from 'streamdown'
5
-
6
- import { useAIChat } from '@/lib/ai-hook'
7
- import type { ChatMessages } from '@/lib/ai-hook'
8
-
9
- function Messages({ messages }: { messages: ChatMessages }) {
10
- const messagesContainerRef = useRef<HTMLDivElement>(null)
11
-
12
- useEffect(() => {
13
- if (messagesContainerRef.current) {
14
- messagesContainerRef.current.scrollTop =
15
- messagesContainerRef.current.scrollHeight
16
- }
17
- }, [messages])
18
-
19
- if (!messages.length) {
20
- return null
21
- }
22
-
23
- return (
24
- <div
25
- ref={messagesContainerRef}
26
- className="flex-1 overflow-y-auto pb-4 min-h-0"
27
- >
28
- <div className="max-w-3xl mx-auto w-full px-4">
29
- {messages.map((message) => (
30
- <div
31
- key={message.id}
32
- className={`p-4 ${
33
- message.role === 'assistant'
34
- ? 'bg-linear-to-r from-orange-500/5 to-red-600/5'
35
- : 'bg-transparent'
36
- }`}
37
- >
38
- <div className="flex items-start gap-4 max-w-3xl mx-auto w-full">
39
- <div
40
- className={`w-8 h-8 rounded-lg flex items-center justify-center text-sm font-medium text-white flex-shrink-0 ${
41
- message.role === 'assistant'
42
- ? 'bg-linear-to-r from-orange-500 to-red-600'
43
- : 'bg-gray-700'
44
- }`}
45
- >
46
- {message.role === 'assistant' ? 'AI' : 'Y'}
47
- </div>
48
- <div className="flex-1 min-w-0">
49
- {message.parts.map((part, index) => {
50
- if (part.type === 'text' && part.content) {
51
- return (
52
- <div
53
- className="flex-1 min-w-0 prose dark:prose-invert max-w-none prose-sm"
54
- key={index}
55
- >
56
- <Streamdown>{part.content}</Streamdown>
57
- </div>
58
- )
59
- }
60
- return null
61
- })}
62
- </div>
63
- </div>
64
- </div>
65
- ))}
66
- </div>
67
- </div>
68
- )
69
- }
70
-
71
- function Home() {
72
- const [input, setInput] = useState('')
73
- const { messages, sendMessage, isLoading, stop } = useAIChat()
74
-
75
- return (
76
- <div className="relative flex h-[calc(100vh-80px)] bg-gray-900">
77
- <div className="flex-1 flex flex-col min-h-0">
78
- {messages.length === 0 && (
79
- <div className="flex-1 flex items-center justify-center px-4">
80
- <div className="text-center max-w-3xl mx-auto w-full">
81
- <h1 className="text-4xl font-bold mb-4 text-white">
82
- Weather Chat
83
- </h1>
84
- <p className="text-gray-400 mb-6">
85
- Ask me about the weather! Try "What's the weather in Paris?"
86
- </p>
87
- </div>
88
- </div>
89
- )}
90
- <Messages messages={messages} />
91
-
92
- <div className="sticky bottom-0 left-0 right-0 bg-gray-900/80 backdrop-blur-sm border-t border-orange-500/10 z-10">
93
- <div className="max-w-3xl mx-auto w-full px-4 py-3">
94
- {isLoading && (
95
- <div className="flex items-center justify-center mb-3">
96
- <button
97
- onClick={stop}
98
- className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-sm font-medium transition-colors flex items-center gap-2"
99
- >
100
- <Square className="w-4 h-4 fill-current" />
101
- Stop
102
- </button>
103
- </div>
104
- )}
105
- <form
106
- onSubmit={(e) => {
107
- e.preventDefault()
108
- if (input.trim()) {
109
- sendMessage(input)
110
- setInput('')
111
- }
112
- }}
113
- >
114
- <div className="relative max-w-xl mx-auto flex items-center gap-2">
115
- <input
116
- type="text"
117
- value={input}
118
- onChange={(e) => setInput(e.target.value)}
119
- placeholder="Ask about the weather..."
120
- className="w-full rounded-lg border border-orange-500/20 bg-gray-800/50 px-4 py-3 text-sm text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-orange-500/50"
121
- disabled={isLoading}
122
- />
123
- <button
124
- type="submit"
125
- disabled={!input.trim() || isLoading}
126
- className="p-3 bg-orange-500 hover:bg-orange-600 disabled:bg-gray-600 text-white rounded-lg transition-colors"
127
- >
128
- <Send className="w-4 h-4" />
129
- </button>
130
- </div>
131
- </form>
132
- </div>
133
- </div>
134
- </div>
135
- </div>
136
- )
137
- }
138
-
139
- export const Route = createFileRoute('/')({
140
- component: Home,
141
- })
@@ -1,165 +0,0 @@
1
- @import "tailwindcss";
2
- @import "highlight.js/styles/github-dark.css";
3
- @source "../../../node_modules/streamdown/dist/*.js";
4
-
5
- body {
6
- @apply m-0;
7
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
8
- "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
9
- sans-serif;
10
- -webkit-font-smoothing: antialiased;
11
- -moz-osx-font-smoothing: grayscale;
12
- }
13
-
14
- code {
15
- font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
16
- monospace;
17
- }
18
-
19
- /* Custom scrollbar styles */
20
- ::-webkit-scrollbar {
21
- width: 8px;
22
- }
23
-
24
- ::-webkit-scrollbar-track {
25
- background: transparent;
26
- }
27
-
28
- ::-webkit-scrollbar-thumb {
29
- background-color: rgba(156, 163, 175, 0.5);
30
- border-radius: 4px;
31
- }
32
-
33
- ::-webkit-scrollbar-thumb:hover {
34
- background-color: rgba(156, 163, 175, 0.7);
35
- }
36
-
37
- /* Smooth transitions for dark mode */
38
- html {
39
- transition: background-color 0.3s ease;
40
- }
41
-
42
- /* Markdown content styles */
43
- .prose {
44
- max-width: none;
45
- color: #e5e7eb;
46
- }
47
-
48
- .prose code {
49
- color: #e5e7eb;
50
- background-color: rgba(31, 41, 55, 0.5);
51
- padding: 0.2em 0.4em;
52
- border-radius: 0.375rem;
53
- font-size: 0.875em;
54
- }
55
-
56
- .prose pre {
57
- background-color: rgba(31, 41, 55, 0.5);
58
- border-radius: 0.5rem;
59
- padding: 1rem;
60
- margin: 1.25em 0;
61
- overflow-x: auto;
62
- }
63
-
64
- .prose pre code {
65
- background-color: transparent;
66
- padding: 0;
67
- border-radius: 0;
68
- color: inherit;
69
- }
70
-
71
- .prose h1,
72
- .prose h2,
73
- .prose h3,
74
- .prose h4 {
75
- color: #f9fafb;
76
- }
77
-
78
- .prose ul,
79
- .prose ol {
80
- margin-top: 1.25em;
81
- margin-bottom: 1.25em;
82
- padding-left: 1.625em;
83
- }
84
-
85
- .prose li {
86
- margin-top: 0.5em;
87
- margin-bottom: 0.5em;
88
- }
89
-
90
- .prose blockquote {
91
- border-left-color: #f97316;
92
- background-color: rgba(249, 115, 22, 0.1);
93
- padding: 1em;
94
- margin: 1.25em 0;
95
- border-radius: 0.5rem;
96
- }
97
-
98
- .prose hr {
99
- border-color: rgba(249, 115, 22, 0.2);
100
- margin: 2em 0;
101
- }
102
-
103
- .prose a {
104
- color: #f97316;
105
- text-decoration: underline;
106
- text-decoration-thickness: 0.1em;
107
- text-underline-offset: 0.2em;
108
- }
109
-
110
- .prose a:hover {
111
- color: #fb923c;
112
- }
113
-
114
- .prose table {
115
- width: 100%;
116
- border-collapse: collapse;
117
- margin: 1.25em 0;
118
- }
119
-
120
- .prose th,
121
- .prose td {
122
- padding: 0.75em;
123
- border: 1px solid rgba(249, 115, 22, 0.2);
124
- }
125
-
126
- .prose th {
127
- background-color: rgba(249, 115, 22, 0.1);
128
- font-weight: 600;
129
- }
130
-
131
- .prose h1 {
132
- font-size: 2em;
133
- margin-bottom: 0.5em;
134
- }
135
-
136
- .prose h2 {
137
- font-size: 1.5em;
138
- margin-top: 1em;
139
- margin-bottom: 0.5em;
140
- }
141
-
142
- .prose h3 {
143
- font-size: 1.25em;
144
- margin-top: 1em;
145
- margin-bottom: 0.5em;
146
- }
147
-
148
- .prose ul {
149
- list-style-type: disc;
150
- padding-left: 1.5em;
151
- }
152
-
153
- .prose ol {
154
- list-style-type: decimal;
155
- padding-left: 1.5em;
156
- }
157
-
158
- .prose strong {
159
- color: #f9fafb;
160
- font-weight: 600;
161
- }
162
-
163
- .prose em {
164
- font-style: italic;
165
- }
@@ -1,25 +0,0 @@
1
- {
2
- "name": "AI Chat",
3
- "description": "A weather chat assistant powered by TanStack AI with multi-provider support for Netlify.",
4
- "phase": "example",
5
- "modes": ["file-router"],
6
- "type": "example",
7
- "priority": 10,
8
- "link": "",
9
- "routes": [
10
- {"url": "/", "path": "src/routes/index.tsx", "jsName": "Home"},
11
- {"url": "/api/chat", "path": "src/routes/api.chat.ts", "jsName": "ChatAPI"}
12
- ],
13
- "features": ["tanstack-start", "tanstack-ai"],
14
- "integrations": [],
15
- "dependsOn": [],
16
- "variables": [],
17
- "packageFileDescriptions": {
18
- "src/styles.css": "Global styles: Tailwind, highlight.js theme, custom scrollbar, prose/markdown styles for chat UI.",
19
- "src/lib/weather-tools.ts": "TanStack AI tool definition for getWeather; server implementation returns mock temperature, condition, humidity for a city.",
20
- "src/lib/ai-hook.ts": "useAIChat hook: useChat with fetchServerSentEvents connection to /api/chat.",
21
- "src/routes/api.chat.ts": "POST handler for /api/chat: multi-provider AI (Anthropic, OpenAI, Gemini, Ollama) with getWeather tool and SSE streaming.",
22
- "src/routes/index.tsx": "Home route: Weather Chat UI with messages list, input form, send/stop, Streamdown markdown rendering.",
23
- "src/routes/__root.tsx": "Root layout: HTML shell, Weather Chat header, styles, TanStack Devtools."
24
- }
25
- }
@@ -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-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
- "highlight.js": "^11.11.1",
11
- "streamdown": "^2.1.0",
12
- "zod": "^4.3.5"
13
- }
14
- }
@@ -1,60 +0,0 @@
1
- # Blog Example
2
-
3
- A Hawaii adventures travel blog built with TanStack Start and content-collections for Netlify deployment.
4
-
5
- ## Features
6
-
7
- - **Content Collections**: Blog posts managed as markdown files with frontmatter
8
- - **Category Navigation**: Filter posts by category (Relaxing, Hiking)
9
- - **Beautiful UI**: Postcard-style blog cards with shadcn/ui components
10
- - **SSR Ready**: Full server-side rendering with TanStack Start
11
-
12
- ## Project Structure
13
-
14
- ```
15
- ├── content/
16
- │ └── posts/ # Markdown blog posts
17
- ├── src/
18
- │ ├── components/
19
- │ │ ├── blog-posts.tsx # Blog post grid
20
- │ │ ├── Header.tsx # Navigation header
21
- │ │ └── ui/
22
- │ │ └── card.tsx # Shadcn card component
23
- │ ├── lib/
24
- │ │ └── utils.ts # Utility functions
25
- │ └── routes/
26
- │ ├── __root.tsx # Root layout
27
- │ ├── index.tsx # Home page
28
- │ ├── posts.$slug.tsx # Individual post
29
- │ └── category.$category.tsx # Category filter
30
- └── public/
31
- └── *.jpg # Blog images
32
- ```
33
-
34
- ## Adding Blog Posts
35
-
36
- Create a new markdown file in `content/posts/` with the following frontmatter:
37
-
38
- ```markdown
39
- ---
40
- date: 2025-03-01
41
- title: "Your Post Title"
42
- summary: "A brief summary of your post"
43
- categories:
44
- - Category1
45
- - Category2
46
- image: your-image.jpg
47
- ---
48
-
49
- Your post content 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
- ```
@@ -1,18 +0,0 @@
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).
@@ -1,12 +0,0 @@
1
- ---
2
- date: 2025-03-01
3
- title: "Day At The Beach"
4
- summary: "Had a great day at the beach in Hawaii"
5
- categories:
6
- - Relaxing
7
- image: beach.jpg
8
- ---
9
-
10
- The morning sun painted the ocean in shimmering gold as I paddled out beyond the break, my surfboard gliding smoothly through the crystal-clear Hawaiian waters. The waves were perfect today - clean, consistent sets rolling in with just enough power to make things interesting without being intimidating. After catching several exhilarating rides, each one lasting what felt like an eternity, I found myself grinning from ear to ear, salt water dripping from my hair, and feeling completely in tune with the rhythm of the ocean.
11
-
12
- After my surf session, I found the perfect spot on the warm sand to soak in the midday sun. The gentle trade winds carried the sweet scent of plumeria, while palm trees swayed overhead providing occasional patches of shade. I alternated between reading my book, taking refreshing dips in the turquoise water, and simply watching the parade of beach life unfold around me - children building sandcastles, paddleboarders gliding by in the distance, and sea turtles occasionally popping their heads above the surface. It was one of those perfect Hawaiian days that remind you why these islands are called paradise.
@@ -1,12 +0,0 @@
1
- <% if (addOnOption.project?.bareBones) { ignoreFile() } %>---
2
- date: 2025-03-02
3
- title: "Hiking The Jungle"
4
- summary: "Picking our way through the jungle in Hawaii"
5
- categories:
6
- - Hiking
7
- image: jungle.jpg
8
- ---
9
-
10
- The ascent through the Hawaiian jungle was a feast for the senses. Massive tree ferns unfurled their prehistoric fronds overhead, creating a living canopy that filtered the morning sunlight into ethereal green beams. The air was thick with humidity and alive with sound – the melodic calls of 'apapane birds echoed through the forest, while the distinctive cry of the 'i'iwi punctuated the constant background chorus of buzzing insects and rustling leaves.
11
-
12
- As we picked our way along the narrow trail, each step carefully placed on the rain-slicked earth, the dense jungle gradually began to thin. Through gaps in the vegetation, tantalizing glimpses of the valley below emerged, hinting at the spectacular vista that awaited us at the summit. The sweet scent of wild ginger mingled with the earthy aroma of damp soil, while delicate 'ōhi'a lehua blossoms dotted the path with splashes of crimson, their presence a hopeful sign of the forest's resilience against environmental challenges.
@@ -1,12 +0,0 @@
1
- <% if (addOnOption.project?.bareBones) { ignoreFile() } %>---
2
- date: 2025-03-02
3
- title: "Mountain Tops"
4
- summary: "Ending our hike with mountain views"
5
- categories:
6
- - Hiking
7
- image: mountains.jpg
8
- ---
9
-
10
- The day's journey took an unexpected turn when we stumbled upon a hidden waterfall cascading down moss-covered rocks. The thundering sound of water drew us off our planned trail, and we spent a magical hour exploring the crystal-clear pool at its base, watching rainbow-like mist dance in the afternoon sun. What started as a simple jungle trek transformed into an adventure of discovery, with exotic birds calling from the canopy above and vibrant butterflies fluttering between patches of filtered sunlight.
11
-
12
- As dusk approached, we finally reached the summit, where jagged peaks pierced through a sea of clouds stretching endlessly toward the horizon. However, our triumph was short-lived as we realized we'd need to navigate the descent in fading light. Armed with only two headlamps between the four of us, we carefully picked our way down the rocky trail, our hearts racing with each uncertain step. The stars emerged one by one above us, and the distant lights of our hotel served as a welcome beacon, guiding us safely back just as true darkness settled over the mountains.
@@ -1,12 +0,0 @@
1
- <% if (addOnOption.project?.bareBones) { ignoreFile() } %>---
2
- date: 2025-03-01
3
- title: "Snorkeling"
4
- summary: "Snorkling with the fish in Hawaii"
5
- categories:
6
- - Relaxing
7
- image: snorkeling.jpg
8
- ---
9
-
10
- As I glided through the crystal-clear waters off the Hawaiian coast, I found myself immersed in an underwater paradise. The warm Pacific waters, hovering around 80 degrees Fahrenheit, embraced me like a gentle blanket while visibility extended for what seemed like eternity. Each gentle wave brought new wonders into view, with sunlight dancing through the water creating mesmerizing patterns on the sandy ocean floor below.
11
-
12
- The vibrant marine life was absolutely breathtaking, with schools of yellow tang darting between clusters of coral and parrotfish methodically grazing on the reef. Brilliant butterfly fish, their distinctive patterns catching the sunlight, swam fearlessly past my mask, while iridescent humuhumunukunukuapua'a (Hawaii's state fish) investigated my presence with curious eyes. In every direction, the coral reefs teemed with life, creating a natural aquarium that made me feel like a privileged guest in this underwater world.
@@ -1,12 +0,0 @@
1
- <% if (addOnOption.project?.bareBones) { ignoreFile() } %>---
2
- date: 2025-03-02
3
- title: "Waterfall Surprise"
4
- summary: "We weren't expecting this waterfall in Hawaii"
5
- categories:
6
- - Hiking
7
- image: waterfall.jpg
8
- ---
9
-
10
- As we made our way through the dense Hawaiian rainforest, the humid air clung to our skin and the chirping of native birds provided a natural symphony to our adventure. The trail had been relatively straightforward, winding through groves of towering bamboo and past ancient lava flows, but nothing prepared us for what lay around the final bend. The sound hit us first - a distant rushing that grew louder with each step, until we emerged into a hidden grotto where a magnificent waterfall cascaded down moss-covered volcanic rocks.
11
-
12
- The secluded waterfall, easily sixty feet tall, created its own microclimate of cool mist and swirling breezes. Crystal clear water plunged into a pristine pool below, surrounded by delicate ferns and vibrant tropical flowers that seemed to thrive in this hidden paradise. We hadn't seen this waterfall mentioned in any of our guidebooks or trail maps, which made the discovery even more special. Standing there, with water droplets dancing in the filtered sunlight, we felt like we had stumbled upon one of Hawaii's best-kept secrets.
@@ -1,30 +0,0 @@
1
- import { defineCollection, defineConfig } from '@content-collections/core'
2
- import { z } from 'zod'
3
-
4
- const posts = defineCollection({
5
- name: 'posts',
6
- directory: 'content/posts',
7
- include: '**/*.md',
8
- schema: z.object({
9
- title: z.string(),
10
- summary: z.string(),
11
- categories: z.array(z.string()),
12
- slug: z.string().optional(),
13
- image: z.string(),
14
- date: z.string(),
15
- content: z.string(),
16
- }),
17
- transform: async (doc) => {
18
- return {
19
- ...doc,
20
- slug: doc.title
21
- .toLowerCase()
22
- .replace('.md', '')
23
- .replace(/[^\w-]+/g, '_'),
24
- }
25
- },
26
- })
27
-
28
- export default defineConfig({
29
- collections: [posts],
30
- })