popeye-cli 1.4.7 → 1.6.0

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 (214) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +264 -63
  3. package/dist/adapters/gemini.d.ts +1 -0
  4. package/dist/adapters/gemini.d.ts.map +1 -1
  5. package/dist/adapters/gemini.js +9 -4
  6. package/dist/adapters/gemini.js.map +1 -1
  7. package/dist/adapters/grok.d.ts +1 -0
  8. package/dist/adapters/grok.d.ts.map +1 -1
  9. package/dist/adapters/grok.js +9 -4
  10. package/dist/adapters/grok.js.map +1 -1
  11. package/dist/adapters/openai.d.ts +1 -1
  12. package/dist/adapters/openai.d.ts.map +1 -1
  13. package/dist/adapters/openai.js +35 -9
  14. package/dist/adapters/openai.js.map +1 -1
  15. package/dist/cli/commands/create.d.ts.map +1 -1
  16. package/dist/cli/commands/create.js +54 -4
  17. package/dist/cli/commands/create.js.map +1 -1
  18. package/dist/cli/interactive.d.ts +29 -0
  19. package/dist/cli/interactive.d.ts.map +1 -1
  20. package/dist/cli/interactive.js +132 -7
  21. package/dist/cli/interactive.js.map +1 -1
  22. package/dist/generators/all.d.ts +8 -2
  23. package/dist/generators/all.d.ts.map +1 -1
  24. package/dist/generators/all.js +37 -316
  25. package/dist/generators/all.js.map +1 -1
  26. package/dist/generators/doc-parser.d.ts +64 -0
  27. package/dist/generators/doc-parser.d.ts.map +1 -0
  28. package/dist/generators/doc-parser.js +407 -0
  29. package/dist/generators/doc-parser.js.map +1 -0
  30. package/dist/generators/frontend-design-analyzer.d.ts +30 -0
  31. package/dist/generators/frontend-design-analyzer.d.ts.map +1 -0
  32. package/dist/generators/frontend-design-analyzer.js +208 -0
  33. package/dist/generators/frontend-design-analyzer.js.map +1 -0
  34. package/dist/generators/shared-packages.d.ts +45 -0
  35. package/dist/generators/shared-packages.d.ts.map +1 -0
  36. package/dist/generators/shared-packages.js +456 -0
  37. package/dist/generators/shared-packages.js.map +1 -0
  38. package/dist/generators/templates/index.d.ts +8 -0
  39. package/dist/generators/templates/index.d.ts.map +1 -1
  40. package/dist/generators/templates/index.js +8 -0
  41. package/dist/generators/templates/index.js.map +1 -1
  42. package/dist/generators/templates/website-components.d.ts +33 -0
  43. package/dist/generators/templates/website-components.d.ts.map +1 -0
  44. package/dist/generators/templates/website-components.js +303 -0
  45. package/dist/generators/templates/website-components.js.map +1 -0
  46. package/dist/generators/templates/website-config.d.ts +55 -0
  47. package/dist/generators/templates/website-config.d.ts.map +1 -0
  48. package/dist/generators/templates/website-config.js +425 -0
  49. package/dist/generators/templates/website-config.js.map +1 -0
  50. package/dist/generators/templates/website-conversion.d.ts +27 -0
  51. package/dist/generators/templates/website-conversion.d.ts.map +1 -0
  52. package/dist/generators/templates/website-conversion.js +326 -0
  53. package/dist/generators/templates/website-conversion.js.map +1 -0
  54. package/dist/generators/templates/website-landing.d.ts +24 -0
  55. package/dist/generators/templates/website-landing.d.ts.map +1 -0
  56. package/dist/generators/templates/website-landing.js +276 -0
  57. package/dist/generators/templates/website-landing.js.map +1 -0
  58. package/dist/generators/templates/website-layout.d.ts +42 -0
  59. package/dist/generators/templates/website-layout.d.ts.map +1 -0
  60. package/dist/generators/templates/website-layout.js +408 -0
  61. package/dist/generators/templates/website-layout.js.map +1 -0
  62. package/dist/generators/templates/website-pricing.d.ts +11 -0
  63. package/dist/generators/templates/website-pricing.d.ts.map +1 -0
  64. package/dist/generators/templates/website-pricing.js +313 -0
  65. package/dist/generators/templates/website-pricing.js.map +1 -0
  66. package/dist/generators/templates/website-sections.d.ts +102 -0
  67. package/dist/generators/templates/website-sections.d.ts.map +1 -0
  68. package/dist/generators/templates/website-sections.js +444 -0
  69. package/dist/generators/templates/website-sections.js.map +1 -0
  70. package/dist/generators/templates/website-seo.d.ts +76 -0
  71. package/dist/generators/templates/website-seo.d.ts.map +1 -0
  72. package/dist/generators/templates/website-seo.js +326 -0
  73. package/dist/generators/templates/website-seo.js.map +1 -0
  74. package/dist/generators/templates/website.d.ts +10 -83
  75. package/dist/generators/templates/website.d.ts.map +1 -1
  76. package/dist/generators/templates/website.js +12 -875
  77. package/dist/generators/templates/website.js.map +1 -1
  78. package/dist/generators/website-content-scanner.d.ts +37 -0
  79. package/dist/generators/website-content-scanner.d.ts.map +1 -0
  80. package/dist/generators/website-content-scanner.js +165 -0
  81. package/dist/generators/website-content-scanner.js.map +1 -0
  82. package/dist/generators/website-context.d.ts +119 -0
  83. package/dist/generators/website-context.d.ts.map +1 -0
  84. package/dist/generators/website-context.js +350 -0
  85. package/dist/generators/website-context.js.map +1 -0
  86. package/dist/generators/website-debug.d.ts +68 -0
  87. package/dist/generators/website-debug.d.ts.map +1 -0
  88. package/dist/generators/website-debug.js +93 -0
  89. package/dist/generators/website-debug.js.map +1 -0
  90. package/dist/generators/website.d.ts +5 -0
  91. package/dist/generators/website.d.ts.map +1 -1
  92. package/dist/generators/website.js +136 -11
  93. package/dist/generators/website.js.map +1 -1
  94. package/dist/generators/workspace-root.d.ts +27 -0
  95. package/dist/generators/workspace-root.d.ts.map +1 -0
  96. package/dist/generators/workspace-root.js +100 -0
  97. package/dist/generators/workspace-root.js.map +1 -0
  98. package/dist/state/index.d.ts +35 -0
  99. package/dist/state/index.d.ts.map +1 -1
  100. package/dist/state/index.js +40 -0
  101. package/dist/state/index.js.map +1 -1
  102. package/dist/types/consensus.d.ts +3 -0
  103. package/dist/types/consensus.d.ts.map +1 -1
  104. package/dist/types/consensus.js +1 -0
  105. package/dist/types/consensus.js.map +1 -1
  106. package/dist/types/website-strategy.d.ts +263 -0
  107. package/dist/types/website-strategy.d.ts.map +1 -0
  108. package/dist/types/website-strategy.js +105 -0
  109. package/dist/types/website-strategy.js.map +1 -0
  110. package/dist/types/workflow.d.ts +21 -0
  111. package/dist/types/workflow.d.ts.map +1 -1
  112. package/dist/types/workflow.js +8 -0
  113. package/dist/types/workflow.js.map +1 -1
  114. package/dist/upgrade/handlers.d.ts +15 -0
  115. package/dist/upgrade/handlers.d.ts.map +1 -1
  116. package/dist/upgrade/handlers.js +52 -0
  117. package/dist/upgrade/handlers.js.map +1 -1
  118. package/dist/workflow/auto-fix-bundler.d.ts +37 -0
  119. package/dist/workflow/auto-fix-bundler.d.ts.map +1 -0
  120. package/dist/workflow/auto-fix-bundler.js +320 -0
  121. package/dist/workflow/auto-fix-bundler.js.map +1 -0
  122. package/dist/workflow/auto-fix.d.ts.map +1 -1
  123. package/dist/workflow/auto-fix.js +10 -3
  124. package/dist/workflow/auto-fix.js.map +1 -1
  125. package/dist/workflow/consensus.d.ts.map +1 -1
  126. package/dist/workflow/consensus.js +2 -0
  127. package/dist/workflow/consensus.js.map +1 -1
  128. package/dist/workflow/execution-mode.d.ts.map +1 -1
  129. package/dist/workflow/execution-mode.js +18 -0
  130. package/dist/workflow/execution-mode.js.map +1 -1
  131. package/dist/workflow/index.d.ts +4 -0
  132. package/dist/workflow/index.d.ts.map +1 -1
  133. package/dist/workflow/index.js +37 -0
  134. package/dist/workflow/index.js.map +1 -1
  135. package/dist/workflow/overview.d.ts +89 -0
  136. package/dist/workflow/overview.d.ts.map +1 -0
  137. package/dist/workflow/overview.js +358 -0
  138. package/dist/workflow/overview.js.map +1 -0
  139. package/dist/workflow/plan-mode.d.ts +6 -4
  140. package/dist/workflow/plan-mode.d.ts.map +1 -1
  141. package/dist/workflow/plan-mode.js +148 -6
  142. package/dist/workflow/plan-mode.js.map +1 -1
  143. package/dist/workflow/website-strategy.d.ts +79 -0
  144. package/dist/workflow/website-strategy.d.ts.map +1 -0
  145. package/dist/workflow/website-strategy.js +310 -0
  146. package/dist/workflow/website-strategy.js.map +1 -0
  147. package/dist/workflow/website-updater.d.ts +17 -0
  148. package/dist/workflow/website-updater.d.ts.map +1 -0
  149. package/dist/workflow/website-updater.js +116 -0
  150. package/dist/workflow/website-updater.js.map +1 -0
  151. package/dist/workflow/workflow-logger.d.ts +1 -1
  152. package/dist/workflow/workflow-logger.d.ts.map +1 -1
  153. package/dist/workflow/workflow-logger.js.map +1 -1
  154. package/package.json +1 -1
  155. package/src/adapters/gemini.ts +10 -4
  156. package/src/adapters/grok.ts +10 -4
  157. package/src/adapters/openai.ts +38 -6
  158. package/src/cli/commands/create.ts +58 -4
  159. package/src/cli/interactive.ts +143 -7
  160. package/src/generators/all.ts +49 -332
  161. package/src/generators/doc-parser.ts +449 -0
  162. package/src/generators/frontend-design-analyzer.ts +261 -0
  163. package/src/generators/shared-packages.ts +500 -0
  164. package/src/generators/templates/index.ts +8 -0
  165. package/src/generators/templates/website-components.ts +330 -0
  166. package/src/generators/templates/website-config.ts +444 -0
  167. package/src/generators/templates/website-conversion.ts +341 -0
  168. package/src/generators/templates/website-landing.ts +331 -0
  169. package/src/generators/templates/website-layout.ts +443 -0
  170. package/src/generators/templates/website-pricing.ts +330 -0
  171. package/src/generators/templates/website-sections.ts +541 -0
  172. package/src/generators/templates/website-seo.ts +370 -0
  173. package/src/generators/templates/website.ts +38 -905
  174. package/src/generators/website-content-scanner.ts +208 -0
  175. package/src/generators/website-context.ts +493 -0
  176. package/src/generators/website-debug.ts +130 -0
  177. package/src/generators/website.ts +178 -20
  178. package/src/generators/workspace-root.ts +113 -0
  179. package/src/state/index.ts +56 -0
  180. package/src/types/consensus.ts +3 -0
  181. package/src/types/website-strategy.ts +243 -0
  182. package/src/types/workflow.ts +21 -0
  183. package/src/upgrade/handlers.ts +65 -0
  184. package/src/workflow/auto-fix-bundler.ts +392 -0
  185. package/src/workflow/auto-fix.ts +11 -3
  186. package/src/workflow/consensus.ts +2 -0
  187. package/src/workflow/execution-mode.ts +21 -0
  188. package/src/workflow/index.ts +37 -0
  189. package/src/workflow/overview.ts +475 -0
  190. package/src/workflow/plan-mode.ts +193 -8
  191. package/src/workflow/website-strategy.ts +379 -0
  192. package/src/workflow/website-updater.ts +142 -0
  193. package/src/workflow/workflow-logger.ts +1 -0
  194. package/tests/adapters/persona-switching.test.ts +63 -0
  195. package/tests/cli/project-naming.test.ts +136 -0
  196. package/tests/generators/doc-parser.test.ts +121 -0
  197. package/tests/generators/frontend-design-analyzer.test.ts +90 -0
  198. package/tests/generators/quality-gate.test.ts +183 -0
  199. package/tests/generators/shared-packages.test.ts +83 -0
  200. package/tests/generators/website-components.test.ts +159 -0
  201. package/tests/generators/website-config.test.ts +84 -0
  202. package/tests/generators/website-content-scanner.test.ts +181 -0
  203. package/tests/generators/website-context.test.ts +331 -0
  204. package/tests/generators/website-debug.test.ts +77 -0
  205. package/tests/generators/website-landing.test.ts +188 -0
  206. package/tests/generators/website-pricing.test.ts +98 -0
  207. package/tests/generators/website-sections.test.ts +245 -0
  208. package/tests/generators/website-seo-quality.test.ts +246 -0
  209. package/tests/generators/workspace-root.test.ts +105 -0
  210. package/tests/upgrade/handlers.test.ts +162 -0
  211. package/tests/workflow/auto-fix-bundler.test.ts +242 -0
  212. package/tests/workflow/overview.test.ts +392 -0
  213. package/tests/workflow/plan-mode.test.ts +111 -1
  214. package/tests/workflow/website-strategy.test.ts +246 -0
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Pricing page generator with monthly/annual toggle, feature comparison,
3
+ * pricing FAQ, and enterprise CTA section
4
+ */
5
+ /**
6
+ * Escape a string for safe use inside JSX template literals
7
+ */
8
+ function escapeJsx(str) {
9
+ return str
10
+ .replace(/\\/g, '\\\\')
11
+ .replace(/'/g, "\\'")
12
+ .replace(/`/g, '\\`')
13
+ .replace(/\$/g, '\\$');
14
+ }
15
+ /**
16
+ * Generate pricing page with optional context-driven tiers, comparison, and FAQ
17
+ * Rendered as client component for monthly/annual toggle
18
+ */
19
+ export function generateWebsitePricingPage(_projectName, context) {
20
+ const strategy = context?.strategy;
21
+ const tiers = context?.pricing && context.pricing.length > 0
22
+ ? context.pricing
23
+ : null;
24
+ // Build tiers array
25
+ const tiersBlock = tiers
26
+ ? tiers.map((t) => {
27
+ const featuresStr = t.features.map((f) => ` '${escapeJsx(f)}'`).join(',\n');
28
+ return ` {
29
+ name: '${escapeJsx(t.name)}',
30
+ price: '${escapeJsx(t.price)}',
31
+ period: '${t.period ? escapeJsx(t.period) : '/month'}',
32
+ description: '${escapeJsx(t.description)}',
33
+ features: [
34
+ ${featuresStr}
35
+ ],
36
+ cta: '${escapeJsx(t.cta)}',
37
+ featured: ${t.featured ? 'true' : 'false'},
38
+ }`;
39
+ }).join(',\n')
40
+ : ` {
41
+ name: 'Starter',
42
+ price: 'Free',
43
+ period: '',
44
+ description: 'Perfect for getting started',
45
+ features: ['Core features', 'Community support', 'Basic analytics'],
46
+ cta: 'Get started',
47
+ featured: false,
48
+ },
49
+ {
50
+ name: 'Pro',
51
+ price: '$29',
52
+ period: '/month',
53
+ description: 'For growing teams',
54
+ features: ['Everything in Starter', 'Priority support', 'Advanced analytics', 'Custom integrations'],
55
+ cta: 'Start free trial',
56
+ featured: true,
57
+ },
58
+ {
59
+ name: 'Enterprise',
60
+ price: 'Custom',
61
+ period: '',
62
+ description: 'For large organizations',
63
+ features: ['Everything in Pro', 'Dedicated support', 'SLA guarantee', 'Custom contracts'],
64
+ cta: 'Contact sales',
65
+ featured: false,
66
+ }`;
67
+ // Enterprise CTA from strategy
68
+ const enterpriseCtaText = strategy?.conversionStrategy.primaryCta.text || 'Contact Sales';
69
+ // Build feature comparison data if tiers have features
70
+ const hasComparison = tiers && tiers.some(t => t.features.length > 0);
71
+ const allFeatureNames = new Set();
72
+ if (tiers) {
73
+ for (const tier of tiers) {
74
+ for (const feature of tier.features) {
75
+ // Normalize feature name (remove "FeatureName: value" to just "FeatureName")
76
+ const name = feature.includes(':') ? feature.split(':')[0].trim() : feature;
77
+ allFeatureNames.add(name);
78
+ }
79
+ }
80
+ }
81
+ const comparisonFeatures = Array.from(allFeatureNames).slice(0, 10);
82
+ const comparisonBlock = hasComparison ? buildComparisonTable(comparisonFeatures, tiers) : '';
83
+ // Pricing FAQ
84
+ const pricingFaq = [
85
+ { q: 'Can I switch plans later?', a: 'Yes, you can upgrade or downgrade your plan at any time. Changes take effect on your next billing cycle.' },
86
+ { q: 'Is there a free trial?', a: 'Yes, all paid plans come with a 14-day free trial. No credit card required.' },
87
+ { q: 'What payment methods do you accept?', a: 'We accept all major credit cards, PayPal, and bank transfers for enterprise plans.' },
88
+ ];
89
+ const faqStr = pricingFaq
90
+ .map(item => ` { question: '${escapeJsx(item.q)}', answer: '${escapeJsx(item.a)}' }`)
91
+ .join(',\n');
92
+ return `'use client';
93
+
94
+ import { useState } from 'react';
95
+ import Link from 'next/link';
96
+ import { Check, ChevronDown } from 'lucide-react';
97
+ import Header from '@/components/Header';
98
+ import Footer from '@/components/Footer';
99
+
100
+ const tiers = [
101
+ ${tiersBlock}
102
+ ];
103
+
104
+ const pricingFaq = [
105
+ ${faqStr}
106
+ ];
107
+
108
+ function FaqItem({ question, answer }: { question: string; answer: string }) {
109
+ const [open, setOpen] = useState(false);
110
+
111
+ return (
112
+ <div className="py-4">
113
+ <button
114
+ type="button"
115
+ className="flex w-full items-center justify-between text-left"
116
+ onClick={() => setOpen(!open)}
117
+ aria-expanded={open}
118
+ >
119
+ <span className="text-base font-medium text-foreground">{question}</span>
120
+ <ChevronDown className={\`h-5 w-5 text-muted-foreground transition-transform \${open ? 'rotate-180' : ''}\`} />
121
+ </button>
122
+ {open && (
123
+ <p className="mt-3 text-muted-foreground">{answer}</p>
124
+ )}
125
+ </div>
126
+ );
127
+ }
128
+
129
+ export default function PricingPage() {
130
+ const [annual, setAnnual] = useState(false);
131
+
132
+ return (
133
+ <>
134
+ <Header />
135
+ <main className="py-20 sm:py-32">
136
+ <div className="container">
137
+ {/* Header */}
138
+ <div className="mx-auto max-w-2xl text-center">
139
+ <h1 className="text-4xl font-bold tracking-tight text-foreground sm:text-5xl">
140
+ Simple, transparent pricing
141
+ </h1>
142
+ <p className="mt-6 text-lg text-muted-foreground">
143
+ Choose the plan that works best for you. All plans include a 14-day free trial.
144
+ </p>
145
+
146
+ {/* Monthly/Annual Toggle */}
147
+ <div className="mt-8 flex items-center justify-center gap-3">
148
+ <span className={\`text-sm font-medium \${!annual ? 'text-foreground' : 'text-muted-foreground'}\`}>
149
+ Monthly
150
+ </span>
151
+ <button
152
+ type="button"
153
+ role="switch"
154
+ aria-checked={annual}
155
+ onClick={() => setAnnual(!annual)}
156
+ className={\`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors \${
157
+ annual ? 'bg-primary-600' : 'bg-muted'
158
+ }\`}
159
+ >
160
+ <span className={\`pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition-transform \${
161
+ annual ? 'translate-x-5' : 'translate-x-0'
162
+ }\`} />
163
+ </button>
164
+ <span className={\`text-sm font-medium \${annual ? 'text-foreground' : 'text-muted-foreground'}\`}>
165
+ Annual
166
+ <span className="ml-1.5 inline-block rounded-full bg-primary-100 px-2 py-0.5 text-xs font-semibold text-primary-700">
167
+ Save 20%
168
+ </span>
169
+ </span>
170
+ </div>
171
+ </div>
172
+
173
+ {/* Tier Cards */}
174
+ <div className="mx-auto mt-16 grid max-w-lg grid-cols-1 gap-8 lg:max-w-5xl lg:grid-cols-3">
175
+ {tiers.map((tier) => (
176
+ <div
177
+ key={tier.name}
178
+ className={\`relative rounded-2xl p-8 transition-shadow hover:shadow-lg \${
179
+ tier.featured
180
+ ? 'border-2 border-primary-600 bg-card shadow-lg'
181
+ : 'border border-border bg-card'
182
+ }\`}
183
+ >
184
+ {tier.featured && (
185
+ <div className="absolute -top-4 left-1/2 -translate-x-1/2">
186
+ <span className="rounded-full bg-primary-600 px-4 py-1 text-sm font-semibold text-white">
187
+ Most Popular
188
+ </span>
189
+ </div>
190
+ )}
191
+ <h2 className="text-lg font-semibold text-foreground">
192
+ {tier.name}
193
+ </h2>
194
+ <p className="mt-2 text-sm text-muted-foreground">
195
+ {tier.description}
196
+ </p>
197
+ <p className="mt-6">
198
+ <span className="text-4xl font-bold text-foreground">
199
+ {tier.price === 'Custom' || tier.price === 'Free'
200
+ ? tier.price
201
+ : annual
202
+ ? \`$\${Math.round(parseFloat(tier.price.replace('$', '')) * 0.8)}\`
203
+ : tier.price}
204
+ </span>
205
+ {tier.period && tier.price !== 'Custom' && tier.price !== 'Free' && (
206
+ <span className="text-sm text-muted-foreground">
207
+ {annual ? '/month, billed annually' : tier.period}
208
+ </span>
209
+ )}
210
+ </p>
211
+ <ul className="mt-8 space-y-4">
212
+ {tier.features.map((feature) => (
213
+ <li key={feature} className="flex text-sm text-muted-foreground">
214
+ <Check className="h-5 w-5 flex-shrink-0 text-primary-600" />
215
+ <span className="ml-3">{feature}</span>
216
+ </li>
217
+ ))}
218
+ </ul>
219
+ <button
220
+ className={\`mt-8 w-full rounded-lg px-4 py-2.5 text-sm font-semibold transition-colors \${
221
+ tier.featured
222
+ ? 'bg-primary-600 text-white hover:bg-primary-500 shadow-lg shadow-primary-600/25'
223
+ : 'bg-card text-foreground border border-border hover:bg-muted'
224
+ }\`}
225
+ >
226
+ {tier.cta}
227
+ </button>
228
+ </div>
229
+ ))}
230
+ </div>
231
+
232
+ ${comparisonBlock}
233
+
234
+ {/* Pricing FAQ */}
235
+ <div className="mx-auto mt-20 max-w-3xl">
236
+ <h2 className="text-2xl font-bold text-foreground text-center">
237
+ Pricing FAQ
238
+ </h2>
239
+ <div className="mt-8 divide-y divide-border">
240
+ {pricingFaq.map((item, i) => (
241
+ <FaqItem key={i} question={item.question} answer={item.answer} />
242
+ ))}
243
+ </div>
244
+ </div>
245
+
246
+ {/* Enterprise CTA */}
247
+ <div className="mx-auto mt-20 max-w-2xl rounded-2xl bg-muted/50 p-8 text-center sm:p-12">
248
+ <h2 className="text-2xl font-bold text-foreground">
249
+ Need a custom plan?
250
+ </h2>
251
+ <p className="mt-4 text-muted-foreground">
252
+ Contact our sales team for enterprise pricing, custom contracts, and dedicated support.
253
+ </p>
254
+ <Link
255
+ href="/contact"
256
+ className="mt-6 inline-block rounded-lg border border-primary-600 px-6 py-3 text-sm font-semibold text-primary-600 hover:bg-primary-50 transition-colors"
257
+ >
258
+ ${escapeJsx(enterpriseCtaText)}
259
+ </Link>
260
+ </div>
261
+ </div>
262
+ </main>
263
+ <Footer />
264
+ </>
265
+ );
266
+ }
267
+ `;
268
+ }
269
+ /**
270
+ * Build feature comparison table section
271
+ */
272
+ function buildComparisonTable(featureNames, tiers) {
273
+ if (featureNames.length === 0)
274
+ return '';
275
+ return `
276
+ {/* Feature Comparison */}
277
+ <div className="mx-auto mt-20 max-w-5xl">
278
+ <h2 className="text-2xl font-bold text-foreground text-center">
279
+ Compare plans
280
+ </h2>
281
+ <div className="mt-8 overflow-x-auto">
282
+ <table className="w-full border-collapse text-sm">
283
+ <thead>
284
+ <tr className="border-b border-border">
285
+ <th className="py-4 pr-4 text-left font-medium text-muted-foreground">Feature</th>
286
+ ${tiers.map(t => ` <th className="px-4 py-4 text-center font-medium text-foreground">${escapeJsx(t.name)}</th>`).join('\n')}
287
+ </tr>
288
+ </thead>
289
+ <tbody>
290
+ ${featureNames.map(feature => {
291
+ const cells = tiers.map(t => {
292
+ const hasFeature = t.features.some(f => f.startsWith(feature));
293
+ const featureValue = t.features.find(f => f.startsWith(feature));
294
+ const value = featureValue && featureValue.includes(':')
295
+ ? featureValue.split(':')[1].trim()
296
+ : hasFeature ? 'check' : 'no';
297
+ return value === 'check'
298
+ ? ' <td className="px-4 py-3 text-center"><Check className="mx-auto h-5 w-5 text-primary-600" /></td>'
299
+ : value === 'no'
300
+ ? ' <td className="px-4 py-3 text-center text-muted-foreground">&mdash;</td>'
301
+ : ` <td className="px-4 py-3 text-center text-foreground">${escapeJsx(value)}</td>`;
302
+ });
303
+ return ` <tr className="border-b border-border">
304
+ <td className="py-3 pr-4 font-medium text-foreground">${escapeJsx(feature)}</td>
305
+ ${cells.join('\n')}
306
+ </tr>`;
307
+ }).join('\n')}
308
+ </tbody>
309
+ </table>
310
+ </div>
311
+ </div>`;
312
+ }
313
+ //# sourceMappingURL=website-pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-pricing.js","sourceRoot":"","sources":["../../../src/generators/templates/website-pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Reusable website section generators
3
+ * Pain Points, Value Proposition, How It Works, Stats/Proof Points, FAQ
4
+ * Each section is data-driven with graceful skip when data is missing
5
+ */
6
+ import type { WebsiteContentContext } from '../website-context.js';
7
+ import type { WebsiteStrategyDocument } from '../../types/website-strategy.js';
8
+ /**
9
+ * Section render metadata for debug tracing
10
+ */
11
+ export interface SectionRenderInfo {
12
+ name: string;
13
+ dataSource: 'strategy' | 'docs' | 'defaults' | 'skipped';
14
+ itemCount: number;
15
+ }
16
+ /**
17
+ * Map a feature title to a lucide-react icon name by keyword matching
18
+ */
19
+ export declare function mapFeatureIcon(title: string): string;
20
+ /**
21
+ * Check if a proof point string contains a numeric metric
22
+ * Numeric metrics are safe to display as stats; qualitative ones become badges
23
+ */
24
+ export declare function isNumericMetric(point: string): boolean;
25
+ /**
26
+ * Generate Pain Points section
27
+ * Data: strategy.icp.painPoints
28
+ * Skip: if painPoints is empty
29
+ */
30
+ export declare function generatePainPointsSection(strategy?: WebsiteStrategyDocument): {
31
+ jsx: string;
32
+ info: SectionRenderInfo;
33
+ };
34
+ /**
35
+ * Generate Value Proposition / Differentiators section
36
+ * Data: strategy.positioning.differentiators + valueProposition
37
+ * Skip: if no differentiators
38
+ */
39
+ export declare function generateDifferentiatorsSection(strategy?: WebsiteStrategyDocument): {
40
+ jsx: string;
41
+ info: SectionRenderInfo;
42
+ };
43
+ /**
44
+ * Generate How It Works section
45
+ * Data: strategy siteArchitecture.pages[0].sections or defaults
46
+ * Always rendered (with defaults if no strategy)
47
+ */
48
+ export declare function generateHowItWorksSection(strategy?: WebsiteStrategyDocument): {
49
+ jsx: string;
50
+ info: SectionRenderInfo;
51
+ };
52
+ /**
53
+ * Generate Stats / Proof Points section
54
+ * CRITICAL: Only show numeric metrics if they appear literally in docs/strategy.
55
+ * Qualitative points render as badges, NOT fake numbers.
56
+ */
57
+ export declare function generateStatsSection(strategy?: WebsiteStrategyDocument): {
58
+ jsx: string;
59
+ info: SectionRenderInfo;
60
+ };
61
+ /**
62
+ * Generate Social Proof section
63
+ * Data: strategy.conversionStrategy.socialProof
64
+ * Skip: if empty
65
+ */
66
+ export declare function generateSocialProofSection(strategy?: WebsiteStrategyDocument): {
67
+ jsx: string;
68
+ info: SectionRenderInfo;
69
+ };
70
+ /**
71
+ * Generate Pricing Teaser section for landing page
72
+ * Data: context.pricing (tier names + starting prices)
73
+ * Skip: if no pricing tiers
74
+ */
75
+ export declare function generatePricingTeaserSection(context?: WebsiteContentContext): {
76
+ jsx: string;
77
+ info: SectionRenderInfo;
78
+ };
79
+ /**
80
+ * Generate FAQ section from strategy objections
81
+ * Data: strategy.icp.objections rephrased as Q&A
82
+ * Skip: if no objections
83
+ * Note: Renders as client component with useState accordion
84
+ */
85
+ export declare function generateFaqSection(strategy?: WebsiteStrategyDocument): {
86
+ jsx: string;
87
+ info: SectionRenderInfo;
88
+ needsClientDirective: boolean;
89
+ };
90
+ /**
91
+ * Build FAQ items array declaration for the page component
92
+ */
93
+ export declare function buildFaqItemsDeclaration(strategy?: WebsiteStrategyDocument): string;
94
+ /**
95
+ * Generate the FaqItem client component code
96
+ */
97
+ export declare function generateFaqItemComponent(): string;
98
+ /**
99
+ * Build JSON-LD FAQ schema for SEO
100
+ */
101
+ export declare function buildFaqSchema(strategy?: WebsiteStrategyDocument): string;
102
+ //# sourceMappingURL=website-sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-sections.d.ts","sourceRoot":"","sources":["../../../src/generators/templates/website-sections.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAa/E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA4BpD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CA4C1C;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CA6C1C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAgD1C;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CA+D1C;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CA0C1C;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,CAAC,EAAE,qBAAqB,GAC9B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,CAgD1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,CAAC,EAAE,uBAAuB,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,oBAAoB,EAAE,OAAO,CAAA;CAAE,CAqCzE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,CAAC,EAAE,uBAAuB,GACjC,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAqBjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,CAAC,EAAE,uBAAuB,GACjC,MAAM,CAwBR"}