@nextsparkjs/ai-workflow 0.1.0-beta.100

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