page.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import Link from "next/link";
  2. import { Button } from "@/components/ui/button";
  3. import { Demo } from "@/components/demo";
  4. import { Code } from "@/components/code";
  5. import { CopyButton } from "@/components/copy-button";
  6. export default function Home() {
  7. return (
  8. <>
  9. {/* Hero */}
  10. <section className="max-w-5xl mx-auto px-6 pt-24 pb-16 text-center">
  11. <h1 className="text-5xl md:text-7xl font-bold tracking-tighter mb-6">
  12. JSON becomes UI
  13. </h1>
  14. <p className="text-lg text-muted-foreground max-w-2xl mx-auto mb-12 leading-relaxed">
  15. Define a catalog. AI generates JSON. Your components render natively.
  16. </p>
  17. <Demo />
  18. <div className="flex gap-3 justify-center mt-12">
  19. <Button size="lg" asChild>
  20. <Link href="/docs">Get Started</Link>
  21. </Button>
  22. <Button size="lg" variant="outline" asChild>
  23. <a
  24. href="https://github.com/vercel-labs/json-render"
  25. target="_blank"
  26. rel="noopener noreferrer"
  27. >
  28. <svg
  29. viewBox="0 0 24 24"
  30. fill="currentColor"
  31. className="w-5 h-5"
  32. >
  33. <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
  34. </svg>
  35. GitHub
  36. </a>
  37. </Button>
  38. </div>
  39. </section>
  40. {/* How it works */}
  41. <section className="border-t border-border">
  42. <div className="max-w-5xl mx-auto px-6 py-24">
  43. <div className="grid md:grid-cols-3 gap-12">
  44. <div>
  45. <div className="text-xs text-muted-foreground font-mono mb-3">01</div>
  46. <h3 className="text-lg font-semibold mb-2">Define Catalog</h3>
  47. <p className="text-sm text-muted-foreground leading-relaxed">
  48. Specify which components AI can use with Zod schemas. Full type safety and validation.
  49. </p>
  50. </div>
  51. <div>
  52. <div className="text-xs text-muted-foreground font-mono mb-3">02</div>
  53. <h3 className="text-lg font-semibold mb-2">Register Components</h3>
  54. <p className="text-sm text-muted-foreground leading-relaxed">
  55. Map catalog types to your React components. Use your own design system.
  56. </p>
  57. </div>
  58. <div>
  59. <div className="text-xs text-muted-foreground font-mono mb-3">03</div>
  60. <h3 className="text-lg font-semibold mb-2">Let AI Generate</h3>
  61. <p className="text-sm text-muted-foreground leading-relaxed">
  62. AI outputs JSON matching your schema. Stream it. Render progressively.
  63. </p>
  64. </div>
  65. </div>
  66. </div>
  67. </section>
  68. {/* Code example */}
  69. <section className="border-t border-border">
  70. <div className="max-w-5xl mx-auto px-6 py-24">
  71. <div className="grid lg:grid-cols-2 gap-12">
  72. <div>
  73. <h2 className="text-2xl font-semibold mb-4">Define your catalog</h2>
  74. <p className="text-muted-foreground mb-6">
  75. Components, actions, and validation functions.
  76. </p>
  77. <Code lang="typescript">{`import { createCatalog } from '@json-render/core';
  78. import { z } from 'zod';
  79. export const catalog = createCatalog({
  80. components: {
  81. Card: {
  82. props: z.object({
  83. title: z.string(),
  84. description: z.string().nullable(),
  85. }),
  86. hasChildren: true,
  87. },
  88. Metric: {
  89. props: z.object({
  90. label: z.string(),
  91. valuePath: z.string(),
  92. format: z.enum(['currency', 'percent']),
  93. }),
  94. },
  95. },
  96. actions: {
  97. export: { params: z.object({ format: z.string() }) },
  98. },
  99. });`}</Code>
  100. </div>
  101. <div>
  102. <h2 className="text-2xl font-semibold mb-4">AI generates JSON</h2>
  103. <p className="text-muted-foreground mb-6">
  104. Constrained output that your components render natively.
  105. </p>
  106. <Code lang="json">{`{
  107. "key": "dashboard",
  108. "type": "Card",
  109. "props": {
  110. "title": "Revenue Dashboard",
  111. "description": null
  112. },
  113. "children": [
  114. {
  115. "key": "revenue",
  116. "type": "Metric",
  117. "props": {
  118. "label": "Total Revenue",
  119. "valuePath": "/metrics/revenue",
  120. "format": "currency"
  121. }
  122. }
  123. ]
  124. }`}</Code>
  125. </div>
  126. </div>
  127. </div>
  128. </section>
  129. {/* Features */}
  130. <section className="border-t border-border">
  131. <div className="max-w-5xl mx-auto px-6 py-24">
  132. <h2 className="text-2xl font-semibold mb-12 text-center">Features</h2>
  133. <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-8">
  134. {[
  135. { title: "Guardrails", desc: "AI can only use components you define in the catalog" },
  136. { title: "Streaming", desc: "Progressive rendering as JSON streams from the model" },
  137. { title: "Data Binding", desc: "Two-way binding with JSON Pointer paths" },
  138. { title: "Actions", desc: "Named actions handled by your application" },
  139. { title: "Visibility", desc: "Conditional show/hide based on data or auth" },
  140. { title: "Validation", desc: "Built-in and custom validation functions" },
  141. ].map((feature) => (
  142. <div key={feature.title}>
  143. <h3 className="font-semibold mb-2">{feature.title}</h3>
  144. <p className="text-sm text-muted-foreground">{feature.desc}</p>
  145. </div>
  146. ))}
  147. </div>
  148. </div>
  149. </section>
  150. {/* CTA */}
  151. <section className="border-t border-border">
  152. <div className="max-w-4xl mx-auto px-6 py-24 text-center">
  153. <h2 className="text-2xl font-semibold mb-4">Get started</h2>
  154. <div className="flex items-center justify-center gap-2 border border-border rounded px-4 py-3 mb-8 mx-auto w-fit">
  155. <code className="text-sm bg-transparent">npm install @json-render/core @json-render/react</code>
  156. <CopyButton text="npm install @json-render/core @json-render/react" />
  157. </div>
  158. <div>
  159. <Button asChild>
  160. <Link href="/docs">Documentation</Link>
  161. </Button>
  162. </div>
  163. </div>
  164. </section>
  165. </>
  166. );
  167. }