@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.
- package/README.md +9 -403
- package/bin/bootspring.js +1 -96
- package/dist/cli/index.js +65134 -0
- package/dist/cli-launcher.js +92 -0
- package/dist/core/index.d.ts +2110 -5582
- package/dist/core/index.js +2 -0
- package/dist/core.js +21123 -5413
- package/dist/mcp/index.d.ts +357 -1
- package/dist/mcp/index.js +2 -0
- package/dist/mcp-server.js +51948 -1976
- package/package.json +27 -63
- package/scripts/postinstall.cjs +144 -0
- package/LICENSE +0 -29
- package/dist/cli/index.cjs +0 -20776
- package/generators/api-docs.js +0 -827
- package/generators/decisions.js +0 -655
- package/generators/generate.js +0 -595
- package/generators/health.js +0 -942
- package/generators/index.ts +0 -82
- package/generators/presets/full.js +0 -28
- package/generators/presets/index.js +0 -12
- package/generators/presets/minimal.js +0 -29
- package/generators/presets/standard.js +0 -28
- package/generators/questionnaire.js +0 -414
- package/generators/sections/advanced.js +0 -136
- package/generators/sections/ai.js +0 -106
- package/generators/sections/auth.js +0 -89
- package/generators/sections/backend.js +0 -146
- package/generators/sections/business.js +0 -118
- package/generators/sections/content.js +0 -300
- package/generators/sections/deployment.js +0 -139
- package/generators/sections/features.js +0 -122
- package/generators/sections/frontend.js +0 -118
- package/generators/sections/identity.js +0 -76
- package/generators/sections/index.js +0 -40
- package/generators/sections/instructions.js +0 -146
- package/generators/sections/payments.js +0 -104
- package/generators/sections/plugins.js +0 -142
- package/generators/sections/pre-build.js +0 -130
- package/generators/sections/security.js +0 -127
- package/generators/sections/technical.js +0 -171
- package/generators/sections/testing.js +0 -125
- package/generators/sections/workflow.js +0 -104
- package/generators/sprint.js +0 -675
- package/generators/templates/agents.template.js +0 -199
- package/generators/templates/assistant-context.template.js +0 -83
- package/generators/templates/build-planning.template.js +0 -708
- package/generators/templates/claude.template.js +0 -379
- package/generators/templates/content.template.js +0 -819
- package/generators/templates/index.js +0 -16
- package/generators/templates/planning.template.js +0 -515
- package/generators/templates/seed.template.js +0 -109
- package/generators/visual-doc-generator.js +0 -910
- package/scripts/postinstall.js +0 -197
- /package/{claude-commands → assets/claude-commands}/agent.md +0 -0
- /package/{claude-commands → assets/claude-commands}/bs.md +0 -0
- /package/{claude-commands → assets/claude-commands}/build.md +0 -0
- /package/{claude-commands → assets/claude-commands}/skill.md +0 -0
- /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
|
-
};
|