@tangle-network/starter-foundry 0.1.0 → 0.3.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 (76) hide show
  1. package/dist/cli.js +30 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/lib/agent-context.d.ts +43 -0
  4. package/dist/lib/agent-context.js +63 -0
  5. package/dist/lib/agent-context.js.map +1 -0
  6. package/dist/lib/compose-prompt.d.ts +50 -0
  7. package/dist/lib/compose-prompt.js +68 -0
  8. package/dist/lib/compose-prompt.js.map +1 -0
  9. package/dist/lib/compose.js +2 -0
  10. package/dist/lib/compose.js.map +1 -1
  11. package/dist/lib/index.d.ts +6 -1
  12. package/dist/lib/index.js +4 -1
  13. package/dist/lib/index.js.map +1 -1
  14. package/dist/lib/industries.d.ts +33 -0
  15. package/dist/lib/industries.js +52 -0
  16. package/dist/lib/industries.js.map +1 -0
  17. package/dist/lib/keywords.d.ts +6 -0
  18. package/dist/lib/keywords.js +21 -0
  19. package/dist/lib/keywords.js.map +1 -1
  20. package/dist/lib/prompt-planner.js +21 -1
  21. package/dist/lib/prompt-planner.js.map +1 -1
  22. package/dist/lib/telemetry.d.ts +1 -0
  23. package/dist/lib/telemetry.js.map +1 -1
  24. package/package.json +4 -1
  25. package/registry/layers/capability/layout-landing/files/features-section.tsx +54 -77
  26. package/registry/layers/capability/layout-landing/files/hero-section.tsx +18 -23
  27. package/registry/layers/capability/layout-landing/files/landing-page.tsx +25 -63
  28. package/registry/layers/capability/layout-landing/files/personalize.json +146 -0
  29. package/registry/layers/capability/layout-landing/files/pricing-section.tsx +45 -94
  30. package/registry/layers/capability/layout-landing/manifest.json +4 -0
  31. package/registry/layers/capability/layout-landing/variants/dark-product/features-section.tsx +55 -59
  32. package/registry/layers/capability/layout-landing/variants/dark-product/hero-section.tsx +83 -55
  33. package/registry/layers/capability/layout-landing/variants/dark-product/landing-page.tsx +25 -63
  34. package/registry/layers/capability/layout-landing/variants/dark-product/personalize.json +53 -0
  35. package/registry/layers/capability/layout-landing/variants/dark-product/pricing-section.tsx +51 -91
  36. package/registry/layers/capability/layout-landing/variants/default/features-section.tsx +54 -77
  37. package/registry/layers/capability/layout-landing/variants/default/hero-section.tsx +18 -23
  38. package/registry/layers/capability/layout-landing/variants/default/landing-page.tsx +25 -63
  39. package/registry/layers/capability/layout-landing/variants/default/personalize.json +146 -0
  40. package/registry/layers/capability/layout-landing/variants/default/pricing-section.tsx +45 -94
  41. package/registry/layers/capability/layout-landing/variants/gradient-hero/features-section.tsx +53 -57
  42. package/registry/layers/capability/layout-landing/variants/gradient-hero/hero-section.tsx +86 -53
  43. package/registry/layers/capability/layout-landing/variants/gradient-hero/landing-page.tsx +25 -63
  44. package/registry/layers/capability/layout-landing/variants/gradient-hero/personalize.json +53 -0
  45. package/registry/layers/capability/layout-landing/variants/gradient-hero/pricing-section.tsx +49 -88
  46. package/registry/layers/capability/layout-landing/variants/minimal-clean/features-section.tsx +53 -51
  47. package/registry/layers/capability/layout-landing/variants/minimal-clean/hero-section.tsx +88 -47
  48. package/registry/layers/capability/layout-landing/variants/minimal-clean/landing-page.tsx +25 -63
  49. package/registry/layers/capability/layout-landing/variants/minimal-clean/personalize.json +53 -0
  50. package/registry/layers/capability/layout-landing/variants/minimal-clean/pricing-section.tsx +51 -87
  51. package/registry/layers/framework/nextjs-app-router/files/layout.tsx +1 -0
  52. package/registry/layers/framework/nextjs-app-router/files/personalize.css +1 -0
  53. package/registry/layers/framework/nextjs-app-router/manifest.json +4 -0
  54. package/registry/layers/framework/react-vite-ts/files/main.ts +1 -0
  55. package/registry/layers/framework/react-vite-ts/files/personalize.css +1 -0
  56. package/registry/layers/framework/react-vite-ts/manifest.json +4 -0
  57. package/registry/layers/industry/creative/files/personalize.css +11 -0
  58. package/registry/layers/industry/creative/manifest.json +39 -0
  59. package/registry/layers/industry/crypto/files/personalize.css +11 -0
  60. package/registry/layers/industry/crypto/manifest.json +41 -0
  61. package/registry/layers/industry/ecommerce/files/personalize.css +11 -0
  62. package/registry/layers/industry/ecommerce/manifest.json +39 -0
  63. package/registry/layers/industry/education/files/personalize.css +11 -0
  64. package/registry/layers/industry/education/manifest.json +39 -0
  65. package/registry/layers/industry/finance/files/personalize.css +11 -0
  66. package/registry/layers/industry/finance/manifest.json +39 -0
  67. package/registry/layers/industry/fitness/files/personalize.css +11 -0
  68. package/registry/layers/industry/fitness/manifest.json +43 -0
  69. package/registry/layers/industry/gaming/files/personalize.css +11 -0
  70. package/registry/layers/industry/gaming/manifest.json +39 -0
  71. package/registry/layers/industry/health/files/personalize.css +11 -0
  72. package/registry/layers/industry/health/manifest.json +39 -0
  73. package/registry/layers/industry/restaurant/files/personalize.css +11 -0
  74. package/registry/layers/industry/restaurant/manifest.json +41 -0
  75. package/registry/layers/industry/saas/files/personalize.css +11 -0
  76. package/registry/layers/industry/saas/manifest.json +39 -0
@@ -1,73 +1,75 @@
1
- import { Layers, Globe, Lock } from 'lucide-react'
1
+ import * as Icons from 'lucide-react'
2
+ import type { LucideIcon } from 'lucide-react'
3
+ import personalize from '@/personalize.json'
2
4
 
3
- const primaryFeatures = [
4
- {
5
- title: 'Lightning Fast',
6
- description:
7
- 'Optimized for speed with edge-first architecture. Sub-second response times out of the box with automatic CDN distribution.',
8
- },
9
- {
10
- title: 'Secure by Default',
11
- description:
12
- 'Enterprise-grade security with end-to-end encryption, SOC 2 compliance, and role-based access controls baked into every layer.',
13
- },
14
- {
15
- title: 'Built-in Analytics',
16
- description:
17
- 'Real-time dashboards and custom reports so you always know what is working. Track every metric that matters to your business.',
18
- },
19
- ]
20
-
21
- const secondaryFeatures = [
22
- { icon: Layers, label: 'Composable modules — pick only the pieces you need' },
23
- { icon: Globe, label: 'Deploy to 30+ regions with a single command' },
24
- { icon: Lock, label: 'SSO, SAML, and audit logs for compliance' },
25
- ]
5
+ function getIcon(name: string): LucideIcon {
6
+ const Icon = (Icons as unknown as Record<string, LucideIcon>)[name]
7
+ return Icon ?? Icons.Sparkles
8
+ }
26
9
 
27
10
  export function FeaturesSection() {
11
+ const { features } = personalize
28
12
  return (
29
- <section className="bg-muted/20 py-24 dark:bg-muted/5 sm:py-32">
13
+ <section id="features" className="relative bg-background py-24 sm:py-32">
30
14
  <div className="mx-auto max-w-6xl px-6 lg:px-8">
31
15
  <div className="mx-auto max-w-2xl text-center">
32
- <h2 className="text-3xl font-light tracking-tight text-foreground sm:text-4xl">
33
- Everything you need to ship
16
+ <p className="text-sm font-semibold uppercase tracking-wider text-primary">
17
+ {features.eyebrow}
18
+ </p>
19
+ <h2 className="mt-3 text-4xl font-bold tracking-tight text-foreground sm:text-5xl">
20
+ {features.headline}
34
21
  </h2>
35
- <p className="mt-4 text-lg font-light leading-relaxed text-muted-foreground">
36
- A complete toolkit so your team can focus on building product, not plumbing.
22
+ <p className="mt-6 text-lg leading-relaxed text-muted-foreground">
23
+ {features.subheadline}
37
24
  </p>
38
25
  </div>
39
26
 
40
- <div className="mx-auto mt-20 max-w-2xl">
41
- {primaryFeatures.map((feature, i) => (
42
- <div key={feature.title}>
43
- {i > 0 && <div className="border-t border-border/50" />}
44
- <div className="py-10">
45
- <h3 className="text-lg font-medium text-foreground">
46
- {feature.title}
47
- </h3>
48
- <p className="mt-3 text-sm font-light leading-relaxed text-muted-foreground">
27
+ <div className="mt-20 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
28
+ {features.primary.map((feature, i) => {
29
+ const Icon = getIcon(feature.icon)
30
+ return (
31
+ <div
32
+ key={feature.title}
33
+ className="group relative overflow-hidden rounded-xl border border-border/50 bg-card p-8 shadow-sm transition-all duration-200 hover:border-border hover:shadow-md"
34
+ style={{ animation: `fadeInUp 0.6s ease ${i * 0.15}s both` }}
35
+ >
36
+ <div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-primary/50 to-transparent" />
37
+ <div className="flex h-11 w-11 items-center justify-center rounded-lg bg-gradient-to-br from-primary/20 to-primary/5 text-primary">
38
+ <Icon className="h-5 w-5" />
39
+ </div>
40
+ <h3 className="mt-6 text-lg font-semibold text-foreground">{feature.title}</h3>
41
+ <p className="mt-3 text-sm leading-relaxed text-muted-foreground">
49
42
  {feature.description}
50
43
  </p>
51
44
  </div>
52
- </div>
53
- ))}
45
+ )
46
+ })}
54
47
  </div>
55
48
 
56
- <div className="mx-auto mt-4 max-w-2xl border-t pt-10">
57
- <div className="grid gap-8 sm:grid-cols-3">
58
- {secondaryFeatures.map((feature) => (
59
- <div key={feature.label} className="flex items-start gap-3">
60
- <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
61
- <feature.icon className="h-4 w-4" />
49
+ <div className="mt-16 grid gap-8 border-t border-border/50 pt-16 sm:grid-cols-3">
50
+ {features.secondary.map((feature) => {
51
+ const Icon = getIcon(feature.icon)
52
+ return (
53
+ <div key={feature.title} className="flex gap-4">
54
+ <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground">
55
+ <Icon className="h-4 w-4" />
56
+ </div>
57
+ <div>
58
+ <h4 className="text-sm font-semibold text-foreground">{feature.title}</h4>
59
+ <p className="mt-1 text-sm text-muted-foreground">{feature.description}</p>
62
60
  </div>
63
- <p className="text-sm leading-snug text-muted-foreground">
64
- {feature.label}
65
- </p>
66
61
  </div>
67
- ))}
68
- </div>
62
+ )
63
+ })}
69
64
  </div>
70
65
  </div>
66
+
67
+ <style>{`
68
+ @keyframes fadeInUp {
69
+ from { opacity: 0; transform: translateY(20px); }
70
+ to { opacity: 1; transform: translateY(0); }
71
+ }
72
+ `}</style>
71
73
  </section>
72
74
  )
73
75
  }
@@ -1,62 +1,103 @@
1
1
  import { Button } from '@/components/ui/button'
2
- import { ArrowRight } from 'lucide-react'
2
+ import { ArrowRight, Play } from 'lucide-react'
3
+ import personalize from '@/personalize.json'
3
4
 
4
5
  export function HeroSection() {
6
+ const { hero, trust } = personalize
5
7
  return (
6
- <section className="bg-background">
7
- <div className="mx-auto max-w-6xl px-6 py-28 sm:py-36 lg:px-8 lg:py-44">
8
- <div className="mx-auto flex max-w-2xl flex-col items-center text-center">
9
- <p className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
10
- NOW IN BETA
11
- </p>
8
+ <section className="relative overflow-hidden bg-background">
9
+ <div
10
+ aria-hidden="true"
11
+ className="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,hsl(var(--primary)/0.08),transparent)]"
12
+ />
13
+ <div
14
+ aria-hidden="true"
15
+ className="pointer-events-none absolute -right-40 -top-40 h-[500px] w-[500px] rounded-full bg-primary/15 blur-3xl"
16
+ />
17
+ <div
18
+ aria-hidden="true"
19
+ className="pointer-events-none absolute -bottom-40 -left-40 h-[400px] w-[400px] rounded-full bg-chart-2/15 blur-3xl"
20
+ />
12
21
 
13
- <h1 className="mt-8 text-4xl font-light tracking-tight text-foreground sm:text-5xl lg:text-6xl">
14
- {'{{headline}}'}
15
- </h1>
22
+ <div className="relative mx-auto max-w-6xl px-6 py-28 sm:py-36 lg:px-8 lg:py-44">
23
+ <div className="grid items-center gap-12 lg:grid-cols-2 lg:gap-16">
24
+ <div className="flex flex-col items-center text-center lg:items-start lg:text-left">
25
+ <div className="rounded-full border border-border/40 bg-muted/50 px-4 py-1.5 text-xs font-medium tracking-wider text-muted-foreground backdrop-blur-sm">
26
+ {hero.badge}
27
+ </div>
16
28
 
17
- <p className="mt-8 max-w-xl text-lg font-light leading-relaxed text-muted-foreground">
18
- Build faster, ship sooner, and scale with confidence. The modern platform
19
- that gives your team everything it needs to go from idea to production.
20
- </p>
29
+ <h1 className="mt-8 text-5xl font-bold tracking-tighter text-foreground sm:text-6xl lg:text-7xl">
30
+ {hero.headline}
31
+ </h1>
21
32
 
22
- <div className="mt-10 flex items-center gap-4">
23
- <Button
24
- size="lg"
25
- className="h-12 rounded-lg px-8 font-medium shadow-lg shadow-primary/25 transition-all hover:brightness-110 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
26
- >
27
- Get Started
28
- </Button>
29
- <Button
30
- size="lg"
31
- variant="ghost"
32
- className="group h-12 gap-2 rounded-lg border-2 border-transparent px-8 font-medium text-foreground underline decoration-muted-foreground/30 underline-offset-4 transition-all hover:bg-transparent hover:decoration-foreground focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
33
- >
34
- Learn more
35
- <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
36
- </Button>
37
- </div>
33
+ <p className="mt-6 max-w-xl text-lg leading-relaxed text-muted-foreground">
34
+ {hero.subheadline}
35
+ </p>
38
36
 
39
- <div className="mt-14 flex items-center justify-center gap-8">
40
- {Array.from({ length: 5 }).map((_, i) => (
41
- <div
42
- key={i}
43
- className="h-6 w-16 rounded bg-muted-foreground/10"
44
- />
45
- ))}
37
+ <div className="mt-10 flex flex-wrap items-center justify-center gap-4 lg:justify-start">
38
+ <Button
39
+ size="lg"
40
+ className="h-12 gap-2 rounded-lg px-8 font-medium shadow-lg shadow-primary/25 transition-transform hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
41
+ >
42
+ {hero.ctaPrimary}
43
+ <ArrowRight className="h-4 w-4" />
44
+ </Button>
45
+ <Button
46
+ size="lg"
47
+ variant="outline"
48
+ className="h-12 gap-2 rounded-lg border-2 px-8 font-medium transition-transform hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
49
+ >
50
+ <Play className="h-4 w-4" />
51
+ {hero.ctaSecondary}
52
+ </Button>
53
+ </div>
54
+
55
+ <div className="mt-12 flex items-center gap-3">
56
+ <div className="flex -space-x-2">
57
+ {['bg-primary', 'bg-chart-1', 'bg-chart-2', 'bg-chart-3', 'bg-chart-4'].map((color, i) => (
58
+ <div
59
+ key={i}
60
+ className={`h-8 w-8 rounded-full border-2 border-background ${color}`}
61
+ />
62
+ ))}
63
+ </div>
64
+ <p className="text-sm font-medium text-muted-foreground">
65
+ {trust.label}
66
+ </p>
67
+ </div>
46
68
  </div>
47
69
 
48
- <div className="mt-8 flex items-center gap-3">
49
- <div className="flex -space-x-2">
50
- {['bg-primary', 'bg-chart-1', 'bg-chart-2', 'bg-chart-3', 'bg-chart-4'].map((color, i) => (
51
- <div
52
- key={i}
53
- className={`h-8 w-8 rounded-full border-2 border-background ${color}`}
70
+ <div className="relative mx-auto w-full max-w-lg lg:mx-0">
71
+ <div
72
+ aria-hidden="true"
73
+ className="pointer-events-none absolute -inset-4 rounded-2xl bg-primary/10 blur-2xl"
74
+ />
75
+ <div className="relative overflow-hidden rounded-xl border border-border/50 bg-card shadow-2xl shadow-primary/5">
76
+ <div className="flex items-center gap-2 border-b border-border/50 bg-muted/50 px-4 py-3">
77
+ <div className="flex items-center gap-1.5">
78
+ <div className="h-3 w-3 rounded-full bg-red-400/80" />
79
+ <div className="h-3 w-3 rounded-full bg-yellow-400/80" />
80
+ <div className="h-3 w-3 rounded-full bg-green-400/80" />
81
+ </div>
82
+ <div className="ml-3 flex-1 rounded-md bg-background/80 px-3 py-1 text-xs text-muted-foreground">
83
+ {personalize.brand.name.toLowerCase()}.com
84
+ </div>
85
+ </div>
86
+ <div className="relative aspect-[4/3]">
87
+ <img
88
+ src="/images/hero-product.png"
89
+ alt={`${personalize.brand.name} product screenshot`}
90
+ className="h-full w-full object-cover"
91
+ onError={(e) => { e.currentTarget.style.display = 'none' }}
54
92
  />
55
- ))}
93
+ <div className="absolute inset-0 flex items-center justify-center bg-gradient-to-br from-primary/10 to-accent/10">
94
+ <div className="text-center">
95
+ <p className="text-sm font-medium text-foreground">{personalize.brand.name}</p>
96
+ <p className="mt-1 text-xs text-muted-foreground">{personalize.brand.tagline}</p>
97
+ </div>
98
+ </div>
99
+ </div>
56
100
  </div>
57
- <p className="text-sm font-medium text-muted-foreground">
58
- Trusted by <span className="text-foreground">1,000+</span> teams
59
- </p>
60
101
  </div>
61
102
  </div>
62
103
  </div>
@@ -2,43 +2,10 @@ import { Button } from '@/components/ui/button'
2
2
  import { HeroSection } from '@/components/landing/hero-section'
3
3
  import { FeaturesSection } from '@/components/landing/features-section'
4
4
  import { PricingSection } from '@/components/landing/pricing-section'
5
-
6
- const footerLinks = {
7
- Product: [
8
- { label: 'Features', href: '#features' },
9
- { label: 'Pricing', href: '#pricing' },
10
- { label: 'Changelog', href: '/changelog' },
11
- { label: 'Docs', href: '/docs' },
12
- ],
13
- Company: [
14
- { label: 'About', href: '/about' },
15
- { label: 'Blog', href: '/blog' },
16
- { label: 'Careers', href: '/careers' },
17
- { label: 'Contact', href: '/contact' },
18
- ],
19
- Resources: [
20
- { label: 'Documentation', href: '/docs' },
21
- { label: 'API Reference', href: '/docs/api' },
22
- { label: 'Status', href: '/status' },
23
- { label: 'Support', href: '/support' },
24
- ],
25
- Legal: [
26
- { label: 'Privacy', href: '/privacy' },
27
- { label: 'Terms', href: '/terms' },
28
- { label: 'Security', href: '/security' },
29
- ],
30
- }
31
-
32
- const trustLogos = [
33
- 'Acme Corp',
34
- 'TechFlow',
35
- 'Quantum',
36
- 'NovaSoft',
37
- 'BuildStack',
38
- 'DataPipe',
39
- ]
5
+ import personalize from '@/personalize.json'
40
6
 
41
7
  export default function LandingPage() {
8
+ const { brand, trust, footer } = personalize
42
9
  return (
43
10
  <div className="min-h-screen scroll-smooth bg-background text-foreground">
44
11
  <a
@@ -53,28 +20,28 @@ export default function LandingPage() {
53
20
  <span className="flex items-center gap-2 text-lg font-semibold tracking-tight">
54
21
  <img
55
22
  src="/images/logo.svg"
56
- alt="{{headline}}"
23
+ alt={brand.name}
57
24
  className="h-8 w-auto"
58
25
  onError={(e) => { e.currentTarget.style.display = 'none' }}
59
26
  />
60
- <span>{'{{headline}}'}</span>
27
+ <span>{brand.name}</span>
61
28
  </span>
62
29
  <nav className="hidden items-center gap-8 text-sm md:flex">
63
30
  <a
64
31
  href="#features"
65
- className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:rounded"
32
+ className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
66
33
  >
67
34
  Features
68
35
  </a>
69
36
  <a
70
37
  href="#pricing"
71
- className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:rounded"
38
+ className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
72
39
  >
73
40
  Pricing
74
41
  </a>
75
42
  <a
76
43
  href="/sign-in"
77
- className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:rounded"
44
+ className="font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
78
45
  >
79
46
  Sign in
80
47
  </a>
@@ -95,17 +62,16 @@ export default function LandingPage() {
95
62
  <main id="main">
96
63
  <HeroSection />
97
64
 
98
- {/* Trust section */}
99
65
  <section className="border-y border-border/50 bg-muted/20 py-12 dark:bg-muted/5">
100
66
  <div className="mx-auto max-w-6xl px-6 lg:px-8">
101
67
  <p className="mb-8 text-center text-xs font-medium uppercase tracking-widest text-muted-foreground">
102
68
  Trusted by teams at
103
69
  </p>
104
70
  <div className="flex flex-wrap items-center justify-center gap-x-10 gap-y-4 lg:gap-x-16">
105
- {trustLogos.map((name) => (
71
+ {trust.logoNames.map((name) => (
106
72
  <span
107
73
  key={name}
108
- className="text-lg font-semibold tracking-tight text-muted-foreground/30 select-none"
74
+ className="select-none text-lg font-semibold tracking-tight text-muted-foreground/30"
109
75
  >
110
76
  {name}
111
77
  </span>
@@ -114,35 +80,33 @@ export default function LandingPage() {
114
80
  </div>
115
81
  </section>
116
82
 
117
- {/* Gradient divider */}
118
83
  <div aria-hidden="true" className="h-px bg-gradient-to-r from-transparent via-border to-transparent" />
119
84
 
120
- <section id="features">
121
- <FeaturesSection />
122
- </section>
85
+ <FeaturesSection />
123
86
 
124
- {/* Gradient divider */}
125
87
  <div aria-hidden="true" className="h-px bg-gradient-to-r from-transparent via-border to-transparent" />
126
88
 
127
- <section id="pricing">
128
- <PricingSection />
129
- </section>
89
+ <PricingSection />
130
90
  </main>
131
91
 
132
- <footer className="border-t bg-muted/30 dark:bg-muted/10">
92
+ <footer className="border-t border-border/50 bg-muted/10">
133
93
  <div className="mx-auto max-w-6xl px-6 py-16 lg:px-8">
134
- <div className="grid gap-8 sm:grid-cols-2 lg:grid-cols-4 lg:gap-12">
135
- {Object.entries(footerLinks).map(([category, links]) => (
136
- <div key={category}>
137
- <h4 className="text-sm font-semibold text-foreground">
138
- {category}
139
- </h4>
94
+ <div className="grid gap-8 lg:grid-cols-5 lg:gap-12">
95
+ <div className="lg:col-span-1">
96
+ <span className="text-lg font-semibold tracking-tight">{brand.name}</span>
97
+ <p className="mt-3 text-sm leading-relaxed text-muted-foreground">
98
+ {footer.tagline}
99
+ </p>
100
+ </div>
101
+ {Object.entries(footer.sections).map(([title, links]) => (
102
+ <div key={title}>
103
+ <h4 className="text-sm font-semibold text-foreground">{title}</h4>
140
104
  <ul className="mt-4 space-y-3">
141
105
  {links.map((link) => (
142
106
  <li key={link.label}>
143
107
  <a
144
108
  href={link.href}
145
- className="text-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:rounded"
109
+ className="text-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
146
110
  >
147
111
  {link.label}
148
112
  </a>
@@ -152,10 +116,8 @@ export default function LandingPage() {
152
116
  </div>
153
117
  ))}
154
118
  </div>
155
- <div className="mt-12 border-t pt-8">
156
- <p className="text-sm text-muted-foreground">
157
- &copy; {new Date().getFullYear()} {'{{headline}}'}. All rights reserved.
158
- </p>
119
+ <div className="mt-12 border-t border-border/50 pt-8">
120
+ <p className="text-sm text-muted-foreground">{footer.copyright}</p>
159
121
  </div>
160
122
  </div>
161
123
  </footer>
@@ -0,0 +1,53 @@
1
+ {
2
+ "_meta": { "variant": "minimal-clean", "doc": "Minimal whitespace variant" },
3
+ "brand": { "name": "Linear", "tagline": "The system for product teams" },
4
+ "hero": {
5
+ "badge": "ESSAYS BY THE TEAM",
6
+ "headline": "Less, but better.",
7
+ "subheadline": "A minimal, opinionated framework that gets out of your way so you can focus on the work.",
8
+ "ctaPrimary": "Get Started",
9
+ "ctaSecondary": "Read the Manifesto"
10
+ },
11
+ "trust": {
12
+ "label": "Used by 10,000+ thoughtful teams",
13
+ "logoNames": ["Ramp", "Vercel", "Linear", "Notion", "Stripe", "Figma"]
14
+ },
15
+ "features": {
16
+ "eyebrow": "Principles",
17
+ "headline": "Built on clear principles",
18
+ "subheadline": "Each decision considered. Every detail intentional.",
19
+ "primary": [
20
+ { "icon": "Minimize", "title": "Restraint", "description": "We say no to features that don't earn their place. Less surface, more depth." },
21
+ { "icon": "Focus", "title": "Focus", "description": "One thing at a time. The interface fades away so the work stays in front." },
22
+ { "icon": "Compass", "title": "Direction", "description": "Strong opinions about what good looks like, so you don't have to decide everything." }
23
+ ],
24
+ "secondary": [
25
+ { "icon": "Type", "title": "Typography", "description": "Set with care, leading and tracking refined for reading." },
26
+ { "icon": "Square", "title": "Geometry", "description": "Spacing follows a strict 4px grid throughout." },
27
+ { "icon": "Eye", "title": "Contrast", "description": "AAA-compliant color pairs across light and dark." }
28
+ ]
29
+ },
30
+ "pricing": {
31
+ "eyebrow": "Pricing",
32
+ "headline": "Honest pricing",
33
+ "subheadline": "No tiers we don't believe in. No tricks.",
34
+ "toggleMonthly": "Monthly",
35
+ "toggleYearly": "Yearly",
36
+ "yearlyDiscount": "Save 20%",
37
+ "tiers": [
38
+ { "name": "Free", "price": "$0", "period": "/mo", "description": "For thinking through ideas", "features": ["Unlimited drafts", "Markdown export", "Local-first"], "cta": "Get started", "highlighted": false, "note": "No account required" },
39
+ { "name": "Pro", "price": "$8", "period": "/mo", "description": "For people who care", "features": ["Sync across devices", "Themes and fonts", "Custom shortcuts", "Vim mode", "Priority support"], "cta": "Try Pro free", "highlighted": true },
40
+ { "name": "Team", "price": "$18", "period": "/seat/mo", "description": "For small teams", "features": ["Everything in Pro", "Shared workspaces", "Role-based access", "Audit log", "SAML SSO"], "cta": "Start team trial", "highlighted": false }
41
+ ]
42
+ },
43
+ "footer": {
44
+ "tagline": "Crafted with care in California.",
45
+ "sections": {
46
+ "Product": [{ "label": "Features", "href": "#features" }, { "label": "Pricing", "href": "#pricing" }, { "label": "Download", "href": "/download" }, { "label": "Changelog", "href": "/changelog" }],
47
+ "Company": [{ "label": "Manifesto", "href": "/manifesto" }, { "label": "Essays", "href": "/essays" }, { "label": "About", "href": "/about" }, { "label": "Contact", "href": "/contact" }],
48
+ "Resources": [{ "label": "Documentation", "href": "/docs" }, { "label": "Shortcuts", "href": "/shortcuts" }, { "label": "Themes", "href": "/themes" }, { "label": "Community", "href": "/community" }],
49
+ "Legal": [{ "label": "Privacy", "href": "/privacy" }, { "label": "Terms", "href": "/terms" }]
50
+ },
51
+ "copyright": "© 2026 Linear."
52
+ }
53
+ }