@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,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Advanced Options Section
|
|
3
|
-
*
|
|
4
|
-
* Collects security, compliance, and infrastructure settings.
|
|
5
|
-
* Only included in full preset.
|
|
6
|
-
*
|
|
7
|
-
* @package bootspring
|
|
8
|
-
* @module generators/sections/advanced
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const title = 'Advanced Options';
|
|
12
|
-
const description = 'Security, compliance, and infrastructure';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Run the advanced section
|
|
16
|
-
*/
|
|
17
|
-
async function run(rl, previousAnswers, helpers) {
|
|
18
|
-
const { askChoice, askMultiSelect, askYesNo } = helpers;
|
|
19
|
-
|
|
20
|
-
const answers = {};
|
|
21
|
-
|
|
22
|
-
console.log('\nAdvanced configuration options');
|
|
23
|
-
|
|
24
|
-
// Security level
|
|
25
|
-
answers.securityLevel = await askChoice(
|
|
26
|
-
rl,
|
|
27
|
-
'Security level:',
|
|
28
|
-
[
|
|
29
|
-
{ label: 'Standard', value: 'standard', description: 'Good defaults for most apps' },
|
|
30
|
-
{ label: 'Enhanced', value: 'enhanced', description: 'Additional security measures' },
|
|
31
|
-
{ label: 'Enterprise', value: 'enterprise', description: 'Maximum security posture' }
|
|
32
|
-
],
|
|
33
|
-
0
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
// Compliance requirements
|
|
37
|
-
const needsCompliance = await askYesNo(
|
|
38
|
-
rl,
|
|
39
|
-
'Have compliance requirements (GDPR, SOC2, etc.)?',
|
|
40
|
-
false
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (needsCompliance) {
|
|
44
|
-
answers.compliance = await askMultiSelect(
|
|
45
|
-
rl,
|
|
46
|
-
'Select compliance requirements:',
|
|
47
|
-
[
|
|
48
|
-
{ label: 'GDPR', value: 'gdpr', description: 'EU data protection' },
|
|
49
|
-
{ label: 'SOC 2', value: 'soc2', description: 'Service organization controls' },
|
|
50
|
-
{ label: 'HIPAA', value: 'hipaa', description: 'Healthcare data' },
|
|
51
|
-
{ label: 'PCI DSS', value: 'pci', description: 'Payment card data' },
|
|
52
|
-
{ label: 'CCPA', value: 'ccpa', description: 'California privacy' }
|
|
53
|
-
],
|
|
54
|
-
[]
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Infrastructure
|
|
59
|
-
answers.infrastructure = await askChoice(
|
|
60
|
-
rl,
|
|
61
|
-
'Infrastructure approach:',
|
|
62
|
-
[
|
|
63
|
-
{ label: 'Managed/Serverless', value: 'managed', description: 'Vercel, Railway, etc.' },
|
|
64
|
-
{ label: 'Containers', value: 'containers', description: 'Docker, Kubernetes' },
|
|
65
|
-
{ label: 'VMs', value: 'vms', description: 'Traditional servers' },
|
|
66
|
-
{ label: 'Hybrid', value: 'hybrid', description: 'Mix of approaches' }
|
|
67
|
-
],
|
|
68
|
-
0
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
// Monitoring
|
|
72
|
-
const wantMonitoring = await askYesNo(
|
|
73
|
-
rl,
|
|
74
|
-
'Set up monitoring/observability?',
|
|
75
|
-
true
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
if (wantMonitoring) {
|
|
79
|
-
answers.monitoring = await askMultiSelect(
|
|
80
|
-
rl,
|
|
81
|
-
'Monitoring tools:',
|
|
82
|
-
[
|
|
83
|
-
{ label: 'Error tracking (Sentry)', value: 'sentry' },
|
|
84
|
-
{ label: 'Analytics (Posthog)', value: 'posthog' },
|
|
85
|
-
{ label: 'Logging (Axiom)', value: 'axiom' },
|
|
86
|
-
{ label: 'Uptime monitoring', value: 'uptime' },
|
|
87
|
-
{ label: 'Performance (Vercel Analytics)', value: 'vercel-analytics' }
|
|
88
|
-
],
|
|
89
|
-
['sentry']
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Feature flags
|
|
94
|
-
answers.featureFlags = await askYesNo(
|
|
95
|
-
rl,
|
|
96
|
-
'Use feature flags?',
|
|
97
|
-
false
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
if (answers.featureFlags) {
|
|
101
|
-
answers.featureFlagProvider = await askChoice(
|
|
102
|
-
rl,
|
|
103
|
-
'Feature flag provider:',
|
|
104
|
-
[
|
|
105
|
-
{ label: 'LaunchDarkly', value: 'launchdarkly' },
|
|
106
|
-
{ label: 'Flagsmith', value: 'flagsmith' },
|
|
107
|
-
{ label: 'PostHog', value: 'posthog' },
|
|
108
|
-
{ label: 'Custom', value: 'custom' }
|
|
109
|
-
],
|
|
110
|
-
0
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Multi-tenancy
|
|
115
|
-
if (previousAnswers.businessModel === 'saas') {
|
|
116
|
-
answers.multiTenancy = await askChoice(
|
|
117
|
-
rl,
|
|
118
|
-
'Multi-tenancy approach:',
|
|
119
|
-
[
|
|
120
|
-
{ label: 'Single tenant', value: 'single', description: 'One instance per customer' },
|
|
121
|
-
{ label: 'Shared DB', value: 'shared-db', description: 'Shared database, row-level' },
|
|
122
|
-
{ label: 'Schema per tenant', value: 'schema', description: 'Separate schemas' },
|
|
123
|
-
{ label: 'DB per tenant', value: 'db-per-tenant', description: 'Separate databases' }
|
|
124
|
-
],
|
|
125
|
-
1
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return answers;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = {
|
|
133
|
-
title,
|
|
134
|
-
description,
|
|
135
|
-
run
|
|
136
|
-
};
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Integration Section
|
|
3
|
-
*
|
|
4
|
-
* AI providers, features, and configuration.
|
|
5
|
-
*
|
|
6
|
-
* @package bootspring
|
|
7
|
-
* @module generators/sections/ai
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const title = 'AI Integration';
|
|
11
|
-
const description = 'AI and LLM setup';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Run the AI section
|
|
15
|
-
*/
|
|
16
|
-
async function run(rl, previousAnswers, helpers) {
|
|
17
|
-
const { askChoice, askMultiSelect, askYesNo } = helpers;
|
|
18
|
-
const answers = {};
|
|
19
|
-
|
|
20
|
-
// Enable AI
|
|
21
|
-
answers.enableAI = await askYesNo(
|
|
22
|
-
rl,
|
|
23
|
-
'Does your app need AI/LLM features?',
|
|
24
|
-
false
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
if (!answers.enableAI) {
|
|
28
|
-
return answers;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// AI Providers (multi-select)
|
|
32
|
-
const providerOptions = [
|
|
33
|
-
{ label: 'Anthropic (Claude)', value: 'anthropic', description: 'Claude models (Recommended)' },
|
|
34
|
-
{ label: 'OpenAI', value: 'openai', description: 'GPT models' },
|
|
35
|
-
{ label: 'Google AI', value: 'google', description: 'Gemini models' },
|
|
36
|
-
{ label: 'Cohere', value: 'cohere', description: 'Enterprise NLP' },
|
|
37
|
-
{ label: 'Hugging Face', value: 'huggingface', description: 'Open source models' },
|
|
38
|
-
{ label: 'Local (Ollama)', value: 'ollama', description: 'Self-hosted models' }
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
answers.aiProviders = await askMultiSelect(
|
|
42
|
-
rl,
|
|
43
|
-
'AI providers to integrate (select one or more):',
|
|
44
|
-
providerOptions,
|
|
45
|
-
['anthropic']
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
// AI Features
|
|
49
|
-
const featureOptions = [
|
|
50
|
-
{ label: 'Chat/Conversation', value: 'chat' },
|
|
51
|
-
{ label: 'Text generation', value: 'generation' },
|
|
52
|
-
{ label: 'Embeddings/Search', value: 'embeddings' },
|
|
53
|
-
{ label: 'RAG (Retrieval Augmented)', value: 'rag' },
|
|
54
|
-
{ label: 'Image generation', value: 'images' },
|
|
55
|
-
{ label: 'Code generation', value: 'code' },
|
|
56
|
-
{ label: 'Speech/Audio', value: 'speech' },
|
|
57
|
-
{ label: 'Structured output', value: 'structured' }
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
answers.aiFeatures = await askMultiSelect(
|
|
61
|
-
rl,
|
|
62
|
-
'AI features needed:',
|
|
63
|
-
featureOptions,
|
|
64
|
-
['chat', 'generation']
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Vector Database (if embeddings/RAG selected)
|
|
68
|
-
if (answers.aiFeatures.includes('embeddings') || answers.aiFeatures.includes('rag')) {
|
|
69
|
-
const vectorOptions = [
|
|
70
|
-
{ label: 'Pinecone', value: 'pinecone', description: 'Managed vector DB' },
|
|
71
|
-
{ label: 'Qdrant', value: 'qdrant', description: 'Open source vector DB' },
|
|
72
|
-
{ label: 'Weaviate', value: 'weaviate', description: 'AI-native vector DB' },
|
|
73
|
-
{ label: 'Supabase pgvector', value: 'pgvector', description: 'PostgreSQL extension' },
|
|
74
|
-
{ label: 'Turbopuffer', value: 'turbopuffer', description: 'Fast serverless' }
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
answers.vectorDb = await askChoice(
|
|
78
|
-
rl,
|
|
79
|
-
'Vector database:',
|
|
80
|
-
vectorOptions,
|
|
81
|
-
0
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Streaming
|
|
86
|
-
answers.aiStreaming = await askYesNo(
|
|
87
|
-
rl,
|
|
88
|
-
'Enable streaming responses?',
|
|
89
|
-
true
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
// Rate limiting
|
|
93
|
-
answers.aiRateLimiting = await askYesNo(
|
|
94
|
-
rl,
|
|
95
|
-
'Need AI rate limiting?',
|
|
96
|
-
true
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return answers;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
module.exports = {
|
|
103
|
-
title,
|
|
104
|
-
description,
|
|
105
|
-
run
|
|
106
|
-
};
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Authentication Section
|
|
3
|
-
*
|
|
4
|
-
* Auth provider, methods, and configuration.
|
|
5
|
-
*
|
|
6
|
-
* @package bootspring
|
|
7
|
-
* @module generators/sections/auth
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const title = 'Authentication';
|
|
11
|
-
const description = 'User authentication setup';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Run the auth section
|
|
15
|
-
*/
|
|
16
|
-
async function run(rl, previousAnswers, helpers) {
|
|
17
|
-
const { askChoice, askMultiSelect, askYesNo } = helpers;
|
|
18
|
-
const answers = {};
|
|
19
|
-
|
|
20
|
-
// Enable auth
|
|
21
|
-
answers.enableAuth = await askYesNo(
|
|
22
|
-
rl,
|
|
23
|
-
'Does your app need user authentication?',
|
|
24
|
-
true
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
if (!answers.enableAuth) {
|
|
28
|
-
return answers;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Auth Provider
|
|
32
|
-
const providerOptions = [
|
|
33
|
-
{ label: 'Clerk', value: 'clerk', description: 'Full-featured, easy setup (Recommended)' },
|
|
34
|
-
{ label: 'Auth.js (NextAuth)', value: 'authjs', description: 'Flexible, many providers' },
|
|
35
|
-
{ label: 'Supabase Auth', value: 'supabase', description: 'Part of Supabase stack' },
|
|
36
|
-
{ label: 'Firebase Auth', value: 'firebase', description: 'Google Firebase' },
|
|
37
|
-
{ label: 'Kinde', value: 'kinde', description: 'Developer-friendly' },
|
|
38
|
-
{ label: 'Custom', value: 'custom', description: 'Build your own' }
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
answers.authProvider = await askChoice(
|
|
42
|
-
rl,
|
|
43
|
-
'Auth provider:',
|
|
44
|
-
providerOptions,
|
|
45
|
-
0
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
// Auth Methods
|
|
49
|
-
const methodOptions = [
|
|
50
|
-
{ label: 'Email/Password', value: 'email' },
|
|
51
|
-
{ label: 'Magic Link', value: 'magic' },
|
|
52
|
-
{ label: 'Google OAuth', value: 'google' },
|
|
53
|
-
{ label: 'GitHub OAuth', value: 'github' },
|
|
54
|
-
{ label: 'Apple OAuth', value: 'apple' },
|
|
55
|
-
{ label: 'Passkeys/WebAuthn', value: 'passkeys' },
|
|
56
|
-
{ label: 'SMS/Phone', value: 'phone' }
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
answers.authMethods = await askMultiSelect(
|
|
60
|
-
rl,
|
|
61
|
-
'Authentication methods:',
|
|
62
|
-
methodOptions,
|
|
63
|
-
['email', 'google']
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// Advanced auth features
|
|
67
|
-
const featureOptions = [
|
|
68
|
-
{ label: 'Multi-factor authentication (MFA)', value: 'mfa' },
|
|
69
|
-
{ label: 'Role-based access control (RBAC)', value: 'rbac' },
|
|
70
|
-
{ label: 'Organization/Team support', value: 'orgs' },
|
|
71
|
-
{ label: 'Session management', value: 'sessions' },
|
|
72
|
-
{ label: 'Audit logging', value: 'audit' }
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
answers.authFeatures = await askMultiSelect(
|
|
76
|
-
rl,
|
|
77
|
-
'Advanced auth features:',
|
|
78
|
-
featureOptions,
|
|
79
|
-
[]
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
return answers;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = {
|
|
86
|
-
title,
|
|
87
|
-
description,
|
|
88
|
-
run
|
|
89
|
-
};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Backend Stack Section
|
|
3
|
-
*
|
|
4
|
-
* API patterns, background jobs, storage, and services.
|
|
5
|
-
*
|
|
6
|
-
* @package bootspring
|
|
7
|
-
* @module generators/sections/backend
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const title = 'Backend Stack';
|
|
11
|
-
const description = 'API and server-side choices';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Run the backend section
|
|
15
|
-
*/
|
|
16
|
-
async function run(rl, previousAnswers, helpers) {
|
|
17
|
-
const { askChoice, askYesNo } = helpers;
|
|
18
|
-
const answers = {};
|
|
19
|
-
|
|
20
|
-
// API Style
|
|
21
|
-
const apiOptions = [
|
|
22
|
-
{ label: 'REST', value: 'rest', description: 'Traditional REST API' },
|
|
23
|
-
{ label: 'tRPC', value: 'trpc', description: 'End-to-end type safety' },
|
|
24
|
-
{ label: 'GraphQL', value: 'graphql', description: 'Query language' },
|
|
25
|
-
{ label: 'Server Actions', value: 'server-actions', description: 'Next.js Server Actions' },
|
|
26
|
-
{ label: 'Hybrid', value: 'hybrid', description: 'Mix of approaches' }
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
// Default based on framework
|
|
30
|
-
const isNextjs = previousAnswers.framework === 'nextjs';
|
|
31
|
-
const defaultApi = isNextjs ? 3 : 0; // Server Actions for Next.js, REST otherwise
|
|
32
|
-
|
|
33
|
-
answers.apiStyle = await askChoice(
|
|
34
|
-
rl,
|
|
35
|
-
'API style:',
|
|
36
|
-
apiOptions,
|
|
37
|
-
defaultApi
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
// Validation
|
|
41
|
-
const validationOptions = [
|
|
42
|
-
{ label: 'Zod', value: 'zod', description: 'TypeScript-first (Recommended)' },
|
|
43
|
-
{ label: 'Yup', value: 'yup', description: 'Popular schema builder' },
|
|
44
|
-
{ label: 'Joi', value: 'joi', description: 'Enterprise validation' },
|
|
45
|
-
{ label: 'Custom', value: 'custom', description: 'Roll your own' }
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
answers.validation = await askChoice(
|
|
49
|
-
rl,
|
|
50
|
-
'Validation library:',
|
|
51
|
-
validationOptions,
|
|
52
|
-
0
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Background Jobs
|
|
56
|
-
answers.enableBackgroundJobs = await askYesNo(
|
|
57
|
-
rl,
|
|
58
|
-
'Need background jobs/queues?',
|
|
59
|
-
false
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
if (answers.enableBackgroundJobs) {
|
|
63
|
-
const jobOptions = [
|
|
64
|
-
{ label: 'Inngest', value: 'inngest', description: 'Serverless functions' },
|
|
65
|
-
{ label: 'Trigger.dev', value: 'trigger', description: 'Background jobs platform' },
|
|
66
|
-
{ label: 'BullMQ', value: 'bullmq', description: 'Redis-based queues' },
|
|
67
|
-
{ label: 'Quirrel', value: 'quirrel', description: 'Job scheduling' }
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
answers.jobProcessor = await askChoice(
|
|
71
|
-
rl,
|
|
72
|
-
'Job processor:',
|
|
73
|
-
jobOptions,
|
|
74
|
-
0
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// File Storage
|
|
79
|
-
answers.enableFileStorage = await askYesNo(
|
|
80
|
-
rl,
|
|
81
|
-
'Need file uploads/storage?',
|
|
82
|
-
false
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
if (answers.enableFileStorage) {
|
|
86
|
-
const storageOptions = [
|
|
87
|
-
{ label: 'Uploadthing', value: 'uploadthing', description: 'Easy file uploads' },
|
|
88
|
-
{ label: 'Cloudflare R2', value: 'r2', description: 'S3-compatible, cheap' },
|
|
89
|
-
{ label: 'AWS S3', value: 's3', description: 'Industry standard' },
|
|
90
|
-
{ label: 'Vercel Blob', value: 'vercel-blob', description: 'Vercel storage' }
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
answers.fileStorage = await askChoice(
|
|
94
|
-
rl,
|
|
95
|
-
'File storage:',
|
|
96
|
-
storageOptions,
|
|
97
|
-
0
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Caching
|
|
102
|
-
const cacheOptions = [
|
|
103
|
-
{ label: 'None', value: 'none', description: 'No caching layer' },
|
|
104
|
-
{ label: 'Redis / Upstash', value: 'redis', description: 'In-memory cache' },
|
|
105
|
-
{ label: 'Vercel KV', value: 'vercel-kv', description: 'Vercel Redis' },
|
|
106
|
-
{ label: 'Cloudflare KV', value: 'cloudflare-kv', description: 'Edge KV' }
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
answers.caching = await askChoice(
|
|
110
|
-
rl,
|
|
111
|
-
'Caching layer:',
|
|
112
|
-
cacheOptions,
|
|
113
|
-
0
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
// Email
|
|
117
|
-
answers.enableEmail = await askYesNo(
|
|
118
|
-
rl,
|
|
119
|
-
'Need email sending?',
|
|
120
|
-
false
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
if (answers.enableEmail) {
|
|
124
|
-
const emailOptions = [
|
|
125
|
-
{ label: 'Resend', value: 'resend', description: 'Modern email API' },
|
|
126
|
-
{ label: 'SendGrid', value: 'sendgrid', description: 'Popular email service' },
|
|
127
|
-
{ label: 'Postmark', value: 'postmark', description: 'Transactional email' },
|
|
128
|
-
{ label: 'AWS SES', value: 'ses', description: 'Amazon email service' }
|
|
129
|
-
];
|
|
130
|
-
|
|
131
|
-
answers.emailProvider = await askChoice(
|
|
132
|
-
rl,
|
|
133
|
-
'Email provider:',
|
|
134
|
-
emailOptions,
|
|
135
|
-
0
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return answers;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
module.exports = {
|
|
143
|
-
title,
|
|
144
|
-
description,
|
|
145
|
-
run
|
|
146
|
-
};
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Business Context Section
|
|
3
|
-
*
|
|
4
|
-
* Collects business model, pricing, and market information.
|
|
5
|
-
* Only included in full preset.
|
|
6
|
-
*
|
|
7
|
-
* @package bootspring
|
|
8
|
-
* @module generators/sections/business
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const title = 'Business Context';
|
|
12
|
-
const description = 'Optional business information for better context';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Skip in minimal and standard presets
|
|
16
|
-
*/
|
|
17
|
-
function shouldSkip(_previousAnswers) {
|
|
18
|
-
// This section is only in 'full' preset, so no need to check
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Run the business section
|
|
24
|
-
*/
|
|
25
|
-
async function run(rl, previousAnswers, helpers) {
|
|
26
|
-
const { askChoice, askText, askYesNo } = helpers;
|
|
27
|
-
|
|
28
|
-
const answers = {};
|
|
29
|
-
|
|
30
|
-
console.log('\nThis helps generate better business context in CLAUDE.md');
|
|
31
|
-
|
|
32
|
-
// Business model
|
|
33
|
-
answers.businessModel = await askChoice(
|
|
34
|
-
rl,
|
|
35
|
-
'Business model:',
|
|
36
|
-
[
|
|
37
|
-
{ label: 'SaaS', value: 'saas', description: 'Software as a Service' },
|
|
38
|
-
{ label: 'Marketplace', value: 'marketplace', description: 'Two-sided marketplace' },
|
|
39
|
-
{ label: 'E-commerce', value: 'ecommerce', description: 'Online store' },
|
|
40
|
-
{ label: 'Consumer App', value: 'consumer', description: 'B2C application' },
|
|
41
|
-
{ label: 'Enterprise', value: 'enterprise', description: 'B2B enterprise' },
|
|
42
|
-
{ label: 'Open Source', value: 'opensource', description: 'Open source project' },
|
|
43
|
-
{ label: 'Internal Tool', value: 'internal', description: 'Internal company tool' },
|
|
44
|
-
{ label: 'Other', value: 'other', description: 'Something else' }
|
|
45
|
-
],
|
|
46
|
-
0
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// Pricing strategy (if commercial)
|
|
50
|
-
if (!['opensource', 'internal'].includes(answers.businessModel)) {
|
|
51
|
-
answers.pricingStrategy = await askChoice(
|
|
52
|
-
rl,
|
|
53
|
-
'Pricing strategy:',
|
|
54
|
-
[
|
|
55
|
-
{ label: 'Freemium', value: 'freemium', description: 'Free tier + paid upgrades' },
|
|
56
|
-
{ label: 'Subscription', value: 'subscription', description: 'Monthly/yearly plans' },
|
|
57
|
-
{ label: 'Usage-based', value: 'usage', description: 'Pay per use' },
|
|
58
|
-
{ label: 'One-time', value: 'one-time', description: 'Single purchase' },
|
|
59
|
-
{ label: 'Free', value: 'free', description: 'Completely free' },
|
|
60
|
-
{ label: 'Undecided', value: 'undecided', description: "Haven't decided yet" }
|
|
61
|
-
],
|
|
62
|
-
0
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// Target market
|
|
66
|
-
answers.targetMarket = await askText(
|
|
67
|
-
rl,
|
|
68
|
-
'Target market (who are your users?)',
|
|
69
|
-
''
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
// Key differentiators
|
|
73
|
-
answers.differentiators = await askText(
|
|
74
|
-
rl,
|
|
75
|
-
'Key differentiator (what makes you unique?)',
|
|
76
|
-
''
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Competitors
|
|
81
|
-
const hasCompetitors = await askYesNo(
|
|
82
|
-
rl,
|
|
83
|
-
'Want to note competitors for reference?',
|
|
84
|
-
false
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
if (hasCompetitors) {
|
|
88
|
-
answers.competitors = await askText(
|
|
89
|
-
rl,
|
|
90
|
-
'Main competitors (comma-separated)',
|
|
91
|
-
''
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Launch timeline
|
|
96
|
-
answers.launchTimeline = await askChoice(
|
|
97
|
-
rl,
|
|
98
|
-
'Launch timeline:',
|
|
99
|
-
[
|
|
100
|
-
{ label: 'Already launched', value: 'launched' },
|
|
101
|
-
{ label: 'This month', value: 'this-month' },
|
|
102
|
-
{ label: '1-3 months', value: '1-3-months' },
|
|
103
|
-
{ label: '3-6 months', value: '3-6-months' },
|
|
104
|
-
{ label: '6+ months', value: '6-plus-months' },
|
|
105
|
-
{ label: 'No timeline', value: 'no-timeline' }
|
|
106
|
-
],
|
|
107
|
-
2
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return answers;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports = {
|
|
114
|
-
title,
|
|
115
|
-
description,
|
|
116
|
-
shouldSkip,
|
|
117
|
-
run
|
|
118
|
-
};
|