@launch77-shared/plugin-marketing-ui 0.0.1

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 ADDED
@@ -0,0 +1,39 @@
1
+ # MarketingUi Plugin
2
+
3
+ Marketing UI component library plugin with conversion-optimized components
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ launch77 plugin:install marketing-ui
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ After installation, the plugin will:
14
+
15
+ - TODO: Describe what the plugin does
16
+ - TODO: List any files created or modified
17
+ - TODO: Explain configuration options
18
+
19
+ ## Development
20
+
21
+ ### Building
22
+
23
+ ```bash
24
+ npm run build
25
+ ```
26
+
27
+ ### Testing
28
+
29
+ ```bash
30
+ npm run typecheck
31
+ ```
32
+
33
+ ## Template Files
34
+
35
+ The `templates/` directory contains files that will be copied to the target application when this plugin is installed. Add any template files your plugin needs here.
36
+
37
+ ## License
38
+
39
+ UNLICENSED
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/generator.ts
4
+ import * as path from "path";
5
+ import chalk from "chalk";
6
+ import { StandardGenerator } from "@launch77/plugin-runtime";
7
+
8
+ // src/utils/config-modifier.ts
9
+ import fs from "fs/promises";
10
+ async function addTailwindContent(filePath, contentPath) {
11
+ try {
12
+ const fileExists = await fs.access(filePath).then(() => true).catch(() => false);
13
+ if (!fileExists) {
14
+ return {
15
+ success: false,
16
+ error: `File not found: ${filePath}`
17
+ };
18
+ }
19
+ const content = await fs.readFile(filePath, "utf-8");
20
+ if (content.includes(contentPath)) {
21
+ return {
22
+ success: true,
23
+ alreadyExists: true
24
+ };
25
+ }
26
+ const lines = content.split("\n");
27
+ let contentArrayStartIndex = -1;
28
+ let contentArrayEndIndex = -1;
29
+ for (let i = 0; i < lines.length; i++) {
30
+ const line = lines[i];
31
+ if (line.includes("content:") && line.includes("[")) {
32
+ contentArrayStartIndex = i;
33
+ if (line.includes("]")) {
34
+ contentArrayEndIndex = i;
35
+ break;
36
+ }
37
+ for (let j = i + 1; j < lines.length; j++) {
38
+ if (lines[j].includes("]")) {
39
+ contentArrayEndIndex = j;
40
+ break;
41
+ }
42
+ }
43
+ break;
44
+ }
45
+ }
46
+ if (contentArrayStartIndex === -1) {
47
+ return {
48
+ success: false,
49
+ error: "Could not find content array in Tailwind config"
50
+ };
51
+ }
52
+ let indentation = " ";
53
+ for (let i = contentArrayStartIndex + 1; i < contentArrayEndIndex; i++) {
54
+ const match = lines[i].match(/^(\s+)['"]/);
55
+ if (match) {
56
+ indentation = match[1];
57
+ break;
58
+ }
59
+ }
60
+ const newLine = `${indentation}'${contentPath}',`;
61
+ lines.splice(contentArrayEndIndex, 0, newLine);
62
+ const newContent = lines.join("\n");
63
+ await fs.writeFile(filePath, newContent, "utf-8");
64
+ return {
65
+ success: true
66
+ };
67
+ } catch (error) {
68
+ return {
69
+ success: false,
70
+ error: error instanceof Error ? error.message : String(error)
71
+ };
72
+ }
73
+ }
74
+
75
+ // src/utils/next-config-modifier.ts
76
+ import * as fs2 from "fs/promises";
77
+ async function addNextImageRemotePattern(filePath, hostname) {
78
+ try {
79
+ const fileExists = await fs2.access(filePath).then(
80
+ () => true,
81
+ () => false
82
+ );
83
+ if (!fileExists) {
84
+ return {
85
+ success: false,
86
+ error: `Config file not found at ${filePath}`
87
+ };
88
+ }
89
+ const content = await fs2.readFile(filePath, "utf-8");
90
+ if (content.includes(`hostname: '${hostname}'`) || content.includes(`hostname: "${hostname}"`)) {
91
+ return {
92
+ success: true,
93
+ alreadyExists: true
94
+ };
95
+ }
96
+ const patternToAdd = ` {
97
+ protocol: 'https',
98
+ hostname: '${hostname}',
99
+ port: '',
100
+ pathname: '/**',
101
+ },`;
102
+ const lines = content.split("\n");
103
+ let newContent;
104
+ const hasRemotePatterns = content.includes("remotePatterns");
105
+ if (hasRemotePatterns) {
106
+ const remotePatternsIndex = lines.findIndex((line) => line.includes("remotePatterns"));
107
+ if (remotePatternsIndex === -1) {
108
+ return {
109
+ success: false,
110
+ error: "Could not find remotePatterns in config"
111
+ };
112
+ }
113
+ let arrayStartIndex = remotePatternsIndex;
114
+ for (let i = remotePatternsIndex; i < lines.length; i++) {
115
+ if (lines[i].includes("[")) {
116
+ arrayStartIndex = i;
117
+ break;
118
+ }
119
+ }
120
+ lines.splice(arrayStartIndex + 1, 0, patternToAdd);
121
+ newContent = lines.join("\n");
122
+ } else {
123
+ const hasImages = content.includes("images:");
124
+ if (hasImages) {
125
+ const imagesIndex = lines.findIndex((line) => line.includes("images:"));
126
+ if (imagesIndex === -1) {
127
+ return {
128
+ success: false,
129
+ error: "Could not find images configuration"
130
+ };
131
+ }
132
+ let objectStartIndex = imagesIndex;
133
+ for (let i = imagesIndex; i < lines.length; i++) {
134
+ if (lines[i].includes("{")) {
135
+ objectStartIndex = i;
136
+ break;
137
+ }
138
+ }
139
+ const remotePatternsProp = ` remotePatterns: [
140
+ ${patternToAdd}
141
+ ],`;
142
+ lines.splice(objectStartIndex + 1, 0, remotePatternsProp);
143
+ newContent = lines.join("\n");
144
+ } else {
145
+ const configIndex = lines.findIndex((line) => line.includes("const config") || line.includes("module.exports") || line.includes("export default"));
146
+ if (configIndex === -1) {
147
+ return {
148
+ success: false,
149
+ error: "Could not find Next.js config object"
150
+ };
151
+ }
152
+ let objectStartIndex = configIndex;
153
+ for (let i = configIndex; i < lines.length; i++) {
154
+ if (lines[i].includes("{")) {
155
+ objectStartIndex = i;
156
+ break;
157
+ }
158
+ }
159
+ const imagesProp = ` images: {
160
+ remotePatterns: [
161
+ ${patternToAdd}
162
+ ],
163
+ },`;
164
+ lines.splice(objectStartIndex + 1, 0, imagesProp);
165
+ newContent = lines.join("\n");
166
+ }
167
+ }
168
+ await fs2.writeFile(filePath, newContent, "utf-8");
169
+ return {
170
+ success: true
171
+ };
172
+ } catch (error) {
173
+ return {
174
+ success: false,
175
+ error: error instanceof Error ? error.message : String(error)
176
+ };
177
+ }
178
+ }
179
+
180
+ // src/generator.ts
181
+ var MarketingUiGenerator = class extends StandardGenerator {
182
+ constructor(context) {
183
+ super(context);
184
+ }
185
+ async injectCode() {
186
+ console.log(chalk.cyan("\u{1F527} Setting up Marketing UI library...\n"));
187
+ await this.updateTailwindConfig();
188
+ await this.updateNextConfig();
189
+ }
190
+ async updateTailwindConfig() {
191
+ const tailwindConfigPath = path.join(this.context.appPath, "tailwind.config.ts");
192
+ const result1 = await addTailwindContent(tailwindConfigPath, "node_modules/@launch77-shared/lib-marketing-ui/dist/**/*.js");
193
+ const result2 = await addTailwindContent(tailwindConfigPath, "../../node_modules/@launch77-shared/lib-marketing-ui/dist/**/*.js");
194
+ if (result1.success || result2.success) {
195
+ if (result1.alreadyExists && result2.alreadyExists) {
196
+ console.log(chalk.gray(" \u2713 Marketing UI library already configured in tailwind.config.ts"));
197
+ } else {
198
+ console.log(chalk.green(" \u2713 Added Marketing UI library to Tailwind content paths"));
199
+ }
200
+ } else {
201
+ console.log(chalk.yellow(` \u26A0\uFE0F Could not auto-configure tailwind.config.ts: ${result1.error}`));
202
+ console.log(chalk.gray(" You will need to add the content paths manually:"));
203
+ console.log(chalk.gray(" 'node_modules/@launch77-shared/lib-marketing-ui/dist/**/*.js'"));
204
+ console.log(chalk.gray(" '../../node_modules/@launch77-shared/lib-marketing-ui/dist/**/*.js'"));
205
+ }
206
+ }
207
+ async updateNextConfig() {
208
+ const nextConfigJsPath = path.join(this.context.appPath, "next.config.js");
209
+ const nextConfigTsPath = path.join(this.context.appPath, "next.config.ts");
210
+ const resultJs = await addNextImageRemotePattern(nextConfigJsPath, "images.unsplash.com");
211
+ const resultTs = await addNextImageRemotePattern(nextConfigTsPath, "images.unsplash.com");
212
+ if (resultJs.success || resultTs.success) {
213
+ if (resultJs.alreadyExists || resultTs.alreadyExists) {
214
+ console.log(chalk.gray(" \u2713 Unsplash images already configured in next.config"));
215
+ } else {
216
+ console.log(chalk.green(" \u2713 Added Unsplash to Next.js image remotePatterns"));
217
+ }
218
+ } else {
219
+ console.log(chalk.yellow(` \u26A0\uFE0F Could not auto-configure next.config: ${resultJs.error || resultTs.error}`));
220
+ console.log(chalk.gray(" You will need to add image configuration manually"));
221
+ console.log(chalk.gray(" See src/modules/marketing-ui/README.md for details"));
222
+ }
223
+ }
224
+ showNextSteps() {
225
+ console.log(chalk.bold.green("\n\u2705 Plugin installed successfully!\n"));
226
+ console.log(chalk.bold("Next Steps:\n"));
227
+ console.log("1. Explore components:");
228
+ console.log(chalk.cyan(" Visit http://localhost:3000/marketing-ui-examples\n"));
229
+ console.log("2. Import components in your code:");
230
+ console.log(chalk.cyan(" import { HeroCentered, CTAButton } from '@launch77-shared/lib-marketing-ui'\n"));
231
+ console.log("3. View documentation:");
232
+ console.log(chalk.cyan(" See src/modules/marketing-ui/README.md\n"));
233
+ console.log(chalk.gray("Note: Unsplash images are pre-configured. To add other image hosts,"));
234
+ console.log(chalk.gray("see the External Images section in README.md\n"));
235
+ }
236
+ };
237
+ async function main() {
238
+ const args = process.argv.slice(2);
239
+ const appPath = args.find((arg) => arg.startsWith("--appPath="))?.split("=")[1];
240
+ const appName = args.find((arg) => arg.startsWith("--appName="))?.split("=")[1];
241
+ const workspaceName = args.find((arg) => arg.startsWith("--workspaceName="))?.split("=")[1];
242
+ const pluginPath = args.find((arg) => arg.startsWith("--pluginPath="))?.split("=")[1];
243
+ if (!appPath || !appName || !workspaceName || !pluginPath) {
244
+ console.error(chalk.red("Error: Missing required arguments"));
245
+ console.error(chalk.gray("Usage: --appPath=<path> --appName=<name> --workspaceName=<name> --pluginPath=<path>"));
246
+ process.exit(1);
247
+ }
248
+ const generator = new MarketingUiGenerator({ appPath, appName, workspaceName, pluginPath });
249
+ await generator.run();
250
+ }
251
+ if (import.meta.url === `file://${process.argv[1]}`) {
252
+ main().catch((error) => {
253
+ console.error(chalk.red("\n\u274C Error during plugin setup:"));
254
+ console.error(error);
255
+ process.exit(1);
256
+ });
257
+ }
258
+ export {
259
+ MarketingUiGenerator
260
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@launch77-shared/plugin-marketing-ui",
3
+ "version": "0.0.1",
4
+ "description": "Marketing UI component library plugin with conversion-optimized components",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "main": "dist/generator.js",
8
+ "bin": {
9
+ "generate": "./dist/generator.js"
10
+ },
11
+ "files": [
12
+ "dist/",
13
+ "templates/",
14
+ "plugin.json"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "dev": "tsup --watch",
19
+ "typecheck": "tsc --noEmit",
20
+ "lint": "eslint src/**/*.ts",
21
+ "release:connect": "launch77-release-connect",
22
+ "release:verify": "launch77-release-verify"
23
+ },
24
+ "dependencies": {
25
+ "@launch77/plugin-runtime": "^0.1.0",
26
+ "chalk": "^5.3.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^20.10.0",
30
+ "tsup": "^8.0.0",
31
+ "typescript": "^5.3.0"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "launch77": {
37
+ "installedPlugins": {
38
+ "release": {
39
+ "package": "release",
40
+ "version": "1.0.1",
41
+ "installedAt": "2026-01-26T01:08:50.461Z",
42
+ "source": "local"
43
+ }
44
+ }
45
+ }
46
+ }
package/plugin.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "targets": ["app"],
3
+ "pluginDependencies": {
4
+ "design-system": "^2.1.0"
5
+ },
6
+ "libraryDependencies": {
7
+ "@launch77-shared/lib-marketing-ui": "^0.1.0"
8
+ }
9
+ }
File without changes
@@ -0,0 +1,283 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { HeroCentered, HeroSplit, ContentSection, MarketingCard, CardGrid, CTAButton, CookieConsent } from '@launch77-shared/lib-marketing-ui'
5
+ import { Button, Badge } from '@launch77-shared/lib-ui'
6
+ import { Zap, Shield, Check, Rocket, Target, Lock } from 'lucide-react'
7
+
8
+ export default function MarketingUiExamplesPage() {
9
+ const [showCookieConsent, setShowCookieConsent] = useState(false)
10
+
11
+ return (
12
+ <div className="min-h-screen bg-background">
13
+ <div className="container mx-auto px-4 py-12 space-y-24">
14
+ {/* Page Header */}
15
+ <div className="space-y-4">
16
+ <h1 className="text-4xl font-bold">Marketing UI Components</h1>
17
+ <p className="text-lg text-muted-foreground">Pre-built marketing components from @launch77-shared/lib-marketing-ui for building landing pages and marketing sites.</p>
18
+ </div>
19
+
20
+ {/* Hero Sections */}
21
+ <section className="space-y-12">
22
+ <div>
23
+ <h2 className="text-3xl font-bold mb-2">Hero Sections</h2>
24
+ <p className="text-muted-foreground">Centered and split hero layouts for impactful first impressions</p>
25
+ </div>
26
+
27
+ {/* HeroCentered */}
28
+ <div className="space-y-4">
29
+ <h3 className="text-2xl font-semibold">HeroCentered</h3>
30
+ <div className="border rounded-lg overflow-hidden">
31
+ <HeroCentered
32
+ badge={
33
+ <Badge variant="secondary" className="text-sm">
34
+ 🚀 New Release
35
+ </Badge>
36
+ }
37
+ headline="Build Your Next SaaS in Days, Not Months"
38
+ subheadline="The AI-first platform that turns your idea into a production-ready app with pre-built components, auth, payments, and more."
39
+ primaryCTA={<Button size="lg">Start Building Free</Button>}
40
+ secondaryCTA={
41
+ <Button variant="outline" size="lg">
42
+ View Demo
43
+ </Button>
44
+ }
45
+ />
46
+ </div>
47
+ </div>
48
+
49
+ {/* HeroSplit */}
50
+ <div className="space-y-4">
51
+ <h3 className="text-2xl font-semibold">HeroSplit</h3>
52
+ <div className="border rounded-lg overflow-hidden">
53
+ <HeroSplit
54
+ imageUrl="https://images.unsplash.com/photo-1551434678-e076c223a692?w=800&h=600&fit=crop"
55
+ imageAlt="Team collaboration"
56
+ imageSide="right"
57
+ decorativeBlob={true}
58
+ blobGradient="from-purple-400 to-blue-400"
59
+ content={
60
+ <div className="space-y-6">
61
+ <Badge variant="outline">Product Update</Badge>
62
+ <h1 className="text-4xl lg:text-5xl font-bold">Ship Faster with Launch77</h1>
63
+ <p className="text-lg text-muted-foreground">Join thousands of developers using our AI-powered platform to build and deploy web apps at lightning speed.</p>
64
+ <div className="flex gap-4">
65
+ <Button size="lg">Get Started</Button>
66
+ <Button variant="link" size="lg">
67
+ Learn More →
68
+ </Button>
69
+ </div>
70
+ </div>
71
+ }
72
+ />
73
+ </div>
74
+ </div>
75
+ </section>
76
+
77
+ {/* Content Sections */}
78
+ <section className="space-y-12">
79
+ <div>
80
+ <h2 className="text-3xl font-bold mb-2">Content Sections</h2>
81
+ <p className="text-muted-foreground">Flexible content layouts for features, benefits, and more</p>
82
+ </div>
83
+
84
+ {/* ContentSection - Features */}
85
+ <div className="space-y-4">
86
+ <h3 className="text-2xl font-semibold">Features Grid</h3>
87
+ <ContentSection headline="Built for Modern Development">
88
+ <div className="space-y-4">
89
+ <Badge>Why Choose Launch77</Badge>
90
+ <p className="text-lg text-muted-foreground">Everything you need to build, deploy, and scale your applications</p>
91
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-8">
92
+ <div className="flex gap-4">
93
+ <div className="text-2xl">🚀</div>
94
+ <div>
95
+ <h3 className="font-semibold mb-1">Ship 10x Faster</h3>
96
+ <p className="text-sm text-muted-foreground">Go from idea to production in days, not months</p>
97
+ </div>
98
+ </div>
99
+ <div className="flex gap-4">
100
+ <div className="text-2xl">💰</div>
101
+ <div>
102
+ <h3 className="font-semibold mb-1">Save Money</h3>
103
+ <p className="text-sm text-muted-foreground">Reduce development costs by up to 70%</p>
104
+ </div>
105
+ </div>
106
+ <div className="flex gap-4">
107
+ <div className="text-2xl">🛡️</div>
108
+ <div>
109
+ <h3 className="font-semibold mb-1">Enterprise Security</h3>
110
+ <p className="text-sm text-muted-foreground">SOC 2 compliant with end-to-end encryption</p>
111
+ </div>
112
+ </div>
113
+ <div className="flex gap-4">
114
+ <div className="text-2xl">📈</div>
115
+ <div>
116
+ <h3 className="font-semibold mb-1">Scale Effortlessly</h3>
117
+ <p className="text-sm text-muted-foreground">Handle millions of users without breaking a sweat</p>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </ContentSection>
123
+ </div>
124
+
125
+ {/* ContentSection - Centered */}
126
+ <div className="space-y-4">
127
+ <h3 className="text-2xl font-semibold">Centered Content</h3>
128
+ <ContentSection headline="How It Works" textAlign="center">
129
+ <div className="space-y-4">
130
+ <p className="text-lg text-muted-foreground">Get from idea to production in three simple steps</p>
131
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-8 mt-12">
132
+ <div className="text-center">
133
+ <div className="text-4xl mb-4">1️⃣</div>
134
+ <h3 className="font-semibold mb-2">Describe Your App</h3>
135
+ <p className="text-sm text-muted-foreground">Tell our AI what you want to build</p>
136
+ </div>
137
+ <div className="text-center">
138
+ <div className="text-4xl mb-4">2️⃣</div>
139
+ <h3 className="font-semibold mb-2">Customize & Review</h3>
140
+ <p className="text-sm text-muted-foreground">Fine-tune the generated code to your needs</p>
141
+ </div>
142
+ <div className="text-center">
143
+ <div className="text-4xl mb-4">3️⃣</div>
144
+ <h3 className="font-semibold mb-2">Deploy & Scale</h3>
145
+ <p className="text-sm text-muted-foreground">Go live with one click and scale effortlessly</p>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ </ContentSection>
150
+ </div>
151
+ </section>
152
+
153
+ {/* Cards */}
154
+ <section className="space-y-12">
155
+ <div>
156
+ <h2 className="text-3xl font-bold mb-2">Cards</h2>
157
+ <p className="text-muted-foreground">Marketing cards for features, testimonials, and pricing</p>
158
+ </div>
159
+
160
+ {/* MarketingCard */}
161
+ <div className="space-y-4">
162
+ <h3 className="text-2xl font-semibold">MarketingCard</h3>
163
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
164
+ <MarketingCard icon={Zap} title="Beautiful Design" description="Pre-built components that look great out of the box" variant="feature" />
165
+ <MarketingCard icon={Rocket} title="Lightning Fast" description="Optimized for performance and Core Web Vitals" variant="feature" />
166
+ <MarketingCard icon={Check} title="Fully Customizable" description="Extend and modify components to match your brand" variant="feature" />
167
+ </div>
168
+ </div>
169
+
170
+ {/* CardGrid */}
171
+ <div className="space-y-4">
172
+ <h3 className="text-2xl font-semibold">CardGrid</h3>
173
+ <CardGrid columns={3} gap="md">
174
+ <MarketingCard icon={Rocket} title="Fast Development" description="Build and ship features at unprecedented speed" variant="feature" />
175
+ <MarketingCard icon={Shield} title="Premium Quality" description="Enterprise-grade code that scales with your business" variant="solution" />
176
+ <MarketingCard icon={Target} title="Focus on Users" description="Spend more time on what matters - your customers" variant="feature" />
177
+ <MarketingCard icon={Lock} title="Secure by Default" description="Built-in security best practices and compliance" variant="solution" />
178
+ </CardGrid>
179
+ </div>
180
+ </section>
181
+
182
+ {/* CTA Components */}
183
+ <section className="space-y-12">
184
+ <div>
185
+ <h2 className="text-3xl font-bold mb-2">Call-to-Action</h2>
186
+ <p className="text-muted-foreground">Conversion-optimized CTA buttons and sections</p>
187
+ </div>
188
+
189
+ {/* CTAButton */}
190
+ <div className="space-y-4">
191
+ <h3 className="text-2xl font-semibold">CTAButton</h3>
192
+ <div className="flex gap-4 flex-wrap">
193
+ <CTAButton
194
+ href="/signup"
195
+ size="lg"
196
+ trackingData={{
197
+ location: 'examples-page',
198
+ text: 'Get Started Free',
199
+ destination: '/signup',
200
+ }}
201
+ >
202
+ Get Started Free
203
+ </CTAButton>
204
+ <CTAButton
205
+ href="/learn-more"
206
+ variant="secondary"
207
+ trackingData={{
208
+ location: 'examples-page',
209
+ text: 'Learn More',
210
+ destination: '/learn-more',
211
+ }}
212
+ >
213
+ Learn More
214
+ </CTAButton>
215
+ <CTAButton
216
+ href="/trial"
217
+ size="lg"
218
+ external={false}
219
+ trackingData={{
220
+ location: 'examples-page',
221
+ text: 'Start Your Trial',
222
+ destination: '/trial',
223
+ }}
224
+ >
225
+ Start Your Trial
226
+ </CTAButton>
227
+ </div>
228
+ </div>
229
+
230
+ {/* CTA Section */}
231
+ <div className="space-y-4">
232
+ <h3 className="text-2xl font-semibold">CTA Section</h3>
233
+ <ContentSection headline="Ready to Get Started?" textAlign="center" className="bg-gradient-to-br from-blue-50 to-purple-50 rounded-2xl p-12">
234
+ <div className="space-y-4">
235
+ <p className="text-lg text-muted-foreground">Join thousands of developers building with Launch77</p>
236
+ <div className="flex gap-4 justify-center mt-8">
237
+ <Button size="lg">Start Free Trial</Button>
238
+ <Button variant="outline" size="lg">
239
+ Book a Demo
240
+ </Button>
241
+ </div>
242
+ <p className="text-sm text-muted-foreground mt-4">No credit card required • 14-day free trial</p>
243
+ </div>
244
+ </ContentSection>
245
+ </div>
246
+ </section>
247
+
248
+ {/* Utilities */}
249
+ <section className="space-y-12">
250
+ <div>
251
+ <h2 className="text-3xl font-bold mb-2">Utilities</h2>
252
+ <p className="text-muted-foreground">Additional marketing utilities for analytics and consent management</p>
253
+ </div>
254
+
255
+ {/* CookieConsent */}
256
+ <div className="space-y-4">
257
+ <h3 className="text-2xl font-semibold">CookieConsent</h3>
258
+ <div className="p-4 bg-blue-50 rounded-lg space-y-4">
259
+ <p className="text-sm text-blue-800">
260
+ <strong>Note:</strong> The CookieConsent component manages its own state and appears automatically on first visit. Click the button below to preview the banner.
261
+ </p>
262
+ <Button onClick={() => setShowCookieConsent(true)} variant="outline">
263
+ Show Cookie Consent Preview
264
+ </Button>
265
+ </div>
266
+ {showCookieConsent && <CookieConsent debug={true} />}
267
+ </div>
268
+ </section>
269
+
270
+ {/* Documentation Link */}
271
+ <section className="border-t pt-12">
272
+ <div className="text-center space-y-4">
273
+ <h2 className="text-2xl font-bold">Need More Help?</h2>
274
+ <p className="text-muted-foreground">Check out the full documentation for detailed usage examples and API reference.</p>
275
+ <Button variant="outline" asChild>
276
+ <a href="/modules/marketing-ui">View Documentation</a>
277
+ </Button>
278
+ </div>
279
+ </section>
280
+ </div>
281
+ </div>
282
+ )
283
+ }
@@ -0,0 +1,400 @@
1
+ # Marketing UI Component Library
2
+
3
+ This module provides access to the Launch77 Marketing UI component library - a collection of pre-built marketing components designed for landing pages, promotional sites, and marketing campaigns.
4
+
5
+ ## Available Components
6
+
7
+ ### Hero Sections
8
+
9
+ - **HeroCentered** - Centered hero layout with headline, subheadline, badge, and CTAs
10
+ - **HeroSplit** - Split-screen hero with content on one side and image/media on the other
11
+
12
+ ### Content Sections
13
+
14
+ - **ContentSection** - Flexible content container with headline and customizable alignment
15
+ - **SectionContainer** - Wrapper component for consistent section spacing and layout
16
+
17
+ ### Cards & Grids
18
+
19
+ - **MarketingCard** - Marketing-focused card with icon, title, and description
20
+ - **CardGrid** - Grid layout for displaying multiple marketing cards
21
+
22
+ ### Call-to-Action
23
+
24
+ - **CTAButton** - Conversion-optimized call-to-action link button
25
+
26
+ ### Utilities
27
+
28
+ - **CookieConsent** - GDPR-compliant cookie consent banner
29
+ - **AnalyticsWrapper** - Wrapper for consent-based analytics tracking
30
+
31
+ ### Typography
32
+
33
+ - **FluidHeading** - Responsive heading with fluid typography
34
+ - **FluidText** - Responsive text with fluid sizing
35
+
36
+ ## Usage Examples
37
+
38
+ ### Basic Hero Section
39
+
40
+ ```tsx
41
+ import { HeroCentered } from '@launch77-shared/lib-marketing-ui'
42
+ import { Button, Badge } from '@launch77-shared/lib-ui'
43
+
44
+ export default function HomePage() {
45
+ return (
46
+ <HeroCentered
47
+ badge={<Badge variant="secondary">New Release</Badge>}
48
+ headline="Build Your Next SaaS in Days, Not Months"
49
+ subheadline="The AI-first platform that turns your idea into a production-ready app with pre-built components, auth, payments, and more."
50
+ primaryCTA={<Button size="lg">Start Building Free</Button>}
51
+ secondaryCTA={
52
+ <Button variant="outline" size="lg">
53
+ View Demo
54
+ </Button>
55
+ }
56
+ />
57
+ )
58
+ }
59
+ ```
60
+
61
+ ### Split Hero with Image
62
+
63
+ ```tsx
64
+ import { HeroSplit } from '@launch77-shared/lib-marketing-ui'
65
+ import { Button, Badge } from '@launch77-shared/lib-ui'
66
+
67
+ export default function AboutPage() {
68
+ return (
69
+ <HeroSplit
70
+ imageUrl="/images/hero-illustration.png"
71
+ imageAlt="Platform illustration"
72
+ imageSide="right"
73
+ decorativeBlob={true}
74
+ blobGradient="from-purple-400 to-blue-400"
75
+ content={
76
+ <div className="space-y-6">
77
+ <Badge variant="outline">Product Update</Badge>
78
+ <h1 className="text-4xl lg:text-5xl font-bold">Ship Faster with Launch77</h1>
79
+ <p className="text-lg text-muted-foreground">Join thousands of developers using our AI-powered platform to build and deploy web apps at lightning speed.</p>
80
+ <div className="flex gap-4">
81
+ <Button size="lg">Get Started</Button>
82
+ <Button variant="link" size="lg">
83
+ Learn More →
84
+ </Button>
85
+ </div>
86
+ </div>
87
+ }
88
+ />
89
+ )
90
+ }
91
+ ```
92
+
93
+ ### Content Section with Features
94
+
95
+ ```tsx
96
+ import { ContentSection } from '@launch77-shared/lib-marketing-ui'
97
+ import { Badge } from '@launch77-shared/lib-ui'
98
+
99
+ export default function FeaturesSection() {
100
+ return (
101
+ <ContentSection headline="Built for Modern Development">
102
+ <div className="space-y-4">
103
+ <Badge>Why Choose Launch77</Badge>
104
+ <p className="text-lg text-muted-foreground">Everything you need to build, deploy, and scale your applications</p>
105
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-8">
106
+ <div className="flex gap-4">
107
+ <div className="text-2xl">🚀</div>
108
+ <div>
109
+ <h3 className="font-semibold mb-1">Ship 10x Faster</h3>
110
+ <p className="text-sm text-muted-foreground">Go from idea to production in days, not months</p>
111
+ </div>
112
+ </div>
113
+ <div className="flex gap-4">
114
+ <div className="text-2xl">💰</div>
115
+ <div>
116
+ <h3 className="font-semibold mb-1">Save Money</h3>
117
+ <p className="text-sm text-muted-foreground">Reduce development costs by up to 70%</p>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </ContentSection>
123
+ )
124
+ }
125
+ ```
126
+
127
+ ### Marketing Cards Grid
128
+
129
+ ```tsx
130
+ import { CardGrid, MarketingCard } from '@launch77-shared/lib-marketing-ui'
131
+ import { Rocket, Shield, Target } from 'lucide-react'
132
+
133
+ export default function BenefitsSection() {
134
+ return (
135
+ <CardGrid columns={3} gap="md">
136
+ <MarketingCard icon={Rocket} title="Fast Development" description="Build and ship features at unprecedented speed" variant="feature" />
137
+ <MarketingCard icon={Shield} title="Premium Quality" description="Enterprise-grade code that scales with your business" variant="solution" />
138
+ <MarketingCard icon={Target} title="Focus on Users" description="Spend more time on what matters - your customers" variant="feature" />
139
+ </CardGrid>
140
+ )
141
+ }
142
+ ```
143
+
144
+ ### Individual Marketing Card
145
+
146
+ ```tsx
147
+ import { MarketingCard } from '@launch77-shared/lib-marketing-ui'
148
+ import { Zap } from 'lucide-react'
149
+
150
+ export default function FeatureCard() {
151
+ return <MarketingCard icon={Zap} title="Beautiful Design" description="Pre-built components that look great out of the box" variant="feature" />
152
+ }
153
+ ```
154
+
155
+ ### Call-to-Action Button
156
+
157
+ ```tsx
158
+ import { CTAButton } from '@launch77-shared/lib-marketing-ui'
159
+
160
+ export default function CTASection() {
161
+ return (
162
+ <CTAButton
163
+ href="/signup"
164
+ size="lg"
165
+ trackingData={{
166
+ location: 'hero-section',
167
+ text: 'Start Free Trial',
168
+ destination: '/signup',
169
+ }}
170
+ >
171
+ Start Free Trial
172
+ </CTAButton>
173
+ )
174
+ }
175
+ ```
176
+
177
+ ### Cookie Consent Banner
178
+
179
+ ```tsx
180
+ import { CookieConsent } from '@launch77-shared/lib-marketing-ui'
181
+
182
+ // Add to your root layout
183
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
184
+ return (
185
+ <html lang="en">
186
+ <body>
187
+ {children}
188
+ <CookieConsent privacyPolicyUrl="/privacy" />
189
+ </body>
190
+ </html>
191
+ )
192
+ }
193
+ ```
194
+
195
+ ### Analytics Wrapper
196
+
197
+ ```tsx
198
+ import { AnalyticsWrapper } from '@launch77-shared/lib-marketing-ui'
199
+
200
+ // Wrap your app to enable consent-based analytics
201
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
202
+ return (
203
+ <html lang="en">
204
+ <body>
205
+ <AnalyticsWrapper>{children}</AnalyticsWrapper>
206
+ </body>
207
+ </html>
208
+ )
209
+ }
210
+ ```
211
+
212
+ ### Fluid Typography
213
+
214
+ ```tsx
215
+ import { FluidHeading, FluidText } from '@launch77-shared/lib-marketing-ui'
216
+
217
+ export default function ResponsiveContent() {
218
+ return (
219
+ <div>
220
+ <FluidHeading level={1} minSize={32} maxSize={64}>
221
+ Responsive Heading
222
+ </FluidHeading>
223
+ <FluidText minSize={16} maxSize={20}>
224
+ This text scales fluidly between viewport sizes for optimal readability.
225
+ </FluidText>
226
+ </div>
227
+ )
228
+ }
229
+ ```
230
+
231
+ ## Component Props
232
+
233
+ ### HeroCentered
234
+
235
+ - `headline` (string, required) - Main headline text
236
+ - `subheadline` (string, optional) - Subheadline/tagline
237
+ - `badge` (ReactNode, optional) - Badge element to display above headline
238
+ - `primaryCTA` (ReactNode, optional) - Primary call-to-action button
239
+ - `secondaryCTA` (ReactNode, optional) - Secondary call-to-action button
240
+ - `background` (string, optional) - Background CSS classes (default: 'bg-white')
241
+ - `className` (string, optional) - Additional CSS classes
242
+ - `id` (string, optional) - HTML id attribute (default: 'hero')
243
+
244
+ ### HeroSplit
245
+
246
+ - `imageUrl` (string, required) - Image source URL
247
+ - `imageAlt` (string, required) - Image alt text for accessibility
248
+ - `imageSide` ('left' | 'right', optional) - Image position (default: 'right')
249
+ - `content` (ReactNode, required) - Hero content (headline, text, buttons, etc.)
250
+ - `decorativeBlob` (boolean, optional) - Show decorative background blob (default: false)
251
+ - `blobGradient` (string, optional) - Tailwind gradient classes for blob
252
+ - `background` (string, optional) - Background CSS classes (default: 'bg-white')
253
+ - `className` (string, optional) - Additional CSS classes
254
+ - `id` (string, optional) - HTML id attribute (default: 'hero')
255
+ - `imageSizes` (string, optional) - Next.js Image sizes attribute
256
+ - `imagePriority` (boolean, optional) - Next.js Image priority loading (default: true)
257
+
258
+ ### ContentSection
259
+
260
+ - `headline` (string, optional) - Section headline
261
+ - `children` (ReactNode, required) - Section content
262
+ - `maxWidth` ('narrow' | 'medium' | 'wide', optional) - Max width constraint (default: 'medium')
263
+ - `textAlign` ('left' | 'center' | 'right', optional) - Text alignment (default: 'center')
264
+ - `background` (string, optional) - Background CSS classes (default: 'bg-white')
265
+ - `className` (string, optional) - Additional CSS classes
266
+ - `id` (string, optional) - HTML id attribute
267
+
268
+ ### MarketingCard
269
+
270
+ - `icon` (LucideIcon, optional) - Lucide icon component (not string)
271
+ - `title` (string, required) - Card title
272
+ - `description` (string, required) - Card description
273
+ - `variant` ('feature' | 'problem' | 'solution', optional) - Visual variant (default: 'feature')
274
+ - `iconBadgeColor` (string, optional) - Override badge background color
275
+ - `iconColor` (string, optional) - Override icon color
276
+ - `className` (string, optional) - Additional CSS classes
277
+ - `children` (ReactNode, optional) - Additional content below description
278
+
279
+ ### CardGrid
280
+
281
+ - `columns` (2 | 3 | 4, optional) - Number of columns (default: 3)
282
+ - `gap` ('sm' | 'md' | 'lg' | 'xl', optional) - Grid gap size (default: 'md')
283
+ - `className` (string, optional) - Additional CSS classes
284
+ - `children` (ReactNode, required) - Grid items (typically MarketingCard components)
285
+
286
+ ### CTAButton
287
+
288
+ - `href` (string, required) - Link destination URL
289
+ - `children` (ReactNode, required) - Button text
290
+ - `external` (boolean, optional) - Open in new tab (default: true)
291
+ - `trackingData` (object, optional) - Analytics tracking data with `location`, `text`, and `destination`
292
+ - `variant` ('default' | 'outline' | 'secondary' | 'ghost' | 'link', optional) - Button style variant
293
+ - `size` ('sm' | 'md' | 'lg', optional) - Button size
294
+ - `className` (string, optional) - Additional CSS classes
295
+ - `onClick` (function, optional) - Click handler
296
+
297
+ ### CookieConsent
298
+
299
+ - `privacyPolicyUrl` (string, optional) - Privacy policy page URL (default: '/privacy')
300
+ - `debug` (boolean, optional) - Enable debug mode to always show banner (default: false)
301
+
302
+ ## Styling
303
+
304
+ All marketing components use Tailwind CSS and the Launch77 design system tokens. You can customize their appearance using:
305
+
306
+ - **Tailwind classes** - Apply utility classes via `className` prop
307
+ - **Design tokens** - Use CSS variables from the design system
308
+ - **Brand customization** - Edit `src/modules/design-system/config/brand.css`
309
+
310
+ ## Live Examples
311
+
312
+ Visit [http://localhost:3000/marketing-ui-examples](http://localhost:3000/marketing-ui-examples) to see all components in action.
313
+
314
+ ## Design Principles
315
+
316
+ The Marketing UI library follows these principles:
317
+
318
+ 1. **Conversion-focused** - Components are optimized for marketing and conversion goals
319
+ 2. **Accessible** - WCAG 2.1 AA compliant with keyboard navigation and screen reader support
320
+ 3. **Responsive** - Mobile-first design that works on all screen sizes
321
+ 4. **Performance** - Optimized for Core Web Vitals and fast page loads
322
+ 5. **Customizable** - Easy to adapt to your brand while maintaining consistency
323
+
324
+ ## Integration with UI Library
325
+
326
+ Marketing UI components work seamlessly with the base UI library components:
327
+
328
+ ```tsx
329
+ import { HeroCentered } from '@launch77-shared/lib-marketing-ui'
330
+ import { Button, Badge } from '@launch77-shared/lib-ui'
331
+
332
+ // Mix marketing and UI components
333
+ ;<HeroCentered
334
+ badge={<Badge>New</Badge>} // UI library component
335
+ headline="Welcome"
336
+ primaryCTA={<Button>Get Started</Button>} // UI library component
337
+ />
338
+ ```
339
+
340
+ ## Utility Functions
341
+
342
+ The library also exports utility functions:
343
+
344
+ ```tsx
345
+ import { cn } from '@launch77-shared/lib-marketing-ui'
346
+
347
+ // Merge Tailwind classes
348
+ const className = cn('base-class', condition && 'conditional-class', 'another-class')
349
+ ```
350
+
351
+ ## Important Notes
352
+
353
+ - **Icons**: MarketingCard accepts Lucide icon components (from `lucide-react`), not strings or emojis
354
+ - **HeroSplit**: Uses a `content` prop for the hero content, not individual headline/CTA props
355
+ - **CTAButton**: Renders as an anchor tag with tracking - requires `href` prop
356
+ - **CardGrid**: Uses children pattern - pass MarketingCard components as children, not a `cards` array prop
357
+
358
+ ## External Images Configuration
359
+
360
+ The HeroSplit component uses Next.js's `<Image>` component for optimized image loading. If you use external image URLs (like CDNs or services like Unsplash), you need to configure them in `next.config.js`:
361
+
362
+ ```js
363
+ // next.config.js
364
+ module.exports = {
365
+ images: {
366
+ remotePatterns: [
367
+ {
368
+ protocol: 'https',
369
+ hostname: 'images.unsplash.com',
370
+ port: '',
371
+ pathname: '/**',
372
+ },
373
+ // Add other image hosts as needed
374
+ {
375
+ protocol: 'https',
376
+ hostname: 'your-cdn.com',
377
+ port: '',
378
+ pathname: '/**',
379
+ },
380
+ ],
381
+ },
382
+ }
383
+ ```
384
+
385
+ **Why is this needed?**
386
+ Next.js blocks external images by default for security reasons. This configuration tells Next.js which domains are safe to optimize images from.
387
+
388
+ **Common image hosts to add:**
389
+
390
+ - Unsplash: `images.unsplash.com`
391
+ - Your CDN: e.g., `cdn.yoursite.com`
392
+ - Cloud storage: e.g., `storage.googleapis.com`, `s3.amazonaws.com`
393
+
394
+ **Error message if not configured:**
395
+
396
+ ```
397
+ Error: Invalid src prop (...) on `next/image`, hostname "..." is not configured under images in your `next.config.js`
398
+ ```
399
+
400
+ See the [Next.js Image Optimization docs](https://nextjs.org/docs/app/api-reference/components/image#remotepatterns) for more details.
@@ -0,0 +1,2 @@
1
+ // Re-export all Marketing UI components for convenient importing
2
+ export * from '@launch77-shared/lib-marketing-ui'