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,372 +0,0 @@
1
- ---
2
- name: netlify-functions
3
- description: Create and deploy Netlify serverless functions and edge functions. Use when implementing API endpoints, server-side logic, background jobs, scheduled tasks, or edge computing on Netlify.
4
- license: Apache-2.0
5
- metadata:
6
- author: netlify
7
- version: "1.0"
8
- ---
9
-
10
- # Netlify Functions
11
-
12
- Netlify Functions are serverless functions that run on-demand without managing servers. They support JavaScript, TypeScript, and Go.
13
-
14
- ## When to Use
15
-
16
- - API endpoints for your frontend
17
- - Server-side data processing
18
- - Third-party API integrations (hiding API keys)
19
- - Background/async processing
20
- - Scheduled jobs (cron-like)
21
- - Edge computing (low-latency responses)
22
-
23
- ## Directory Structure
24
-
25
- ```
26
- project/
27
- ├── netlify/
28
- │ └── functions/
29
- │ ├── hello.ts # → /.netlify/functions/hello
30
- │ ├── api/
31
- │ │ └── users.ts # → /.netlify/functions/api-users
32
- │ └── process-background.ts # Background function
33
- │ └── edge-functions/
34
- │ └── geo.ts # Edge function
35
- ├── netlify.toml
36
- └── package.json
37
- ```
38
-
39
- ## Basic Serverless Function (TypeScript)
40
-
41
- ```typescript
42
- // netlify/functions/hello.ts
43
- import type { Context } from "@netlify/functions";
44
-
45
- export default async (request: Request, context: Context) => {
46
- const { name = "World" } = await request.json().catch(() => ({}));
47
-
48
- return new Response(JSON.stringify({ message: `Hello, ${name}!` }), {
49
- status: 200,
50
- headers: { "Content-Type": "application/json" },
51
- });
52
- };
53
- ```
54
-
55
- ## Function with Path Parameters
56
-
57
- ```typescript
58
- // netlify/functions/users.ts
59
- import type { Context } from "@netlify/functions";
60
-
61
- export default async (request: Request, context: Context) => {
62
- const { id } = context.params; // From path like /api/users/:id
63
-
64
- // Fetch user from database
65
- const user = await getUser(id);
66
-
67
- if (!user) {
68
- return new Response(JSON.stringify({ error: "User not found" }), {
69
- status: 404,
70
- headers: { "Content-Type": "application/json" },
71
- });
72
- }
73
-
74
- return Response.json(user);
75
- };
76
-
77
- // Configure custom path in the function
78
- export const config = {
79
- path: "/api/users/:id",
80
- };
81
- ```
82
-
83
- ## Handling Different HTTP Methods
84
-
85
- ```typescript
86
- // netlify/functions/items.ts
87
- import type { Context } from "@netlify/functions";
88
-
89
- export default async (request: Request, context: Context) => {
90
- const { method } = request;
91
-
92
- switch (method) {
93
- case "GET":
94
- return handleGet(request, context);
95
- case "POST":
96
- return handlePost(request, context);
97
- case "PUT":
98
- return handlePut(request, context);
99
- case "DELETE":
100
- return handleDelete(request, context);
101
- default:
102
- return new Response("Method not allowed", { status: 405 });
103
- }
104
- };
105
-
106
- async function handleGet(request: Request, context: Context) {
107
- const items = await fetchItems();
108
- return Response.json(items);
109
- }
110
-
111
- async function handlePost(request: Request, context: Context) {
112
- const body = await request.json();
113
- const newItem = await createItem(body);
114
- return Response.json(newItem, { status: 201 });
115
- }
116
- ```
117
-
118
- ## Environment Variables
119
-
120
- Access environment variables via `process.env`:
121
-
122
- ```typescript
123
- // netlify/functions/api.ts
124
- export default async (request: Request, context: Context) => {
125
- const apiKey = process.env.API_KEY;
126
-
127
- if (!apiKey) {
128
- return new Response("API key not configured", { status: 500 });
129
- }
130
-
131
- const response = await fetch("https://api.example.com/data", {
132
- headers: { Authorization: `Bearer ${apiKey}` },
133
- });
134
-
135
- return Response.json(await response.json());
136
- };
137
- ```
138
-
139
- Set environment variables in Netlify UI or `netlify.toml`:
140
-
141
- ```toml
142
- # netlify.toml
143
- [build.environment]
144
- API_KEY = "your-api-key" # Better to set in Netlify UI for secrets
145
- ```
146
-
147
- ## Background Functions
148
-
149
- For long-running tasks (up to 15 minutes), use background functions:
150
-
151
- ```typescript
152
- // netlify/functions/process-background.ts
153
- // Name MUST end with `-background`
154
- import type { Context } from "@netlify/functions";
155
-
156
- export default async (request: Request, context: Context) => {
157
- const data = await request.json();
158
-
159
- // Long-running task - client gets 202 immediately
160
- await processLargeDataset(data);
161
-
162
- // Response is ignored for background functions
163
- // Client always receives 202 Accepted immediately
164
- };
165
- ```
166
-
167
- **Naming**: File must be named `*-background.ts` (e.g., `process-background.ts`)
168
-
169
- ## Scheduled Functions
170
-
171
- Run functions on a schedule (cron):
172
-
173
- ```typescript
174
- // netlify/functions/daily-cleanup.ts
175
- import type { Config } from "@netlify/functions";
176
-
177
- export default async () => {
178
- await cleanupOldRecords();
179
- console.log("Cleanup completed");
180
- };
181
-
182
- export const config: Config = {
183
- schedule: "0 0 * * *", // Run daily at midnight UTC
184
- };
185
- ```
186
-
187
- Common cron patterns:
188
- - `"0 * * * *"` - Every hour
189
- - `"0 0 * * *"` - Daily at midnight
190
- - `"0 0 * * 0"` - Weekly on Sunday
191
- - `"*/5 * * * *"` - Every 5 minutes
192
-
193
- ## Edge Functions
194
-
195
- Edge functions run closer to users for ultra-low latency:
196
-
197
- ```typescript
198
- // netlify/edge-functions/geo.ts
199
- import type { Context } from "@netlify/edge-functions";
200
-
201
- export default async (request: Request, context: Context) => {
202
- const { country, city } = context.geo;
203
-
204
- return new Response(JSON.stringify({
205
- message: `Hello from ${city}, ${country}!`,
206
- timestamp: new Date().toISOString(),
207
- }), {
208
- headers: { "Content-Type": "application/json" },
209
- });
210
- };
211
-
212
- export const config = {
213
- path: "/api/location",
214
- };
215
- ```
216
-
217
- Configure in `netlify.toml`:
218
-
219
- ```toml
220
- [[edge_functions]]
221
- function = "geo"
222
- path = "/api/location"
223
- ```
224
-
225
- ## Edge Function vs Serverless Function
226
-
227
- | Feature | Serverless | Edge |
228
- |---------|-----------|------|
229
- | Location | Single region | Global edge |
230
- | Timeout | 10s (26s on paid) | 50ms |
231
- | Cold start | Can be slow | Very fast |
232
- | Use case | Heavy computation | Low-latency responses |
233
- | Middleware | No | Yes |
234
-
235
- ## Context Object Properties
236
-
237
- ```typescript
238
- export default async (request: Request, context: Context) => {
239
- // Request info
240
- context.ip; // Client IP address
241
- context.geo.city; // Geo location
242
- context.geo.country.code; // Country code
243
- context.geo.subdivision.code; // State/region
244
-
245
- // Deploy info
246
- context.site.id; // Site ID
247
- context.deploy.id; // Deploy ID
248
- context.deploy.published; // Is this the published deploy?
249
-
250
- // Function info
251
- context.requestId; // Unique request ID
252
- context.params; // URL path parameters
253
-
254
- // Cookies
255
- context.cookies.get("session");
256
- context.cookies.set({ name: "session", value: "abc123" });
257
-
258
- // Environment
259
- context.env.get("API_KEY");
260
- };
261
- ```
262
-
263
- ## CORS Configuration
264
-
265
- ```typescript
266
- // netlify/functions/api.ts
267
- const headers = {
268
- "Access-Control-Allow-Origin": "*",
269
- "Access-Control-Allow-Headers": "Content-Type",
270
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
271
- };
272
-
273
- export default async (request: Request, context: Context) => {
274
- // Handle preflight
275
- if (request.method === "OPTIONS") {
276
- return new Response(null, { status: 204, headers });
277
- }
278
-
279
- // Your logic here
280
- const data = { message: "Hello" };
281
-
282
- return new Response(JSON.stringify(data), {
283
- status: 200,
284
- headers: { ...headers, "Content-Type": "application/json" },
285
- });
286
- };
287
- ```
288
-
289
- ## netlify.toml Configuration
290
-
291
- ```toml
292
- [build]
293
- functions = "netlify/functions"
294
-
295
- [functions]
296
- # Set default Node.js version
297
- node_bundler = "esbuild"
298
-
299
- # Include files in function bundle
300
- included_files = ["data/**"]
301
-
302
- # Function-specific settings
303
- [functions."api-*"]
304
- # Increase memory for API functions
305
- memory = 1024
306
-
307
- # Edge function declarations
308
- [[edge_functions]]
309
- function = "auth"
310
- path = "/dashboard/*"
311
- ```
312
-
313
- ## Local Development
314
-
315
- ```bash
316
- # Install Netlify CLI
317
- npm install -g netlify-cli
318
-
319
- # Run locally with functions
320
- netlify dev
321
-
322
- # Functions available at http://localhost:8888/.netlify/functions/
323
- ```
324
-
325
- ## Common Patterns
326
-
327
- ### Database Connection
328
-
329
- ```typescript
330
- // netlify/functions/db.ts
331
- import { neon } from "@neondatabase/serverless";
332
-
333
- const sql = neon(process.env.DATABASE_URL!);
334
-
335
- export default async (request: Request) => {
336
- const users = await sql`SELECT * FROM users LIMIT 10`;
337
- return Response.json(users);
338
- };
339
- ```
340
-
341
- ### Rate Limiting with Blobs
342
-
343
- ```typescript
344
- import { getStore } from "@netlify/blobs";
345
-
346
- export default async (request: Request, context: Context) => {
347
- const store = getStore("rate-limits");
348
- const ip = context.ip;
349
-
350
- const current = await store.get(ip, { type: "json" }) as { count: number; reset: number } | null;
351
- const now = Date.now();
352
-
353
- if (current && current.reset > now && current.count >= 100) {
354
- return new Response("Rate limit exceeded", { status: 429 });
355
- }
356
-
357
- await store.setJSON(ip, {
358
- count: (current?.count || 0) + 1,
359
- reset: current?.reset > now ? current.reset : now + 60000,
360
- });
361
-
362
- // Continue with request...
363
- };
364
- ```
365
-
366
- ## Limits
367
-
368
- - **Serverless functions**: 10 second timeout (26s on paid plans)
369
- - **Background functions**: 15 minute timeout
370
- - **Edge functions**: 50ms CPU time
371
- - **Payload size**: 6MB request/response
372
- - **Memory**: 1024MB default (configurable)