@girardmedia/bootspring 2.5.0 → 2.5.2

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 (59) hide show
  1. package/README.md +9 -403
  2. package/bin/bootspring.js +1 -96
  3. package/dist/cli/index.js +65134 -0
  4. package/dist/cli-launcher.js +92 -0
  5. package/dist/core/index.d.ts +2110 -5582
  6. package/dist/core/index.js +2 -0
  7. package/dist/core.js +21123 -5413
  8. package/dist/mcp/index.d.ts +357 -1
  9. package/dist/mcp/index.js +2 -0
  10. package/dist/mcp-server.js +51948 -1976
  11. package/package.json +27 -63
  12. package/scripts/postinstall.cjs +144 -0
  13. package/LICENSE +0 -29
  14. package/dist/cli/index.cjs +0 -20776
  15. package/generators/api-docs.js +0 -827
  16. package/generators/decisions.js +0 -655
  17. package/generators/generate.js +0 -595
  18. package/generators/health.js +0 -942
  19. package/generators/index.ts +0 -82
  20. package/generators/presets/full.js +0 -28
  21. package/generators/presets/index.js +0 -12
  22. package/generators/presets/minimal.js +0 -29
  23. package/generators/presets/standard.js +0 -28
  24. package/generators/questionnaire.js +0 -414
  25. package/generators/sections/advanced.js +0 -136
  26. package/generators/sections/ai.js +0 -106
  27. package/generators/sections/auth.js +0 -89
  28. package/generators/sections/backend.js +0 -146
  29. package/generators/sections/business.js +0 -118
  30. package/generators/sections/content.js +0 -300
  31. package/generators/sections/deployment.js +0 -139
  32. package/generators/sections/features.js +0 -122
  33. package/generators/sections/frontend.js +0 -118
  34. package/generators/sections/identity.js +0 -76
  35. package/generators/sections/index.js +0 -40
  36. package/generators/sections/instructions.js +0 -146
  37. package/generators/sections/payments.js +0 -104
  38. package/generators/sections/plugins.js +0 -142
  39. package/generators/sections/pre-build.js +0 -130
  40. package/generators/sections/security.js +0 -127
  41. package/generators/sections/technical.js +0 -171
  42. package/generators/sections/testing.js +0 -125
  43. package/generators/sections/workflow.js +0 -104
  44. package/generators/sprint.js +0 -675
  45. package/generators/templates/agents.template.js +0 -199
  46. package/generators/templates/assistant-context.template.js +0 -83
  47. package/generators/templates/build-planning.template.js +0 -708
  48. package/generators/templates/claude.template.js +0 -379
  49. package/generators/templates/content.template.js +0 -819
  50. package/generators/templates/index.js +0 -16
  51. package/generators/templates/planning.template.js +0 -515
  52. package/generators/templates/seed.template.js +0 -109
  53. package/generators/visual-doc-generator.js +0 -910
  54. package/scripts/postinstall.js +0 -197
  55. /package/{claude-commands → assets/claude-commands}/agent.md +0 -0
  56. /package/{claude-commands → assets/claude-commands}/bs.md +0 -0
  57. /package/{claude-commands → assets/claude-commands}/build.md +0 -0
  58. /package/{claude-commands → assets/claude-commands}/skill.md +0 -0
  59. /package/{claude-commands → assets/claude-commands}/todo.md +0 -0
@@ -1,300 +0,0 @@
1
- /**
2
- * Content Section
3
- *
4
- * Content strategy, documentation, and publishing planning.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/content
8
- */
9
-
10
- const title = 'Content & Documentation';
11
- const description = 'Content strategy and documentation planning';
12
-
13
- /**
14
- * Run the content section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askMultiSelect, askText } = helpers;
18
- const answers = {};
19
-
20
- // Content Strategy
21
- const strategyOptions = [
22
- { label: 'Developer-focused', value: 'developer', description: 'Technical docs, tutorials, API refs' },
23
- { label: 'Marketing-focused', value: 'marketing', description: 'Landing pages, blog, case studies' },
24
- { label: 'Mixed (Dev + Marketing)', value: 'mixed', description: 'Both technical and marketing' },
25
- { label: 'Internal only', value: 'internal', description: 'Internal docs and wikis' },
26
- { label: 'Minimal', value: 'minimal', description: 'Just README and basics' }
27
- ];
28
-
29
- answers.contentStrategy = await askChoice(
30
- rl,
31
- 'Content strategy:',
32
- strategyOptions,
33
- 2
34
- );
35
-
36
- // Documentation Types
37
- const docTypeOptions = [
38
- { label: 'Getting Started guide', value: 'getting-started' },
39
- { label: 'API Reference', value: 'api-reference' },
40
- { label: 'Tutorials/Guides', value: 'tutorials' },
41
- { label: 'Architecture docs', value: 'architecture' },
42
- { label: 'Contributing guide', value: 'contributing' },
43
- { label: 'Changelog', value: 'changelog' },
44
- { label: 'FAQ', value: 'faq' },
45
- { label: 'Troubleshooting', value: 'troubleshooting' }
46
- ];
47
-
48
- const defaultDocs = {
49
- developer: ['getting-started', 'api-reference', 'tutorials', 'contributing', 'changelog'],
50
- marketing: ['getting-started', 'faq'],
51
- mixed: ['getting-started', 'api-reference', 'tutorials', 'faq', 'changelog'],
52
- internal: ['architecture', 'contributing', 'troubleshooting'],
53
- minimal: ['getting-started']
54
- };
55
-
56
- answers.documentationTypes = await askMultiSelect(
57
- rl,
58
- 'Documentation to generate:',
59
- docTypeOptions,
60
- defaultDocs[answers.contentStrategy] || defaultDocs.minimal
61
- );
62
-
63
- // Blog/Content Publishing
64
- const publishingOptions = [
65
- { label: 'Yes, blog with regular posts', value: 'blog', description: 'Regular content publishing' },
66
- { label: 'Yes, announcements only', value: 'announcements', description: 'Release notes, updates' },
67
- { label: 'Yes, technical blog', value: 'technical', description: 'Tutorials, deep dives' },
68
- { label: 'No blog planned', value: 'none', description: 'No content publishing' }
69
- ];
70
-
71
- answers.contentPublishing = await askChoice(
72
- rl,
73
- 'Content publishing:',
74
- publishingOptions,
75
- answers.contentStrategy === 'marketing' ? 0 :
76
- answers.contentStrategy === 'developer' ? 2 : 3
77
- );
78
-
79
- // Content Formats
80
- if (answers.contentPublishing !== 'none') {
81
- const formatOptions = [
82
- { label: 'Blog posts', value: 'blog-posts' },
83
- { label: 'Tutorials', value: 'tutorials' },
84
- { label: 'Case studies', value: 'case-studies' },
85
- { label: 'Video content', value: 'video' },
86
- { label: 'Newsletter', value: 'newsletter' },
87
- { label: 'Social media', value: 'social' },
88
- { label: 'Podcasts', value: 'podcasts' },
89
- { label: 'Webinars', value: 'webinars' }
90
- ];
91
-
92
- const defaultFormats = {
93
- blog: ['blog-posts', 'social', 'newsletter'],
94
- announcements: ['blog-posts'],
95
- technical: ['tutorials', 'blog-posts', 'video']
96
- };
97
-
98
- answers.contentFormats = await askMultiSelect(
99
- rl,
100
- 'Content formats:',
101
- formatOptions,
102
- defaultFormats[answers.contentPublishing] || []
103
- );
104
- }
105
-
106
- // SEO Priority
107
- const seoOptions = [
108
- { label: 'High priority', value: 'high', description: 'Full SEO optimization' },
109
- { label: 'Medium priority', value: 'medium', description: 'Basic SEO practices' },
110
- { label: 'Low priority', value: 'low', description: 'Minimal SEO focus' },
111
- { label: 'Not applicable', value: 'none', description: 'Internal/private content' }
112
- ];
113
-
114
- answers.seoPriority = await askChoice(
115
- rl,
116
- 'SEO priority:',
117
- seoOptions,
118
- answers.contentStrategy === 'marketing' ? 0 : 1
119
- );
120
-
121
- // Documentation Platform
122
- const platformOptions = [
123
- { label: 'Built into app (MDX/Next.js)', value: 'builtin', description: 'Self-hosted docs' },
124
- { label: 'Docusaurus', value: 'docusaurus', description: 'React-based docs' },
125
- { label: 'GitBook', value: 'gitbook', description: 'Hosted docs platform' },
126
- { label: 'ReadMe', value: 'readme', description: 'API docs platform' },
127
- { label: 'Notion', value: 'notion', description: 'Wiki-style docs' },
128
- { label: 'GitHub Wiki', value: 'github-wiki', description: 'Simple wiki' },
129
- { label: 'Custom', value: 'custom', description: 'Build from scratch' }
130
- ];
131
-
132
- answers.docsPlatform = await askChoice(
133
- rl,
134
- 'Documentation platform:',
135
- platformOptions,
136
- 0
137
- );
138
-
139
- // Writing Style
140
- const styleOptions = [
141
- { label: 'Technical & precise', value: 'technical', description: 'Developer-focused, detailed' },
142
- { label: 'Friendly & approachable', value: 'friendly', description: 'Casual, welcoming' },
143
- { label: 'Professional & formal', value: 'professional', description: 'Enterprise, formal' },
144
- { label: 'Minimal & concise', value: 'minimal', description: 'Brief, to the point' }
145
- ];
146
-
147
- answers.writingStyle = await askChoice(
148
- rl,
149
- 'Writing style:',
150
- styleOptions,
151
- answers.contentStrategy === 'marketing' ? 1 :
152
- answers.contentStrategy === 'internal' ? 2 : 0
153
- );
154
-
155
- // Content Templates
156
- const templateOptions = [
157
- { label: 'README template', value: 'readme' },
158
- { label: 'Blog post template', value: 'blog' },
159
- { label: 'API endpoint docs', value: 'api-docs' },
160
- { label: 'Release notes template', value: 'release-notes' },
161
- { label: 'Tutorial template', value: 'tutorial' },
162
- { label: 'Landing page copy', value: 'landing' },
163
- { label: 'Email templates', value: 'email' },
164
- { label: 'Social media templates', value: 'social' }
165
- ];
166
-
167
- answers.contentTemplates = await askMultiSelect(
168
- rl,
169
- 'Content templates to generate:',
170
- templateOptions,
171
- ['readme', 'blog', 'release-notes']
172
- );
173
-
174
- // Localization
175
- const localizationOptions = [
176
- { label: 'English only', value: 'en', description: 'Single language' },
177
- { label: 'English + top languages', value: 'multi-top', description: 'EN, ES, FR, DE, ZH' },
178
- { label: 'Full i18n', value: 'full', description: 'All major languages' },
179
- { label: 'Community translations', value: 'community', description: 'Crowdsourced' }
180
- ];
181
-
182
- answers.localization = await askChoice(
183
- rl,
184
- 'Content localization:',
185
- localizationOptions,
186
- 0
187
- );
188
-
189
- // Content calendar
190
- if (answers.contentPublishing !== 'none') {
191
- const calendarOptions = [
192
- { label: 'Weekly publishing', value: 'weekly', description: '1+ posts per week' },
193
- { label: 'Bi-weekly publishing', value: 'biweekly', description: '2 posts per month' },
194
- { label: 'Monthly publishing', value: 'monthly', description: '1 post per month' },
195
- { label: 'Release-driven', value: 'release', description: 'Publish with releases' },
196
- { label: 'Ad-hoc', value: 'adhoc', description: 'No schedule' }
197
- ];
198
-
199
- answers.contentCadence = await askChoice(
200
- rl,
201
- 'Content cadence:',
202
- calendarOptions,
203
- 3
204
- );
205
- }
206
-
207
- return answers;
208
- }
209
-
210
- /**
211
- * Generate content-related CLAUDE.md sections
212
- */
213
- function generateSection(answers) {
214
- const sections = [];
215
-
216
- if (answers.contentStrategy && answers.contentStrategy !== 'minimal') {
217
- sections.push(`## Content Strategy
218
-
219
- - **Strategy**: ${answers.contentStrategy}
220
- - **Writing Style**: ${answers.writingStyle || 'technical'}
221
- - **SEO Priority**: ${answers.seoPriority || 'medium'}
222
- - **Documentation Platform**: ${answers.docsPlatform || 'builtin'}
223
- - **Localization**: ${answers.localization || 'en'}
224
- `);
225
- }
226
-
227
- if (answers.documentationTypes && answers.documentationTypes.length > 0) {
228
- sections.push(`### Documentation Types
229
-
230
- ${answers.documentationTypes.map(d => `- ${formatDocType(d)}`).join('\n')}
231
- `);
232
- }
233
-
234
- if (answers.contentFormats && answers.contentFormats.length > 0) {
235
- sections.push(`### Content Formats
236
-
237
- ${answers.contentFormats.map(f => `- ${formatContentFormat(f)}`).join('\n')}
238
-
239
- **Cadence**: ${answers.contentCadence || 'ad-hoc'}
240
- `);
241
- }
242
-
243
- if (answers.contentTemplates && answers.contentTemplates.length > 0) {
244
- sections.push(`### Content Templates
245
-
246
- ${answers.contentTemplates.map(t => `- ${formatTemplate(t)}`).join('\n')}
247
- `);
248
- }
249
-
250
- return sections.join('\n');
251
- }
252
-
253
- function formatDocType(type) {
254
- const labels = {
255
- 'getting-started': 'Getting Started Guide',
256
- 'api-reference': 'API Reference',
257
- 'tutorials': 'Tutorials & Guides',
258
- 'architecture': 'Architecture Documentation',
259
- 'contributing': 'Contributing Guide',
260
- 'changelog': 'Changelog',
261
- 'faq': 'FAQ',
262
- 'troubleshooting': 'Troubleshooting Guide'
263
- };
264
- return labels[type] || type;
265
- }
266
-
267
- function formatContentFormat(format) {
268
- const labels = {
269
- 'blog-posts': 'Blog Posts',
270
- 'tutorials': 'Tutorial Articles',
271
- 'case-studies': 'Case Studies',
272
- 'video': 'Video Content',
273
- 'newsletter': 'Email Newsletter',
274
- 'social': 'Social Media',
275
- 'podcasts': 'Podcast Episodes',
276
- 'webinars': 'Webinars'
277
- };
278
- return labels[format] || format;
279
- }
280
-
281
- function formatTemplate(template) {
282
- const labels = {
283
- 'readme': 'README Template',
284
- 'blog': 'Blog Post Template',
285
- 'api-docs': 'API Documentation Template',
286
- 'release-notes': 'Release Notes Template',
287
- 'tutorial': 'Tutorial Template',
288
- 'landing': 'Landing Page Copy Template',
289
- 'email': 'Email Templates',
290
- 'social': 'Social Media Templates'
291
- };
292
- return labels[template] || template;
293
- }
294
-
295
- module.exports = {
296
- title,
297
- description,
298
- run,
299
- generateSection
300
- };
@@ -1,139 +0,0 @@
1
- /**
2
- * Deployment Section
3
- *
4
- * DevOps, CI/CD, and deployment configuration.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/deployment
8
- */
9
-
10
- const title = 'DevOps & Deployment';
11
- const description = 'CI/CD and deployment setup';
12
-
13
- /**
14
- * Run the deployment section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askMultiSelect, askYesNo } = helpers;
18
- const answers = {};
19
-
20
- // Environments
21
- const envOptions = [
22
- { label: 'Production only', value: 'prod', description: 'Single environment' },
23
- { label: 'Production + Preview', value: 'prod-preview', description: 'Standard setup' },
24
- { label: 'Dev + Staging + Production', value: 'full', description: 'Full pipeline' },
25
- { label: 'Custom', value: 'custom', description: 'Define your own' }
26
- ];
27
-
28
- answers.environments = await askChoice(
29
- rl,
30
- 'Deployment environments:',
31
- envOptions,
32
- 1
33
- );
34
-
35
- // CI/CD Platform
36
- const ciOptions = [
37
- { label: 'GitHub Actions', value: 'github', description: 'GitHub native (Recommended)' },
38
- { label: 'Vercel', value: 'vercel', description: 'Automatic with Vercel' },
39
- { label: 'GitLab CI', value: 'gitlab', description: 'GitLab pipelines' },
40
- { label: 'CircleCI', value: 'circleci', description: 'Popular CI service' },
41
- { label: 'None', value: 'none', description: 'Manual deployment' }
42
- ];
43
-
44
- answers.ciPlatform = await askChoice(
45
- rl,
46
- 'CI/CD platform:',
47
- ciOptions,
48
- 0
49
- );
50
-
51
- // Branch Strategy
52
- const branchOptions = [
53
- { label: 'Trunk-based', value: 'trunk', description: 'Deploy from main' },
54
- { label: 'Git Flow', value: 'gitflow', description: 'Feature/develop/release branches' },
55
- { label: 'GitHub Flow', value: 'github-flow', description: 'Feature branches + PRs' },
56
- { label: 'Custom', value: 'custom', description: 'Your own strategy' }
57
- ];
58
-
59
- answers.branchStrategy = await askChoice(
60
- rl,
61
- 'Branch strategy:',
62
- branchOptions,
63
- 2
64
- );
65
-
66
- // Pipeline Steps
67
- const pipelineOptions = [
68
- { label: 'Lint', value: 'lint' },
69
- { label: 'Type check', value: 'typecheck' },
70
- { label: 'Unit tests', value: 'unit' },
71
- { label: 'Integration tests', value: 'integration' },
72
- { label: 'E2E tests', value: 'e2e' },
73
- { label: 'Security scan', value: 'security' },
74
- { label: 'Build', value: 'build' },
75
- { label: 'Deploy preview', value: 'preview' }
76
- ];
77
-
78
- answers.pipelineSteps = await askMultiSelect(
79
- rl,
80
- 'CI pipeline steps:',
81
- pipelineOptions,
82
- ['lint', 'typecheck', 'unit', 'build']
83
- );
84
-
85
- // Monitoring
86
- answers.enableMonitoring = await askYesNo(
87
- rl,
88
- 'Set up monitoring/observability?',
89
- false
90
- );
91
-
92
- if (answers.enableMonitoring) {
93
- const monitoringOptions = [
94
- { label: 'Sentry', value: 'sentry', description: 'Error tracking' },
95
- { label: 'LogRocket', value: 'logrocket', description: 'Session replay' },
96
- { label: 'Datadog', value: 'datadog', description: 'Full observability' },
97
- { label: 'New Relic', value: 'newrelic', description: 'APM' },
98
- { label: 'Vercel Analytics', value: 'vercel', description: 'Basic analytics' }
99
- ];
100
-
101
- answers.monitoringProvider = await askChoice(
102
- rl,
103
- 'Monitoring provider:',
104
- monitoringOptions,
105
- 0
106
- );
107
- }
108
-
109
- // Feature Flags
110
- answers.enableFeatureFlags = await askYesNo(
111
- rl,
112
- 'Need feature flags?',
113
- false
114
- );
115
-
116
- if (answers.enableFeatureFlags) {
117
- const flagOptions = [
118
- { label: 'LaunchDarkly', value: 'launchdarkly', description: 'Enterprise flags' },
119
- { label: 'PostHog', value: 'posthog', description: 'Product analytics + flags' },
120
- { label: 'Flagsmith', value: 'flagsmith', description: 'Open source flags' },
121
- { label: 'Custom', value: 'custom', description: 'Build your own' }
122
- ];
123
-
124
- answers.featureFlagProvider = await askChoice(
125
- rl,
126
- 'Feature flag provider:',
127
- flagOptions,
128
- 1
129
- );
130
- }
131
-
132
- return answers;
133
- }
134
-
135
- module.exports = {
136
- title,
137
- description,
138
- run
139
- };
@@ -1,122 +0,0 @@
1
- /**
2
- * Features Section
3
- *
4
- * Application features and functionality planning.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/features
8
- */
9
-
10
- const title = 'Features & Functionality';
11
- const description = 'Core features planning';
12
-
13
- /**
14
- * Run the features section
15
- */
16
- async function run(rl, previousAnswers, helpers) {
17
- const { askChoice, askMultiSelect, askText } = helpers;
18
- const answers = {};
19
-
20
- // App Type
21
- const typeOptions = [
22
- { label: 'SaaS Application', value: 'saas', description: 'Software as a Service' },
23
- { label: 'Marketplace', value: 'marketplace', description: 'Two-sided platform' },
24
- { label: 'E-commerce', value: 'ecommerce', description: 'Online store' },
25
- { label: 'Content Platform', value: 'content', description: 'Blog, media, CMS' },
26
- { label: 'Internal Tool', value: 'internal', description: 'Business tool' },
27
- { label: 'API/Developer Tool', value: 'api', description: 'Developer-focused' },
28
- { label: 'Mobile App Backend', value: 'mobile', description: 'Mobile API backend' },
29
- { label: 'Other', value: 'other', description: 'Custom application' }
30
- ];
31
-
32
- answers.appType = await askChoice(
33
- rl,
34
- 'Application type:',
35
- typeOptions,
36
- 0
37
- );
38
-
39
- // Common Features based on app type
40
- const commonFeatures = {
41
- saas: ['dashboard', 'settings', 'notifications', 'billing', 'teams'],
42
- marketplace: ['listings', 'search', 'messaging', 'reviews', 'payments'],
43
- ecommerce: ['catalog', 'cart', 'checkout', 'orders', 'inventory'],
44
- content: ['posts', 'comments', 'categories', 'search', 'rss'],
45
- internal: ['dashboard', 'reports', 'users', 'permissions', 'audit'],
46
- api: ['docs', 'keys', 'usage', 'webhooks', 'playground'],
47
- mobile: ['push', 'sync', 'offline', 'auth', 'media'],
48
- other: ['dashboard', 'settings', 'notifications']
49
- };
50
-
51
- const suggestedFeatures = commonFeatures[answers.appType] || commonFeatures.other;
52
-
53
- // Feature Selection
54
- const featureOptions = [
55
- { label: 'User dashboard', value: 'dashboard' },
56
- { label: 'Settings/preferences', value: 'settings' },
57
- { label: 'Notifications', value: 'notifications' },
58
- { label: 'Billing/subscriptions', value: 'billing' },
59
- { label: 'Team/organization', value: 'teams' },
60
- { label: 'Search', value: 'search' },
61
- { label: 'File uploads', value: 'uploads' },
62
- { label: 'Comments/feedback', value: 'comments' },
63
- { label: 'Analytics', value: 'analytics' },
64
- { label: 'API access', value: 'api' },
65
- { label: 'Webhooks', value: 'webhooks' },
66
- { label: 'Export/import', value: 'export' }
67
- ];
68
-
69
- answers.coreFeatures = await askMultiSelect(
70
- rl,
71
- 'Core features:',
72
- featureOptions,
73
- suggestedFeatures.filter(f => featureOptions.some(o => o.value === f))
74
- );
75
-
76
- // MVP Scope
77
- const mvpOptions = [
78
- { label: 'Landing page only', value: 'landing', description: 'Validate idea' },
79
- { label: 'Waitlist MVP', value: 'waitlist', description: 'Collect interest' },
80
- { label: 'Single feature MVP', value: 'single', description: 'One core feature' },
81
- { label: 'Full MVP', value: 'full', description: 'Multiple features' },
82
- { label: 'Production ready', value: 'production', description: 'Launch ready' }
83
- ];
84
-
85
- answers.mvpScope = await askChoice(
86
- rl,
87
- 'MVP scope:',
88
- mvpOptions,
89
- 2
90
- );
91
-
92
- // Primary use case
93
- answers.primaryUseCase = await askText(
94
- rl,
95
- 'Describe the primary use case in one sentence',
96
- ''
97
- );
98
-
99
- // Target users
100
- const userOptions = [
101
- { label: 'Consumers (B2C)', value: 'b2c' },
102
- { label: 'Businesses (B2B)', value: 'b2b' },
103
- { label: 'Developers', value: 'developers' },
104
- { label: 'Enterprise', value: 'enterprise' },
105
- { label: 'Internal team', value: 'internal' }
106
- ];
107
-
108
- answers.targetUsers = await askChoice(
109
- rl,
110
- 'Primary target users:',
111
- userOptions,
112
- 0
113
- );
114
-
115
- return answers;
116
- }
117
-
118
- module.exports = {
119
- title,
120
- description,
121
- run
122
- };
@@ -1,118 +0,0 @@
1
- /**
2
- * Frontend Stack Section
3
- *
4
- * UI library, styling, state management, and component choices.
5
- *
6
- * @package bootspring
7
- * @module generators/sections/frontend
8
- */
9
-
10
- const title = 'Frontend Stack';
11
- const description = 'UI and styling choices';
12
-
13
- /**
14
- * Check if frontend section should be skipped
15
- */
16
- function shouldSkip(previousAnswers) {
17
- // Skip for pure backend frameworks
18
- const backendOnly = ['express', 'fastify', 'hono', 'koa'];
19
- return backendOnly.includes(previousAnswers.framework);
20
- }
21
-
22
- /**
23
- * Run the frontend section
24
- */
25
- async function run(rl, previousAnswers, helpers) {
26
- const { askChoice, askMultiSelect } = helpers;
27
- const answers = {};
28
-
29
- // UI Component Library
30
- const uiOptions = [
31
- { label: 'shadcn/ui', value: 'shadcn', description: 'Copy-paste components (Recommended)' },
32
- { label: 'Radix UI', value: 'radix', description: 'Unstyled primitives' },
33
- { label: 'Chakra UI', value: 'chakra', description: 'Accessible components' },
34
- { label: 'Mantine', value: 'mantine', description: 'Full-featured React library' },
35
- { label: 'Ant Design', value: 'antd', description: 'Enterprise UI library' },
36
- { label: 'Custom', value: 'custom', description: 'Build your own' }
37
- ];
38
-
39
- answers.uiLibrary = await askChoice(
40
- rl,
41
- 'UI Component Library:',
42
- uiOptions,
43
- 0
44
- );
45
-
46
- // Styling
47
- const stylingOptions = [
48
- { label: 'Tailwind CSS', value: 'tailwind', description: 'Utility-first (Recommended)' },
49
- { label: 'CSS Modules', value: 'cssmodules', description: 'Scoped CSS' },
50
- { label: 'Styled Components', value: 'styled', description: 'CSS-in-JS' },
51
- { label: 'Emotion', value: 'emotion', description: 'CSS-in-JS' },
52
- { label: 'Sass/SCSS', value: 'sass', description: 'CSS preprocessor' },
53
- { label: 'Plain CSS', value: 'css', description: 'Vanilla CSS' }
54
- ];
55
-
56
- answers.styling = await askChoice(
57
- rl,
58
- 'Styling approach:',
59
- stylingOptions,
60
- 0
61
- );
62
-
63
- // State Management (for non-Next.js frameworks or complex apps)
64
- const stateOptions = [
65
- { label: 'React Context', value: 'context', description: 'Built-in, simple apps' },
66
- { label: 'Zustand', value: 'zustand', description: 'Lightweight and flexible' },
67
- { label: 'Jotai', value: 'jotai', description: 'Atomic state' },
68
- { label: 'Redux Toolkit', value: 'redux', description: 'Powerful, complex apps' },
69
- { label: 'None / Server State', value: 'none', description: 'Use React Query / SWR only' }
70
- ];
71
-
72
- answers.stateManagement = await askChoice(
73
- rl,
74
- 'State management:',
75
- stateOptions,
76
- 0
77
- );
78
-
79
- // Data Fetching
80
- const fetchingOptions = [
81
- { label: 'TanStack Query', value: 'tanstack', description: 'Server state (Recommended)' },
82
- { label: 'SWR', value: 'swr', description: 'Vercel data fetching' },
83
- { label: 'Native fetch', value: 'native', description: 'Built-in fetch API' },
84
- { label: 'Axios', value: 'axios', description: 'HTTP client' }
85
- ];
86
-
87
- answers.dataFetching = await askChoice(
88
- rl,
89
- 'Data fetching:',
90
- fetchingOptions,
91
- 0
92
- );
93
-
94
- // Additional features
95
- const featureOptions = [
96
- { label: 'Dark mode', value: 'darkMode' },
97
- { label: 'Animations (Framer Motion)', value: 'animations' },
98
- { label: 'Internationalization (i18n)', value: 'i18n' },
99
- { label: 'Form handling (React Hook Form)', value: 'forms' },
100
- { label: 'Icon library (Lucide)', value: 'icons' }
101
- ];
102
-
103
- answers.frontendFeatures = await askMultiSelect(
104
- rl,
105
- 'Additional frontend features:',
106
- featureOptions,
107
- ['darkMode', 'forms', 'icons']
108
- );
109
-
110
- return answers;
111
- }
112
-
113
- module.exports = {
114
- title,
115
- description,
116
- shouldSkip,
117
- run
118
- };