From 9c8e1a5f34bfcedcad0d0c2c52e7ac0b792b7597 Mon Sep 17 00:00:00 2001 From: Mark Henderson Date: Thu, 5 Mar 2026 20:15:59 -0800 Subject: [PATCH] Add live design configurator for marketing surface Users can now compose their marketing site by selecting: - Mode (dark/light), Background style (gradient/beams/meteors/etc.), Nav style, Hero header layout, which Sections appear, and Font. All 4 marketing scaffolds (DaisyUI, HeroUI, Aceternity, Tailwind) respond live to config changes. Library capability cards + style options data defined per library. Aceternity shows actual background effects (beams, meteors, sparkles, wavy, dot-grid). Made-with: Cursor --- .../project/[projectId]/design/page.tsx | 338 +++++- components/design-scaffolds/index.ts | 6 +- components/design-scaffolds/marketing.tsx | 980 ++++++++++++++---- components/design-scaffolds/types.ts | 29 + 4 files changed, 1167 insertions(+), 186 deletions(-) diff --git a/app/[workspace]/project/[projectId]/design/page.tsx b/app/[workspace]/project/[projectId]/design/page.tsx index 5c37b86..31b7d45 100644 --- a/app/[workspace]/project/[projectId]/design/page.tsx +++ b/app/[workspace]/project/[projectId]/design/page.tsx @@ -2,7 +2,10 @@ import { use, useState, useEffect } from "react"; import { toast } from "sonner"; -import { SCAFFOLD_REGISTRY, THEME_REGISTRY, type ThemeColor } from "@/components/design-scaffolds"; +import { + SCAFFOLD_REGISTRY, THEME_REGISTRY, + type ThemeColor, type DesignConfig, type LibraryStyleOptions, +} from "@/components/design-scaffolds"; // --------------------------------------------------------------------------- // Surface definitions @@ -201,6 +204,310 @@ const ALL_SURFACES: Surface[] = [ }, ]; +// --------------------------------------------------------------------------- +// Library style configurator options — per library, for the Marketing surface +// (other surfaces can adopt this pattern as needed) +// --------------------------------------------------------------------------- + +const LIBRARY_STYLE_OPTIONS: Record = { + "daisy-ui": { + modes: [{ id: "light", label: "Light" }, { id: "dark", label: "Dark" }], + backgrounds: [ + { id: "solid", label: "Solid", description: "Clean theme background" }, + { id: "gradient", label: "Gradient", description: "Radial glow from primary color" }, + { id: "pattern", label: "Dot grid", description: "Subtle repeating dot pattern" }, + { id: "noise", label: "Noise", description: "Fine grain texture" }, + ], + navStyles: [ + { id: "standard", label: "Standard", description: "Bordered top bar" }, + { id: "transparent", label: "Transparent", description: "Overlaps the hero section" }, + { id: "pill", label: "Pill", description: "Floating centered nav" }, + ], + headerStyles: [ + { id: "centered", label: "Centered", description: "Title and CTAs centred" }, + { id: "split", label: "Split", description: "Left text, right mockup" }, + { id: "stats", label: "With stats", description: "Metrics row below CTAs" }, + ], + components: [ + { id: "logos", label: "Logo strip" }, + { id: "features", label: "Feature cards" }, + { id: "steps", label: "How it works" }, + { id: "testimonials", label: "Testimonials" }, + { id: "pricing", label: "Pricing table" }, + { id: "faq", label: "FAQ" }, + { id: "cta", label: "CTA banner" }, + ], + fonts: [ + { id: "system", label: "System UI" }, + { id: "plus-jakarta", label: "Plus Jakarta" }, + { id: "dm-sans", label: "DM Sans" }, + { id: "geist", label: "Geist" }, + ], + defaultConfig: { mode: "dark", background: "solid", nav: "standard", header: "centered", components: ["features", "pricing"], font: "system" }, + }, + "hero-ui": { + modes: [{ id: "light", label: "Light" }, { id: "dark", label: "Dark" }], + backgrounds: [ + { id: "clean", label: "Clean", description: "Solid background" }, + { id: "gradient-mesh", label: "Gradient mesh", description: "Soft multi-colour mesh" }, + { id: "glass", label: "Glassmorphism", description: "Frosted glass feel" }, + { id: "aurora", label: "Aurora", description: "Animated colour glow" }, + ], + navStyles: [ + { id: "blur", label: "Blur backdrop", description: "Frosted glass sticky navbar" }, + { id: "standard", label: "Standard", description: "Solid bordered bar" }, + { id: "minimal", label: "Minimal", description: "No border, clean" }, + ], + headerStyles: [ + { id: "animated-badge", label: "Animated", description: "Chip badge + gradient headline" }, + { id: "split", label: "Split", description: "Text + dashboard preview" }, + { id: "gradient", label: "Gradient", description: "Full gradient headline" }, + ], + components: [ + { id: "features", label: "Feature cards" }, + { id: "metrics", label: "Metrics grid" }, + { id: "avatars", label: "Social proof" }, + { id: "pricing", label: "Pricing" }, + { id: "testimonials", label: "Testimonials" }, + { id: "cta", label: "CTA section" }, + ], + fonts: [ + { id: "system", label: "System UI" }, + { id: "inter", label: "Inter" }, + { id: "geist", label: "Geist" }, + { id: "nunito", label: "Nunito" }, + ], + defaultConfig: { mode: "light", background: "clean", nav: "blur", header: "animated-badge", components: ["features", "metrics"], font: "system" }, + }, + "aceternity": { + modes: [{ id: "dark", label: "Dark" }, { id: "light", label: "Light (limited)" }], + backgrounds: [ + { id: "beams", label: "Beams", description: "Signature vertical beam lines" }, + { id: "meteors", label: "Meteors", description: "Shooting particle streaks" }, + { id: "sparkles", label: "Sparkles", description: "Scattered star particles" }, + { id: "wavy", label: "Wavy", description: "Smooth wave shapes" }, + { id: "dot-grid", label: "Dot grid", description: "Perspective dot matrix" }, + { id: "gradient", label: "Glow only", description: "Pure radial glow" }, + ], + navStyles: [ + { id: "minimal", label: "Minimal", description: "Barely-there top bar" }, + { id: "floating", label: "Floating", description: "Centred floating pill" }, + ], + headerStyles: [ + { id: "gradient-text", label: "Gradient text", description: "Fade-to-transparent heading" }, + { id: "lamp", label: "Lamp effect", description: "Spotlight cone from above" }, + { id: "typewriter", label: "Typewriter", description: "Animated text reveal" }, + ], + components: [ + { id: "badge", label: "Glow badge" }, + { id: "features", label: "Feature cards" }, + { id: "moving-cards", label: "Moving cards" }, + { id: "bento", label: "Bento grid" }, + { id: "pricing", label: "Pricing" }, + { id: "cta", label: "CTA section" }, + ], + fonts: [ + { id: "system", label: "System UI" }, + { id: "geist", label: "Geist" }, + { id: "plus-jakarta", label: "Plus Jakarta" }, + ], + defaultConfig: { mode: "dark", background: "beams", nav: "minimal", header: "gradient-text", components: ["features", "moving-cards"], font: "system" }, + }, + "tailwind-only": { + modes: [{ id: "light", label: "Light" }, { id: "dark", label: "Dark" }], + backgrounds: [ + { id: "clean", label: "Clean", description: "Pure white or dark" }, + { id: "dot-grid", label: "Dot grid", description: "Subtle dot pattern" }, + { id: "lines", label: "Grid lines", description: "Faint gridlines" }, + { id: "noise", label: "Noise", description: "Fine grain texture" }, + ], + navStyles: [ + { id: "minimal", label: "Minimal", description: "Logo + links, no decoration" }, + { id: "bordered", label: "Bordered", description: "With bottom border" }, + { id: "spaced", label: "Spread", description: "Logo left, CTA right" }, + ], + headerStyles: [ + { id: "editorial", label: "Editorial", description: "Big bold display typography" }, + { id: "split", label: "Split", description: "Text left + terminal preview" }, + { id: "centered", label: "Centered", description: "Minimal centred layout" }, + ], + components: [ + { id: "badge", label: "Release badge" }, + { id: "logos", label: "Logo strip" }, + { id: "features", label: "Features grid" }, + { id: "stats", label: "Stats row" }, + { id: "testimonials", label: "Testimonials" }, + { id: "pricing", label: "Pricing" }, + { id: "faq", label: "FAQ" }, + { id: "cta", label: "CTA" }, + ], + fonts: [ + { id: "system", label: "System UI" }, + { id: "inter", label: "Inter" }, + { id: "plus-jakarta", label: "Plus Jakarta" }, + { id: "dm-sans", label: "DM Sans" }, + ], + defaultConfig: { mode: "light", background: "clean", nav: "minimal", header: "editorial", components: ["features", "stats", "pricing"], font: "system" }, + }, +}; + +// --------------------------------------------------------------------------- +// DesignConfigurator — shows mode/bg/nav/header/components/font pickers +// --------------------------------------------------------------------------- + +function ConfigRow({ label, children }: { label: string; children: React.ReactNode }) { + return ( +
+ {label} +
+ {children} +
+
+ ); +} + +function OptionChip({ + label, description, active, onClick, multi, checked, +}: { + label: string; description?: string; active: boolean; onClick: () => void; + multi?: boolean; checked?: boolean; +}) { + return ( + + ); +} + +function ModeToggle({ value, onChange }: { value: string; onChange: (v: "dark" | "light") => void }) { + return ( +
+ {(["Light", "Dark"] as const).map(m => { + const id = m.toLowerCase() as "light" | "dark"; + const active = value === id; + return ( + + ); + })} +
+ ); +} + +function DesignConfigurator({ + libraryId, + config, + onChange, +}: { + libraryId: string; + config: DesignConfig; + onChange: (patch: Partial) => void; +}) { + const opts = LIBRARY_STYLE_OPTIONS[libraryId]; + if (!opts) return null; + + const toggleComponent = (id: string) => { + const next = config.components.includes(id) + ? config.components.filter(c => c !== id) + : [...config.components, id]; + onChange({ components: next }); + }; + + return ( +
+ {/* Mode */} + + onChange({ mode: v })} /> + + + {/* Background */} + + {opts.backgrounds.map(bg => ( + onChange({ background: bg.id })} + /> + ))} + + + {/* Nav */} + + {opts.navStyles.map(n => ( + onChange({ nav: n.id })} + /> + ))} + + + {/* Header */} + + {opts.headerStyles.map(h => ( + onChange({ header: h.id })} + /> + ))} + + + {/* Sections */} + + {opts.components.map(c => ( + toggleComponent(c.id)} + /> + ))} + + + {/* Font */} + + {opts.fonts.map(f => ( + onChange({ font: f.id })} + /> + ))} + +
+ ); +} + // --------------------------------------------------------------------------- // Surface section // --------------------------------------------------------------------------- @@ -232,6 +539,22 @@ function SurfaceSection({ const [selectedColorTheme, setSelectedColorTheme] = useState(null); const activeColorTheme = selectedColorTheme ?? availableColorThemes[0] ?? null; + // Design config — per-library style choices (mode, background, nav, header, sections, font) + const defaultForLibrary = previewId ? LIBRARY_STYLE_OPTIONS[previewId]?.defaultConfig : undefined; + const [designConfig, setDesignConfig] = useState( + defaultForLibrary ?? { mode: "light", background: "solid", nav: "standard", header: "centered", components: ["features", "pricing"], font: "system" } + ); + // Reset config when library changes + const [lastPreviewId, setLastPreviewId] = useState(previewId); + if (previewId !== lastPreviewId) { + setLastPreviewId(previewId); + const def = previewId ? LIBRARY_STYLE_OPTIONS[previewId]?.defaultConfig : undefined; + if (def) setDesignConfig(def); + } + const patchConfig = (patch: Partial) => setDesignConfig(prev => ({ ...prev, ...patch })); + + const hasConfigurator = !!previewId && !!LIBRARY_STYLE_OPTIONS[previewId]; + const isLocked = !!lockedThemeId; return ( @@ -267,7 +590,7 @@ function SurfaceSection({ {/* Scaffold */}
{ScaffoldComponent - ? + ? : (
Select a library below to preview @@ -369,7 +692,16 @@ function SurfaceSection({ })}
- {/* Color swatches — shown below the cards when available */} + {/* Design configurator — mode, background, nav, header, sections, font */} + {hasConfigurator && !isLocked && ( + + )} + + {/* Palette (colour) — shown after configurator */} {availableColorThemes.length > 0 && (
Colour diff --git a/components/design-scaffolds/index.ts b/components/design-scaffolds/index.ts index a712f9e..e10582f 100644 --- a/components/design-scaffolds/index.ts +++ b/components/design-scaffolds/index.ts @@ -8,7 +8,7 @@ * 4. Add it to ALL_SURFACES in the design page */ -export type { ThemeColor } from "./types"; +export type { ThemeColor, DesignConfig, StyleOption, LibraryStyleOptions } from "./types"; export { SHADCN_THEMES, MANTINE_THEMES, HEROUI_THEMES, TREMOR_THEMES, DAISY_THEMES, HEROUI_MARKETING_THEMES, @@ -21,7 +21,7 @@ import { MobileNativewind, MobileGluestack } from "./mobile"; import { EmailReactEmail } from "./email"; import { DocsNextra, DocsShadcnCustom } from "./docs"; -import type { ThemeColor } from "./types"; +import type { ThemeColor, DesignConfig } from "./types"; import { SHADCN_THEMES, MANTINE_THEMES, HEROUI_THEMES, TREMOR_THEMES, DAISY_THEMES, HEROUI_MARKETING_THEMES, @@ -31,7 +31,7 @@ import { // SCAFFOLD_REGISTRY — surface → library → preview component // --------------------------------------------------------------------------- -export const SCAFFOLD_REGISTRY: Record>> = { +export const SCAFFOLD_REGISTRY: Record>> = { "web-app": { shadcn: WebAppShadcn, mantine: WebAppMantine, diff --git a/components/design-scaffolds/marketing.tsx b/components/design-scaffolds/marketing.tsx index 0d5a5b9..e81f4fc 100644 --- a/components/design-scaffolds/marketing.tsx +++ b/components/design-scaffolds/marketing.tsx @@ -1,209 +1,829 @@ "use client"; -import { ThemeColor, DAISY_THEMES, HEROUI_MARKETING_THEMES } from "./types"; +import { ThemeColor, DesignConfig, DAISY_THEMES, HEROUI_MARKETING_THEMES } from "./types"; // Marketing Site surface — public-facing pages: hero, features, pricing, CTA // Context: prospective users discovering the product, not signed-in users. +// All components accept a DesignConfig to drive live preview changes. -export function MarketingDaisy({ themeColor }: { themeColor?: ThemeColor }) { - const theme = themeColor ?? DAISY_THEMES[0]; - const text = theme.textColor ?? "#f8f8f2"; - const muted = theme.mutedText ?? "rgba(255,255,255,0.5)"; - const card = theme.cardBg ?? "rgba(255,255,255,0.05)"; - const border = theme.borderColor ?? "rgba(255,255,255,0.1)"; - const bg = theme.bg ?? "#1d232a"; - - return ( -
- {/* Nav */} - - - {/* Hero */} -
-
- ✦ {theme.label} theme — v2.0 -
-

Build faster,
ship smarter

-

The all-in-one platform that helps teams build, launch, and scale their products.

-
- - -
-
- - {/* Feature cards */} -
- {[{ icon: "⚡", title: "Lightning fast", desc: "Deploy in seconds" }, { icon: "🔒", title: "Secure by default", desc: "Enterprise-grade security" }, { icon: "📈", title: "Scales with you", desc: "From zero to millions" }].map(f => ( -
-
{f.icon}
-

{f.title}

-

{f.desc}

-
- ))} -
- - {/* Pricing strip */} -
-
-

Simple pricing

-
- {[{ plan: "Starter", price: "Free", highlight: false }, { plan: "Pro", price: "$29/mo", highlight: true }, { plan: "Enterprise", price: "Custom", highlight: false }].map(p => ( -
-

{p.plan}

-

{p.price}

-
- ))} -
-
-
-
- ); +function fontStack(font?: string) { + if (font === "plus-jakarta") return '"Plus Jakarta Sans", system-ui, sans-serif'; + if (font === "dm-sans") return '"DM Sans", system-ui, sans-serif'; + if (font === "geist") return '"Geist", system-ui, sans-serif'; + if (font === "inter") return '"Inter", system-ui, sans-serif'; + if (font === "nunito") return '"Nunito", system-ui, sans-serif'; + return "system-ui, sans-serif"; } -export function MarketingHeroUI({ themeColor }: { themeColor?: ThemeColor }) { - const theme = themeColor ?? HEROUI_MARKETING_THEMES[0]; - const bg = theme.bg ?? "#fff"; - const text = theme.textColor ?? "#18181b"; - const muted = theme.mutedText ?? "#71717a"; - const card = theme.cardBg ?? "#fff"; - const border = theme.borderColor ?? "#f4f4f5"; +// --------------------------------------------------------------------------- +// DaisyUI +// --------------------------------------------------------------------------- + +export function MarketingDaisy({ themeColor, config }: { themeColor?: ThemeColor; config?: DesignConfig }) { + const theme = themeColor ?? DAISY_THEMES[0]; + const isDark = config ? config.mode === "dark" : (theme.bg ?? "#fff").match(/^#[012]/i) !== null; + + const bg = isDark ? (theme.bg ?? "#1d232a") : (theme.bg?.match(/^#[012]/) ? "#fff" : (theme.bg ?? "#fff")); + const text = isDark ? (theme.textColor ?? "#a6adba") : (theme.textColor ?? "#1f2937"); + const muted = isDark ? (theme.mutedText ?? "rgba(255,255,255,0.4)") : (theme.mutedText ?? "#6b7280"); + const card = isDark ? (theme.cardBg ?? "rgba(255,255,255,0.04)") : (theme.cardBg ?? "#f9fafb"); + const border = isDark ? (theme.borderColor ?? "rgba(255,255,255,0.08)") : (theme.borderColor ?? "#e5e7eb"); + + const bgStyle = config?.background ?? "solid"; + const navStyle = config?.nav ?? "standard"; + const hdrStyle = config?.header ?? "centered"; + const comps = config?.components ?? ["features", "pricing"]; + const ff = fontStack(config?.font); + + // Background overlay applied to the hero area + const heroBgLayer = + bgStyle === "gradient" ? `radial-gradient(ellipse 80% 55% at 50% -5%, ${theme.primary}40, transparent)` : + bgStyle === "pattern" ? undefined : // handled as a full-page layer + bgStyle === "noise" ? undefined : + undefined; + + const navBg = navStyle === "transparent" ? "transparent" : bg; + const navBorderB = navStyle === "transparent" ? "none" : `1px solid ${border}`; + + const pillNav = navStyle === "pill"; + + const NavContent = () => ( + <> +
+
+ Acme +
+
+ {["Features", "Pricing", "Docs", "Blog"].map(i => {i})} +
+
+ + +
+ + ); return ( -
- +
+ {/* Dot-pattern full-page overlay */} + {bgStyle === "pattern" && ( +
+ )} -
-
- 🚀 {theme.label} theme — v2.0 -
-

Build faster,
ship smarter

-

The all-in-one platform for teams that move fast.

-
- - + {/* Nav */} + {pillNav ? ( +
+
+ ) : ( + + )} - {/* Dashboard preview card */} -
-
- {["#ff5f56", "#ffbd2e", "#27c93f"].map(c =>
)} + {/* Hero — centered */} + {hdrStyle === "centered" && ( +
+ {heroBgLayer &&
} +
+ ✦ {theme.label} theme · v2.0
-
-
- {["Revenue $12k", "Users 2.8k", "Growth +24%", "Churn 2.1%"].map((m, i) => ( -
-

{m.split(" ")[0]}

-

{m.split(" ")[1]}

+

Build faster,
ship smarter

+

The all-in-one platform that helps teams build, launch, and scale.

+
+ + +
+
+ )} + + {/* Hero — split layout */} + {hdrStyle === "split" && ( +
+ {heroBgLayer &&
} +
+
✦ New · v2.0
+

Build faster,
ship smarter

+

The platform teams trust to ship faster.

+
+ + +
+
+
+
+ {["#ff5f56","#ffbd2e","#27c93f"].map(c =>
)} +
+
+ {["Revenue $12k","Users 2.8k","Growth +24%"].map(m => ( +
+

{m.split(" ")[0]}

+

{m.split(" ")[1]}

))}
-
-
- ); -} + )} -export function MarketingAceternity() { - return ( -
- -
-
-
- ✦ Open source · 12k GitHub stars -
-

- Build the future
of the web -

-

Beautifully crafted components built with Tailwind CSS and Framer Motion.

-
- - -
-
- {["Animated", "Accessible", "Open source"].map((f, i) => ( -
-
-
-
-

{f}

-

Built for production

-
- ))} -
-
-
- ); -} - -export function MarketingTailwind() { - return ( -
- -
-
- Now in public beta -

The platform
built for scale

-

Everything your team needs to build, deploy, and monitor production applications.

-
- - + {/* Hero — with stats */} + {hdrStyle === "stats" && ( +
+ {heroBgLayer &&
} +

Build faster,
ship smarter

+

Trusted by thousands of teams worldwide.

+
+ +
-
- {["99.9% uptime SLA", "10ms avg latency", "SOC2 compliant", "GDPR ready"].map(f => ( -
-
- -
- {f} +
+ {[["50k+","Teams"],["99.9%","Uptime"],["10ms","Latency"]].map(([v, l]) => ( +
+

{v}

+

{l}

))}
+ )} + + {/* Conditional sections */} + {comps.includes("logos") && ( +
+ Trusted by + {["Vercel","Stripe","Linear","Notion","Supabase"].map(b => ( + {b} + ))} +
+ )} + + {comps.includes("features") && ( +
+ {[{ icon: "⚡", title: "Lightning fast", desc: "Deploy in seconds" }, { icon: "🔒", title: "Secure by default", desc: "Enterprise-grade" }, { icon: "📈", title: "Scales with you", desc: "From 0 to millions" }].map(f => ( +
+
{f.icon}
+

{f.title}

+

{f.desc}

+
+ ))} +
+ )} + + {comps.includes("steps") && ( +
+

How it works

+
+ {["Connect your repo","Configure your stack","Deploy in seconds"].map((s, i) => ( +
+
{i + 1}
+

{s}

+
+ ))} +
+
+ )} + + {comps.includes("testimonials") && ( +
+
+ {[{ q: "\"Deployed in 5 minutes. Incredible.\"", name: "Sarah K.", role: "CTO, Startup" }, { q: "\"Cut our infra costs by 40%.\"", name: "James R.", role: "Eng Lead" }].map(t => ( +
+

{t.q}

+

{t.name}

+

{t.role}

+
+ ))} +
+
+ )} + + {comps.includes("pricing") && ( +
+

Simple pricing

+
+ {[{ plan: "Starter", price: "Free", highlight: false }, { plan: "Pro", price: "$29/mo", highlight: true }, { plan: "Enterprise", price: "Custom", highlight: false }].map(p => ( +
+

{p.plan}

+

{p.price}

+
+ ))} +
+
+ )} + + {comps.includes("faq") && ( +
+

FAQ

+ {["What's included in the free plan?","Can I upgrade anytime?","Do you offer team billing?"].map((q, i) => ( +
+ {q} + {i === 0 ? "−" : "+"} +
+ ))} +
+ )} + + {comps.includes("cta") && ( +
+

Ready to ship faster?

+

Join 50,000+ teams already on Acme.

+ +
+ )} + +
+
+ ); +} + +// --------------------------------------------------------------------------- +// HeroUI +// --------------------------------------------------------------------------- + +export function MarketingHeroUI({ themeColor, config }: { themeColor?: ThemeColor; config?: DesignConfig }) { + const theme = themeColor ?? HEROUI_MARKETING_THEMES[0]; + const isDark = config ? config.mode === "dark" : (theme.bg ?? "#fff") === "#09090b"; + + const bg = isDark ? (theme.bg ?? "#09090b") : (theme.bg ?? "#fff"); + const text = isDark ? (theme.textColor ?? "#f4f4f5") : (theme.textColor ?? "#18181b"); + const muted = isDark ? (theme.mutedText ?? "#71717a") : (theme.mutedText ?? "#71717a"); + const card = isDark ? (theme.cardBg ?? "#18181b") : (theme.cardBg ?? "#fafafa"); + const border = isDark ? (theme.borderColor ?? "#27272a") : (theme.borderColor ?? "#f4f4f5"); + + const bgStyle = config?.background ?? "clean"; + const navStyle = config?.nav ?? "blur"; + const hdrStyle = config?.header ?? "animated-badge"; + const comps = config?.components ?? ["features", "metrics"]; + const ff = fontStack(config?.font); + + const navBlur = navStyle === "blur"; + const navBg = navBlur + ? (isDark ? "rgba(9,9,11,0.7)" : "rgba(255,255,255,0.7)") + : navStyle === "minimal" ? "transparent" + : bg; + const navBorderB = navStyle === "minimal" ? "none" : `1px solid ${border}`; + + const heroBgOverlay = + bgStyle === "gradient-mesh" ? `radial-gradient(ellipse 70% 60% at 30% 40%, ${theme.primary}25, transparent 60%), radial-gradient(ellipse 50% 50% at 80% 60%, ${isDark ? "#06b6d422" : "#06b6d418"}, transparent 60%)` : + bgStyle === "glass" ? `linear-gradient(135deg, ${theme.primary}14, ${isDark ? "#18181b" : "#fff"} 60%)` : + bgStyle === "aurora" ? `radial-gradient(ellipse 80% 60% at 50% -10%, ${theme.primary}35, transparent 70%)` : + undefined; + + return ( +
+ {heroBgOverlay &&
} + + {/* Nav */} + + + {/* Hero — animated badge style */} + {hdrStyle === "animated-badge" && ( +
+
+ 🚀 Now in public beta +
+

Build faster,
ship smarter

+

The all-in-one platform for teams that move fast.

+
+ + +
+
+ )} + + {/* Hero — split layout */} + {hdrStyle === "split" && ( +
+
+
🚀 Beta
+

Build faster,
ship smarter

+

The platform for fast-moving teams.

+
+ + +
+
+
+
+ {["#ff5f56","#ffbd2e","#27c93f"].map(c =>
)} +
+
+
+ {["Revenue $12k","Users 2.8k","Growth +24%","Churn 2.1%"].map(m => ( +
+

{m.split(" ")[0]}

+

{m.split(" ")[1]}

+
+ ))} +
+
+
+
+ )} + + {/* Hero — gradient headline */} + {hdrStyle === "gradient" && ( +
+

+ Build faster.
Ship smarter. +

+

Everything your team needs in one platform.

+
+ +
+
+ )} + + {/* Conditional sections */} + {comps.includes("features") && ( +
+ {[{ icon: "⚡", title: "10x faster deploys" }, { icon: "🔒", title: "Zero-trust security" }, { icon: "📦", title: "Any stack" }, { icon: "🌍", title: "Global CDN" }].map(f => ( +
+ {f.icon} +

{f.title}

+
+ ))} +
+ )} + + {comps.includes("metrics") && ( +
+
+
+ {["Revenue $12k","Users 2.8k","Growth +24%","Churn 2.1%"].map((m, i) => ( +
+

{m.split(" ")[0]}

+

{m.split(" ")[1]}

+
+ ))} +
+
+
+ )} + + {comps.includes("avatars") && ( +
+
+ {["#7c3aed","#2563eb","#0d9488","#e11d48"].map((c, i) => ( +
0 ? -8 : 0 }} /> + ))} +
+ Trusted by 50,000+ teams +
+ )} + + {comps.includes("pricing") && ( +
+
+ {[{ plan: "Starter", price: "Free", hi: false }, { plan: "Pro", price: "$29/mo", hi: true }, { plan: "Enterprise", price: "Custom", hi: false }].map(p => ( +
+

{p.plan}

+

{p.price}

+
+ ))} +
+
+ )} + + {comps.includes("testimonials") && ( +
+
+ {[{ q: "\"Shipped 3x faster since switching.\"", name: "Sarah K." }, { q: "\"Cut infra costs by 40%.\"", name: "James R." }].map(t => ( +
+

{t.q}

+

{t.name}

+
+ ))} +
+
+ )} + + {comps.includes("cta") && ( +
+

Ready to ship faster?

+

Join 50,000+ teams already on Acme.

+ +
+ )} + +
+
+ ); +} + +// --------------------------------------------------------------------------- +// Aceternity UI +// --------------------------------------------------------------------------- + +export function MarketingAceternity({ config }: { themeColor?: ThemeColor; config?: DesignConfig }) { + const isDark = config?.mode !== "light"; + const bgStyle = config?.background ?? "beams"; + const navStyle = config?.nav ?? "minimal"; + const hdrStyle = config?.header ?? "gradient-text"; + const comps = config?.components ?? ["features", "moving-cards"]; + const ff = fontStack(config?.font); + + const bg = isDark ? "#030303" : "#f8fafc"; + const text = isDark ? "#fff" : "#0f172a"; + const muted = isDark ? "rgba(255,255,255,0.38)" : "#64748b"; + const card = isDark ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)"; + const border= isDark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.08)"; + + // Background effects rendered as CSS + const BackgroundEffect = () => { + if (bgStyle === "beams") return ( +
+ {/* Vertical beam lines */} + {Array.from({ length: 8 }).map((_, i) => ( +
+ ))} +
+ ); + if (bgStyle === "meteors") return ( +
+
+ {Array.from({ length: 6 }).map((_, i) => ( +
+ ))} +
+ ); + if (bgStyle === "sparkles") return ( +
+ {Array.from({ length: 20 }).map((_, i) => ( +
+ ))} +
+ ); + if (bgStyle === "wavy") return ( +
+ + + + +
+ ); + if (bgStyle === "dot-grid") return ( +
+ ); + // gradient (default radial glow) + return
; + }; + + const floatingNav = navStyle === "floating"; + + return ( +
+ + + {/* Nav */} + {floatingNav ? ( +
+ +
+ ) : ( + + )} + + {/* Hero — gradient text */} + {hdrStyle === "gradient-text" && ( +
+
+ ✦ Open source · 12k stars +
+

+ Build the future
of the web +

+

Beautifully crafted components built with Tailwind CSS and Framer Motion.

+
+ + +
+
+ )} + + {/* Hero — lamp effect */} + {hdrStyle === "lamp" && ( +
+
+
+

Build the future
of the web

+

Powered by Framer Motion and Tailwind CSS.

+ +
+ )} + + {/* Hero — typewriter */} + {hdrStyle === "typewriter" && ( +
+
THE FUTURE IS HERE
+

+ Build the future
+ of the web_ +

+

Components that bring your ideas to life.

+ +
+ )} + + {/* Conditional sections */} + {comps.includes("features") && ( +
+ {[{ label: "Animated", color: "#a855f7" }, { label: "Accessible", color: "#3b82f6" }, { label: "Open source", color: "#22c55e" }].map(f => ( +
+
+
+
+

{f.label}

+

Built for production

+
+ ))} +
+ )} + + {comps.includes("badge") && ( +
+ ✦ v2.0 just shipped — see what's new → +
+ )} + + {comps.includes("moving-cards") && ( +
+

What our users say

+
+ {[{ text: "\"Game changer for our team.\"", name: "Sarah K." }, { text: "\"Ships 3x faster.\"", name: "James R." }, { text: "\"Zero-config deploys.\"", name: "Mia L." }].map(t => ( +
+

{t.text}

+

— {t.name}

+
+ ))} +
+
+ )} + + {comps.includes("bento") && ( +
+
+
+

Analytics

+
+
+
+

Deploys

+

+
+
+

Uptime

+

99.9%

+
+
+
+ )} + + {comps.includes("pricing") && ( +
+
+ {[{ plan: "Starter", price: "Free", hi: false }, { plan: "Pro", price: "$29/mo", hi: true }, { plan: "Enterprise", price: "Custom", hi: false }].map(p => ( +
+

{p.plan}

+

{p.price}

+
+ ))} +
+
+ )} + + {comps.includes("cta") && ( +
+

Start building today

+

Join thousands of developers worldwide.

+ +
+ )} + +
+
+ ); +} + +// --------------------------------------------------------------------------- +// Tailwind only +// --------------------------------------------------------------------------- + +export function MarketingTailwind({ config }: { themeColor?: ThemeColor; config?: DesignConfig }) { + const isDark = config?.mode === "dark"; + const bgStyle = config?.background ?? "clean"; + const navStyle = config?.nav ?? "minimal"; + const hdrStyle = config?.header ?? "editorial"; + const comps = config?.components ?? ["features", "stats", "pricing"]; + const ff = fontStack(config?.font); + + const bg = isDark ? "#09090b" : "#fff"; + const text = isDark ? "#f4f4f5" : "#09090b"; + const muted = isDark ? "#71717a" : "#71717a"; + const card = isDark ? "#18181b" : "#f9fafb"; + const border= isDark ? "#27272a" : "#e5e7eb"; + const accent = "#7c3aed"; + + const navBg = navStyle === "minimal" ? "transparent" : bg; + const navBorderB = navStyle === "minimal" ? "none" : `1px solid ${border}`; + + return ( +
+ {/* Background effects */} + {bgStyle === "dot-grid" && ( +
+ )} + {bgStyle === "lines" && ( +
+ )} + {bgStyle === "noise" && ( +
+ )} + + {/* Nav */} + + + {/* Hero — editorial big type */} + {hdrStyle === "editorial" && ( +
+ Now in public beta +

The platform
built for scale

+

Everything your team needs to build, deploy, and monitor production applications.

+
+ + +
+
+ )} + + {/* Hero — split */} + {hdrStyle === "split" && ( +
+
+ Public beta +

The platform
built for scale

+

Deploy anywhere. Monitor everything.

+
+ + +
+
+
+
+ {["#ff5f56","#ffbd2e","#27c93f"].map(c =>
)} +
+
+
✓ Build complete
+
→ Deploying…
+
✓ Live in 2.1s
+
+
+
+ )} + + {/* Hero — centered minimal */} + {hdrStyle === "centered" && ( +
+

The platform
built for scale

+

Everything your team needs.

+ +
+ )} + + {/* Conditional sections */} + {comps.includes("badge") && ( +
+ → v2.0 released — see what's new +
+ )} + + {comps.includes("logos") && ( +
+ Trusted by + {["Vercel","Stripe","Linear","Notion","Supabase"].map(b => ( + {b} + ))} +
+ )} + + {comps.includes("features") && ( +
+ {[{ title: "99.9% uptime SLA", desc: "Enterprise reliability" }, { title: "10ms avg latency", desc: "Edge-first network" }, { title: "SOC2 compliant", desc: "Security baked in" }, { title: "GDPR ready", desc: "Privacy by default" }].map(f => ( +
+
+ +
+
+

{f.title}

+

{f.desc}

+
+
+ ))} +
+ )} + + {comps.includes("stats") && ( +
+
+ {[["50k+","Teams"],["99.9%","Uptime"],["10ms","Latency"],["$0","To start"]].map(([v, l], i) => ( +
+

{v}

+

{l}

+
+ ))} +
+
+ )} + + {comps.includes("testimonials") && ( +
+
+ {[{ q: "\"Shipped 3x faster.\"", name: "Sarah K.", role: "CTO" }, { q: "\"Cut costs by 40%.\"", name: "James R.", role: "Eng Lead" }].map(t => ( +
+

{t.q}

+

{t.name} · {t.role}

+
+ ))} +
+
+ )} + + {comps.includes("pricing") && ( +
+
+ {[{ plan: "Starter", price: "Free", hi: false }, { plan: "Pro", price: "$29/mo", hi: true }, { plan: "Enterprise", price: "Custom", hi: false }].map(p => ( +
+

{p.plan}

+

{p.price}

+
+ ))} +
+
+ )} + + {comps.includes("faq") && ( +
+ {["What's included in free?","Can I upgrade anytime?","Do you offer team plans?"].map((q, i) => ( +
+ {q} + {i === 0 ? "−" : "+"} +
+ ))} +
+ )} + + {comps.includes("cta") && ( +
+

Ready to ship faster?

+

Join 50,000+ teams already on Acme.

+ +
+ )} + +
); } diff --git a/components/design-scaffolds/types.ts b/components/design-scaffolds/types.ts index 26835c0..be4a7d4 100644 --- a/components/design-scaffolds/types.ts +++ b/components/design-scaffolds/types.ts @@ -19,6 +19,35 @@ export interface ThemeColor { mutedText?: string; } +// --------------------------------------------------------------------------- +// Design configurator types — used by the surface configurator and scaffolds +// --------------------------------------------------------------------------- + +export interface StyleOption { + id: string; + label: string; + description?: string; +} + +export interface LibraryStyleOptions { + modes: StyleOption[]; + backgrounds: StyleOption[]; + navStyles: StyleOption[]; + headerStyles: StyleOption[]; + components: StyleOption[]; + fonts: StyleOption[]; + defaultConfig: DesignConfig; +} + +export interface DesignConfig { + mode: "dark" | "light"; + background: string; + nav: string; + header: string; + components: string[]; + font: string; +} + // Shared mock data export const TABLE_ROWS = [ { name: "Alice Martin", email: "alice@co.com", role: "Admin", status: "Active", date: "Jan 12" },