@nextsparkjs/ai-workflow 0.1.0-beta.86

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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +636 -0
  5. package/claude/agents/architecture-supervisor.md +1381 -0
  6. package/claude/agents/backend-developer.md +1021 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1460 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1291 -0
  15. package/claude/agents/frontend-developer.md +1259 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +971 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +373 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +681 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +512 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +455 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/close.md +146 -0
  77. package/claude/commands/session/commit.md +174 -0
  78. package/claude/commands/session/db-entity.md +206 -0
  79. package/claude/commands/session/db-fix.md +212 -0
  80. package/claude/commands/session/db-sample.md +206 -0
  81. package/claude/commands/session/demo.md +178 -0
  82. package/claude/commands/session/doc-bdd.md +207 -0
  83. package/claude/commands/session/doc-feature.md +218 -0
  84. package/claude/commands/session/doc-read.md +225 -0
  85. package/claude/commands/session/execute.md +204 -0
  86. package/claude/commands/session/explain.md +202 -0
  87. package/claude/commands/session/fix-bug.md +210 -0
  88. package/claude/commands/session/fix-build.md +182 -0
  89. package/claude/commands/session/fix-test.md +189 -0
  90. package/claude/commands/session/pending.md +232 -0
  91. package/claude/commands/session/refine.md +188 -0
  92. package/claude/commands/session/resume.md +192 -0
  93. package/claude/commands/session/review.md +192 -0
  94. package/claude/commands/session/scope-change.md +181 -0
  95. package/claude/commands/session/start-blocks.md +347 -0
  96. package/claude/commands/session/start.md +476 -0
  97. package/claude/commands/session/status.md +169 -0
  98. package/claude/commands/session/test-fix.md +221 -0
  99. package/claude/commands/session/test-run.md +203 -0
  100. package/claude/commands/session/test-write.md +242 -0
  101. package/claude/commands/session/validate.md +162 -0
  102. package/claude/config/context.json +54 -0
  103. package/claude/config/github.json +69 -0
  104. package/claude/config/github.schema.json +106 -0
  105. package/claude/config/team.json +46 -0
  106. package/claude/config/team.schema.json +106 -0
  107. package/claude/config/workspace.json +49 -0
  108. package/claude/config/workspace.schema.json +64 -0
  109. package/claude/scripts/.gitkeep +0 -0
  110. package/claude/sessions/.gitkeep +0 -0
  111. package/claude/skills/README.md +228 -0
  112. package/claude/skills/accessibility/SKILL.md +573 -0
  113. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  114. package/claude/skills/asana-integration/SKILL.md +499 -0
  115. package/claude/skills/better-auth/SKILL.md +666 -0
  116. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  117. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  118. package/claude/skills/clickup-integration/SKILL.md +434 -0
  119. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  120. package/claude/skills/create-plugin/SKILL.md +425 -0
  121. package/claude/skills/create-theme/SKILL.md +331 -0
  122. package/claude/skills/cypress-api/SKILL.md +511 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  124. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  125. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  126. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  127. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  128. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  129. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  130. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  131. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  132. package/claude/skills/database-migrations/SKILL.md +335 -0
  133. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  134. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  135. package/claude/skills/design-system/SKILL.md +682 -0
  136. package/claude/skills/documentation/SKILL.md +540 -0
  137. package/claude/skills/entity-api/SKILL.md +482 -0
  138. package/claude/skills/entity-system/SKILL.md +635 -0
  139. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  140. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  141. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  142. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  143. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  144. package/claude/skills/github/SKILL.md +467 -0
  145. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  146. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  147. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  148. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  149. package/claude/skills/impact-analysis/SKILL.md +203 -0
  150. package/claude/skills/jest-unit/SKILL.md +306 -0
  151. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  152. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  153. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  154. package/claude/skills/jira-integration/SKILL.md +539 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +483 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +677 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +431 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +479 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +34 -0
  270. package/scripts/setup.mjs +282 -0
  271. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,681 @@
1
+ # /how-to:handle-file-uploads
2
+
3
+ Interactive guide to implement file uploads and media management in NextSpark.
4
+
5
+ **Aliases:** `/how-to:media`, `/how-to:file-upload`
6
+
7
+ ---
8
+
9
+ ## Required Skills
10
+
11
+ Before executing, these skills provide deeper context:
12
+ - `.claude/skills/entity-system/SKILL.md` - Entity field definitions
13
+ - `.claude/skills/zod-validation/SKILL.md` - Input validation patterns
14
+
15
+ ---
16
+
17
+ ## Syntax
18
+
19
+ ```
20
+ /how-to:handle-file-uploads
21
+ /how-to:handle-file-uploads --component image
22
+ /how-to:handle-file-uploads --entity
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Behavior
28
+
29
+ Guides the user through implementing file uploads, using upload components, and adding file fields to entities.
30
+
31
+ ---
32
+
33
+ ## Tutorial Structure
34
+
35
+ ```
36
+ STEPS OVERVIEW (5 steps)
37
+
38
+ Step 1: Understanding the Media System
39
+ └── Vercel Blob, supported types, limits
40
+
41
+ Step 2: Configure Environment
42
+ └── BLOB_READ_WRITE_TOKEN setup
43
+
44
+ Step 3: Using Upload Components
45
+ └── FileUpload, ImageUpload, VideoUpload, AudioUpload
46
+
47
+ Step 4: Adding File Fields to Entities
48
+ └── Entity field types and configuration
49
+
50
+ Step 5: Custom Upload Handling
51
+ └── API endpoint, permissions, advanced usage
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Step 1: Understanding the Media System
57
+
58
+ ```
59
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
60
+ 📚 HOW TO: HANDLE FILE UPLOADS
61
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
62
+
63
+ STEP 1 OF 5: Understanding the Media System
64
+
65
+ NextSpark uses Vercel Blob for cloud file storage
66
+ with specialized components for different media types.
67
+
68
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
69
+ ```
70
+
71
+ **📋 Storage Architecture:**
72
+
73
+ ```
74
+ ┌─────────────────────────────────────────────┐
75
+ │ VERCEL BLOB STORAGE │
76
+ │ ───────────────────────────────────────── │
77
+ │ • Cloud-based file storage │
78
+ │ • Public URLs for uploaded files │
79
+ │ • Automatic CDN distribution │
80
+ │ • No server storage required │
81
+ └─────────────────────────────────────────────┘
82
+ ```
83
+
84
+ **📋 Supported File Types:**
85
+
86
+ | Category | MIME Types | Extensions |
87
+ |----------|------------|------------|
88
+ | Images | image/jpeg, image/png, image/gif, image/webp | .jpg, .png, .gif, .webp |
89
+ | Videos | video/mp4, video/mpeg, video/quicktime, video/webm | .mp4, .mpeg, .mov, .webm |
90
+ | Audio | audio/mpeg, audio/wav, audio/ogg, audio/m4a | .mp3, .wav, .ogg, .m4a |
91
+ | Files | Any | Any (configurable) |
92
+
93
+ **📋 Limits:**
94
+
95
+ | Limit | Value |
96
+ |-------|-------|
97
+ | Max file size | 10 MB per file |
98
+ | Max files per upload | 5 files (configurable) |
99
+ | Storage path | `uploads/temp/{timestamp}_{random}.{ext}` |
100
+
101
+ **📋 Available Components:**
102
+
103
+ ```
104
+ packages/core/src/components/ui/
105
+ ├── file-upload.tsx # Generic file upload
106
+ ├── image-upload.tsx # Image-specific with preview
107
+ ├── video-upload.tsx # Video with thumbnail generation
108
+ └── audio-upload.tsx # Audio with built-in player
109
+ ```
110
+
111
+ ```
112
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
113
+
114
+ What would you like to do?
115
+
116
+ [1] Continue to Step 2 (Configure Environment)
117
+ [2] Can I use S3 or Cloudinary instead?
118
+ [3] What are the storage costs?
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Step 2: Configure Environment
124
+
125
+ ```
126
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
127
+ STEP 2 OF 5: Configure Environment
128
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
129
+
130
+ Set up Vercel Blob storage for your project.
131
+ ```
132
+
133
+ **📋 Required Environment Variables:**
134
+
135
+ ```bash
136
+ # .env or .env.local
137
+
138
+ # Vercel Blob Storage Token (REQUIRED)
139
+ BLOB_READ_WRITE_TOKEN=vercel_blob_rw_xxxxxxxxxxxxx
140
+ ```
141
+
142
+ **📋 Getting a Blob Token:**
143
+
144
+ 1. Go to your Vercel project dashboard
145
+ 2. Navigate to **Storage** tab
146
+ 3. Create a new **Blob** store
147
+ 4. Copy the `BLOB_READ_WRITE_TOKEN`
148
+ 5. Add to your `.env.local` file
149
+
150
+ **📋 Local Development:**
151
+
152
+ For local development, you still need a Vercel Blob token. The files are stored in Vercel's cloud even during development.
153
+
154
+ ```bash
155
+ # Verify your token is set
156
+ echo $BLOB_READ_WRITE_TOKEN
157
+ ```
158
+
159
+ **📋 Package Dependencies:**
160
+
161
+ The required package is already included:
162
+
163
+ ```json
164
+ {
165
+ "@vercel/blob": "^2.0.0"
166
+ }
167
+ ```
168
+
169
+ ```
170
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
171
+
172
+ What would you like to do?
173
+
174
+ [1] Continue to Step 3 (Upload Components)
175
+ [2] I don't use Vercel, what are my options?
176
+ [3] How do I test without a token?
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Step 3: Using Upload Components
182
+
183
+ ```
184
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
185
+ STEP 3 OF 5: Using Upload Components
186
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
187
+
188
+ NextSpark provides specialized components for
189
+ different media types.
190
+ ```
191
+
192
+ **📋 1. FileUpload (Generic):**
193
+
194
+ ```typescript
195
+ import { FileUpload } from '@/core/components/ui/file-upload'
196
+
197
+ interface FileUploadProps {
198
+ value: UploadedFile[]
199
+ onChange: (files: UploadedFile[]) => void
200
+ maxFiles?: number // Default: 5
201
+ maxSize?: number // MB, Default: 10
202
+ acceptedTypes?: string[] // Default: ["*"]
203
+ disabled?: boolean
204
+ multiple?: boolean // Default: true
205
+ dragDrop?: boolean // Default: true
206
+ }
207
+
208
+ // Usage
209
+ <FileUpload
210
+ value={files}
211
+ onChange={setFiles}
212
+ maxFiles={3}
213
+ maxSize={5}
214
+ acceptedTypes={['application/pdf', 'text/*']}
215
+ />
216
+ ```
217
+
218
+ **📋 2. ImageUpload (Images with Preview):**
219
+
220
+ ```typescript
221
+ import { ImageUpload } from '@/core/components/ui/image-upload'
222
+
223
+ interface ImageUploadProps {
224
+ value: UploadedImage[]
225
+ onChange: (images: UploadedImage[]) => void
226
+ maxImages?: number // Default: 5
227
+ maxSize?: number // MB, Default: 5
228
+ aspectRatio?: 'square' | 'landscape' | 'portrait' | 'free'
229
+ showPreview?: boolean // Default: true
230
+ multiple?: boolean
231
+ }
232
+
233
+ // Usage
234
+ <ImageUpload
235
+ value={images}
236
+ onChange={setImages}
237
+ maxImages={1}
238
+ aspectRatio="square"
239
+ />
240
+ ```
241
+
242
+ **📋 3. VideoUpload (Videos with Thumbnails):**
243
+
244
+ ```typescript
245
+ import { VideoUpload } from '@/core/components/ui/video-upload'
246
+
247
+ interface VideoUploadProps {
248
+ value: UploadedVideo[]
249
+ onChange: (videos: UploadedVideo[]) => void
250
+ maxVideos?: number // Default: 3
251
+ maxSize?: number // MB, Default: 100
252
+ acceptedFormats?: string[] // Default: ["mp4", "mov", "avi", "mkv", "webm"]
253
+ }
254
+
255
+ // Usage - auto-generates thumbnails!
256
+ <VideoUpload
257
+ value={videos}
258
+ onChange={setVideos}
259
+ maxVideos={1}
260
+ maxSize={50}
261
+ />
262
+ ```
263
+
264
+ **📋 4. AudioUpload (Audio with Player):**
265
+
266
+ ```typescript
267
+ import { AudioUpload } from '@/core/components/ui/audio-upload'
268
+
269
+ interface AudioUploadProps {
270
+ value: UploadedAudio[]
271
+ onChange: (audios: UploadedAudio[]) => void
272
+ maxAudios?: number // Default: 5
273
+ maxSize?: number // MB, Default: 50
274
+ acceptedFormats?: string[] // Default: ["mp3", "wav", "ogg", "m4a", "aac"]
275
+ showPlayer?: boolean // Default: true
276
+ }
277
+
278
+ // Usage - includes built-in audio player!
279
+ <AudioUpload
280
+ value={audioFiles}
281
+ onChange={setAudioFiles}
282
+ showPlayer={true}
283
+ />
284
+ ```
285
+
286
+ **📋 Uploaded File Types:**
287
+
288
+ ```typescript
289
+ interface UploadedFile {
290
+ id: string
291
+ name: string
292
+ size: number
293
+ type: string
294
+ url?: string
295
+ uploadProgress?: number
296
+ }
297
+
298
+ interface UploadedImage extends UploadedFile {
299
+ alt?: string
300
+ width?: number
301
+ height?: number
302
+ }
303
+
304
+ interface UploadedVideo extends UploadedFile {
305
+ duration?: number
306
+ thumbnail?: string // Auto-generated
307
+ }
308
+
309
+ interface UploadedAudio extends UploadedFile {
310
+ duration?: number
311
+ }
312
+ ```
313
+
314
+ ```
315
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
316
+
317
+ What would you like to do?
318
+
319
+ [1] Continue to Step 4 (Entity Fields)
320
+ [2] Show me a complete form example
321
+ [3] How do I customize the upload UI?
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Step 4: Adding File Fields to Entities
327
+
328
+ ```
329
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
330
+ STEP 4 OF 5: Adding File Fields to Entities
331
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
332
+
333
+ Add file fields to your entities for automatic
334
+ form and display handling.
335
+ ```
336
+
337
+ **📋 Available Field Types:**
338
+
339
+ | Type | Component | Use Case |
340
+ |------|-----------|----------|
341
+ | `file` | FileUpload | Documents, PDFs, any files |
342
+ | `image` | ImageUpload | Photos, avatars, graphics |
343
+ | `video` | VideoUpload | Video content |
344
+ | `audio` | AudioUpload | Audio files, podcasts |
345
+
346
+ **📋 Entity Field Definition:**
347
+
348
+ ```typescript
349
+ // In your entity.fields.ts
350
+
351
+ // Image field example
352
+ {
353
+ name: 'featuredImage',
354
+ type: 'image',
355
+ required: false,
356
+ display: {
357
+ label: 'Featured Image',
358
+ description: 'Main image for the post',
359
+ placeholder: 'Upload an image...',
360
+ showInList: false, // Hide in table (shows count)
361
+ showInDetail: true,
362
+ showInForm: true,
363
+ order: 5,
364
+ },
365
+ api: {
366
+ searchable: false,
367
+ sortable: false,
368
+ readOnly: false,
369
+ },
370
+ }
371
+
372
+ // File attachments example
373
+ {
374
+ name: 'attachments',
375
+ type: 'file',
376
+ required: false,
377
+ display: {
378
+ label: 'Attachments',
379
+ description: 'Upload project files (max 5)',
380
+ showInList: false,
381
+ showInDetail: true,
382
+ showInForm: true,
383
+ order: 10,
384
+ },
385
+ api: {
386
+ searchable: false,
387
+ sortable: false,
388
+ readOnly: false,
389
+ },
390
+ }
391
+ ```
392
+
393
+ **📋 Database Storage:**
394
+
395
+ Files are stored as JSONB arrays in the database:
396
+
397
+ ```sql
398
+ -- In your migration
399
+ ALTER TABLE posts ADD COLUMN featured_image jsonb;
400
+ ALTER TABLE posts ADD COLUMN attachments jsonb;
401
+ ```
402
+
403
+ ```json
404
+ // Stored structure
405
+ [
406
+ {
407
+ "id": "1704067200000-0.456",
408
+ "name": "image.jpg",
409
+ "size": 245678,
410
+ "type": "image/jpeg",
411
+ "url": "https://xxxxx.public.blob.vercel-storage.com/uploads/temp/...",
412
+ "alt": "Description"
413
+ }
414
+ ]
415
+ ```
416
+
417
+ **📋 EntityFieldRenderer Integration:**
418
+
419
+ The entity system automatically renders the correct component:
420
+
421
+ ```typescript
422
+ // This happens automatically in EntityFieldRenderer.tsx
423
+ case 'image':
424
+ return (
425
+ <ImageUpload
426
+ value={Array.isArray(value) ? value : []}
427
+ onChange={onChange}
428
+ disabled={disabled}
429
+ multiple={true}
430
+ />
431
+ )
432
+ ```
433
+
434
+ **📋 Display in List/Detail Views:**
435
+
436
+ File fields show a count in list and detail views:
437
+
438
+ ```
439
+ // In list view column
440
+ "2 archivos"
441
+
442
+ // In detail view
443
+ "3 archivos"
444
+ ```
445
+
446
+ ```
447
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
448
+
449
+ What would you like to do?
450
+
451
+ [1] Continue to Step 5 (Custom Upload Handling)
452
+ [2] How do I validate file types in schema?
453
+ [3] Can I have a single image instead of array?
454
+ ```
455
+
456
+ ---
457
+
458
+ ## Step 5: Custom Upload Handling
459
+
460
+ ```
461
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
462
+ STEP 5 OF 5: Custom Upload Handling
463
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
464
+
465
+ For advanced use cases, interact directly
466
+ with the upload API.
467
+ ```
468
+
469
+ **📋 Upload API Endpoint:**
470
+
471
+ ```
472
+ POST /api/v1/media/upload
473
+ Content-Type: multipart/form-data
474
+ Authorization: Bearer {apiKey} OR Session Cookie
475
+ ```
476
+
477
+ **📋 Making Upload Requests:**
478
+
479
+ ```typescript
480
+ async function uploadFiles(files: File[]) {
481
+ const formData = new FormData()
482
+
483
+ files.forEach((file, index) => {
484
+ formData.append(`file${index}`, file)
485
+ })
486
+
487
+ const response = await fetch('/api/v1/media/upload', {
488
+ method: 'POST',
489
+ body: formData,
490
+ // Note: Don't set Content-Type, browser sets it with boundary
491
+ })
492
+
493
+ const data = await response.json()
494
+
495
+ if (data.success) {
496
+ return data.urls // Array of uploaded file URLs
497
+ } else {
498
+ throw new Error(data.error)
499
+ }
500
+ }
501
+ ```
502
+
503
+ **📋 API Response Format:**
504
+
505
+ ```json
506
+ // Success
507
+ {
508
+ "message": "Files uploaded successfully",
509
+ "urls": [
510
+ "https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1704067200000_abc123.jpg",
511
+ "https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1704067200001_def456.pdf"
512
+ ],
513
+ "count": 2
514
+ }
515
+
516
+ // Error
517
+ {
518
+ "success": false,
519
+ "error": "File type not allowed"
520
+ }
521
+ ```
522
+
523
+ **📋 Required Permissions:**
524
+
525
+ | Scope | Action |
526
+ |-------|--------|
527
+ | `media:write` | Upload files |
528
+ | `media:read` | List/retrieve files |
529
+
530
+ **📋 Deleting Files:**
531
+
532
+ ```typescript
533
+ import { del } from '@vercel/blob'
534
+
535
+ // Delete a specific file by URL
536
+ await del(fileUrl)
537
+
538
+ // List files (for cleanup)
539
+ import { list } from '@vercel/blob'
540
+ const { blobs } = await list({ prefix: 'uploads/temp/' })
541
+ ```
542
+
543
+ **📋 Server-Side Validation:**
544
+
545
+ The upload endpoint validates:
546
+ 1. File type (MIME type check)
547
+ 2. File size (max 10MB)
548
+ 3. File count (max per request)
549
+ 4. Authentication (session or API key)
550
+ 5. Permissions (media:write scope)
551
+
552
+ ```
553
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
554
+
555
+ ✅ TUTORIAL STORY!
556
+
557
+ You've learned:
558
+ • Media system architecture (Vercel Blob)
559
+ • Environment configuration
560
+ • Using upload components
561
+ • Adding file fields to entities
562
+ • Custom upload handling
563
+
564
+ 📚 Related tutorials:
565
+ • /how-to:create-entity - Create entities with file fields
566
+ • /how-to:create-api - Custom API endpoints
567
+
568
+ 🔙 Back to menu: /how-to:start
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Interactive Options
574
+
575
+ ### "Can I use S3 or Cloudinary instead?"
576
+
577
+ ```
578
+ 📋 Alternative Storage Providers:
579
+
580
+ Currently, NextSpark uses Vercel Blob. To use S3 or Cloudinary:
581
+
582
+ 1. Create a custom upload endpoint:
583
+ /app/api/v1/media/upload-s3/route.ts
584
+
585
+ 2. Implement your provider:
586
+
587
+ import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
588
+
589
+ const s3 = new S3Client({ region: 'us-east-1' })
590
+
591
+ export async function POST(request: Request) {
592
+ const formData = await request.formData()
593
+ const file = formData.get('file') as File
594
+
595
+ await s3.send(new PutObjectCommand({
596
+ Bucket: process.env.S3_BUCKET,
597
+ Key: `uploads/${file.name}`,
598
+ Body: Buffer.from(await file.arrayBuffer()),
599
+ ContentType: file.type,
600
+ }))
601
+
602
+ return Response.json({
603
+ url: `https://${process.env.S3_BUCKET}.s3.amazonaws.com/uploads/${file.name}`
604
+ })
605
+ }
606
+
607
+ 3. Configure upload components to use your endpoint.
608
+ ```
609
+
610
+ ### "Show me a complete form example"
611
+
612
+ ```typescript
613
+ 'use client'
614
+
615
+ import { useState } from 'react'
616
+ import { ImageUpload } from '@/core/components/ui/image-upload'
617
+ import { FileUpload } from '@/core/components/ui/file-upload'
618
+ import { Button } from '@/core/components/ui/button'
619
+
620
+ export function ProductForm() {
621
+ const [images, setImages] = useState([])
622
+ const [documents, setDocuments] = useState([])
623
+
624
+ const handleSubmit = async (e) => {
625
+ e.preventDefault()
626
+
627
+ const productData = {
628
+ // ... other fields
629
+ images: images.map(img => ({
630
+ url: img.url,
631
+ alt: img.alt || img.name
632
+ })),
633
+ documents: documents.map(doc => ({
634
+ url: doc.url,
635
+ name: doc.name,
636
+ size: doc.size
637
+ }))
638
+ }
639
+
640
+ await saveProduct(productData)
641
+ }
642
+
643
+ return (
644
+ <form onSubmit={handleSubmit}>
645
+ <div className="space-y-4">
646
+ <div>
647
+ <label>Product Images</label>
648
+ <ImageUpload
649
+ value={images}
650
+ onChange={setImages}
651
+ maxImages={5}
652
+ aspectRatio="square"
653
+ />
654
+ </div>
655
+
656
+ <div>
657
+ <label>Documentation</label>
658
+ <FileUpload
659
+ value={documents}
660
+ onChange={setDocuments}
661
+ maxFiles={3}
662
+ acceptedTypes={['application/pdf']}
663
+ />
664
+ </div>
665
+
666
+ <Button type="submit">Save Product</Button>
667
+ </div>
668
+ </form>
669
+ )
670
+ }
671
+ ```
672
+
673
+ ---
674
+
675
+ ## Related Commands
676
+
677
+ | Command | Description |
678
+ |---------|-------------|
679
+ | `/how-to:create-entity` | Create entities with file fields |
680
+ | `/how-to:create-api` | Custom API endpoints |
681
+ | `/how-to:add-metadata` | Add metadata to uploaded files |