page.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. <p className="text-xs sm:text-sm font-medium text-muted-foreground tracking-widest uppercase mb-4">
  12. The Generative UI Framework
  13. </p>
  14. <h1 className="text-4xl sm:text-6xl md:text-7xl font-bold tracking-tighter mb-6">
  15. AI → json-render → UI
  16. </h1>
  17. <p className="text-lg text-muted-foreground max-w-2xl mx-auto mb-12 leading-relaxed">
  18. Generate dynamic, personalized UIs from prompts without sacrificing
  19. reliability. Predefined components and actions for safe, predictable
  20. output.
  21. </p>
  22. <Demo />
  23. <div className="flex items-center justify-center gap-2 border border-border rounded px-4 py-3 mt-12 mx-auto w-fit">
  24. <code className="text-sm bg-transparent">
  25. npm install @json-render/core @json-render/react
  26. </code>
  27. <CopyButton text="npm install @json-render/core @json-render/react" />
  28. </div>
  29. <div className="flex gap-3 justify-center mt-6">
  30. <Button size="lg" asChild>
  31. <Link href="/docs">Get Started</Link>
  32. </Button>
  33. <Button size="lg" variant="outline" asChild>
  34. <a
  35. href="https://github.com/vercel-labs/json-render"
  36. target="_blank"
  37. rel="noopener noreferrer"
  38. >
  39. <svg viewBox="0 0 24 24" fill="currentColor" className="w-5 h-5">
  40. <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" />
  41. </svg>
  42. GitHub
  43. </a>
  44. </Button>
  45. </div>
  46. </section>
  47. {/* How it works */}
  48. <section className="border-t border-border">
  49. <div className="max-w-5xl mx-auto px-6 py-24">
  50. <div className="grid md:grid-cols-3 gap-12">
  51. <div>
  52. <div className="text-xs text-muted-foreground font-mono mb-3">
  53. 01
  54. </div>
  55. <h3 className="text-lg font-semibold mb-2">
  56. Define Your Catalog
  57. </h3>
  58. <p className="text-sm text-muted-foreground leading-relaxed">
  59. Set the guardrails. Define which components, actions, and data
  60. bindings AI can use.
  61. </p>
  62. </div>
  63. <div>
  64. <div className="text-xs text-muted-foreground font-mono mb-3">
  65. 02
  66. </div>
  67. <h3 className="text-lg font-semibold mb-2">AI Generates</h3>
  68. <p className="text-sm text-muted-foreground leading-relaxed">
  69. Describe what you want. AI generates JSON constrained to your
  70. catalog. Every interface is unique.
  71. </p>
  72. </div>
  73. <div>
  74. <div className="text-xs text-muted-foreground font-mono mb-3">
  75. 03
  76. </div>
  77. <h3 className="text-lg font-semibold mb-2">Render Instantly</h3>
  78. <p className="text-sm text-muted-foreground leading-relaxed">
  79. Stream the response. Your components render progressively as
  80. JSON arrives.
  81. </p>
  82. </div>
  83. </div>
  84. </div>
  85. </section>
  86. {/* Code example */}
  87. <section className="border-t border-border">
  88. <div className="max-w-5xl mx-auto px-6 py-24">
  89. <div className="grid lg:grid-cols-2 gap-12">
  90. <div className="min-w-0">
  91. <h2 className="text-2xl font-semibold mb-4">
  92. Define your catalog
  93. </h2>
  94. <p className="text-muted-foreground mb-6">
  95. Components, actions, and validation functions.
  96. </p>
  97. <Code lang="typescript">{`import { defineSchema, defineCatalog } from '@json-render/core';
  98. import { z } from 'zod';
  99. const schema = defineSchema({ /* ... */ });
  100. export const catalog = defineCatalog(schema, {
  101. components: {
  102. Card: {
  103. props: z.object({
  104. title: z.string(),
  105. description: z.string().nullable(),
  106. }),
  107. hasChildren: true,
  108. },
  109. Metric: {
  110. props: z.object({
  111. label: z.string(),
  112. statePath: z.string(),
  113. format: z.enum(['currency', 'percent']),
  114. }),
  115. },
  116. },
  117. actions: {
  118. export: { params: z.object({ format: z.string() }) },
  119. },
  120. });`}</Code>
  121. </div>
  122. <div className="min-w-0">
  123. <h2 className="text-2xl font-semibold mb-4">AI generates JSON</h2>
  124. <p className="text-muted-foreground mb-6">
  125. Constrained output that your components render natively.
  126. </p>
  127. <Code lang="json">{`{
  128. "root": "dashboard",
  129. "elements": {
  130. "dashboard": {
  131. "type": "Card",
  132. "props": {
  133. "title": "Revenue Dashboard"
  134. },
  135. "children": ["revenue"]
  136. },
  137. "revenue": {
  138. "type": "Metric",
  139. "props": {
  140. "label": "Total Revenue",
  141. "statePath": "/metrics/revenue",
  142. "format": "currency"
  143. }
  144. }
  145. }
  146. }`}</Code>
  147. </div>
  148. </div>
  149. </div>
  150. </section>
  151. {/* Code Export */}
  152. <section className="border-t border-border">
  153. <div className="max-w-5xl mx-auto px-6 py-24">
  154. <div className="text-center mb-12">
  155. <h2 className="text-2xl font-semibold mb-4">Export as Code</h2>
  156. <p className="text-muted-foreground max-w-2xl mx-auto">
  157. Export generated UI as standalone React components. No runtime
  158. dependencies required.
  159. </p>
  160. </div>
  161. <div className="grid lg:grid-cols-2 gap-12">
  162. <div className="min-w-0">
  163. <h3 className="text-lg font-semibold mb-4">Generated UI Tree</h3>
  164. <p className="text-muted-foreground mb-6 text-sm">
  165. AI generates a JSON structure from the user&apos;s prompt.
  166. </p>
  167. <Code lang="json">{`{
  168. "root": "card",
  169. "elements": {
  170. "card": {
  171. "type": "Card",
  172. "props": { "title": "Revenue" },
  173. "children": ["metric", "chart"]
  174. },
  175. "metric": {
  176. "type": "Metric",
  177. "props": {
  178. "label": "Total Revenue",
  179. "statePath": "analytics/revenue",
  180. "format": "currency"
  181. }
  182. },
  183. "chart": {
  184. "type": "Chart",
  185. "props": {
  186. "statePath": "analytics/salesByRegion"
  187. }
  188. }
  189. }
  190. }`}</Code>
  191. </div>
  192. <div className="min-w-0">
  193. <h3 className="text-lg font-semibold mb-4">
  194. Exported React Code
  195. </h3>
  196. <p className="text-muted-foreground mb-6 text-sm">
  197. Export as a standalone Next.js project with all components.
  198. </p>
  199. <Code lang="tsx">{`"use client";
  200. import { Card, Metric, Chart } from "@/components/ui";
  201. const data = {
  202. analytics: {
  203. revenue: 125000,
  204. salesByRegion: [
  205. { label: "US", value: 45000 },
  206. { label: "EU", value: 35000 },
  207. ],
  208. },
  209. };
  210. export default function Page() {
  211. return (
  212. <Card data={data} title="Revenue">
  213. <Metric
  214. data={data}
  215. label="Total Revenue"
  216. statePath="analytics/revenue"
  217. format="currency"
  218. />
  219. <Chart data={data} statePath="analytics/salesByRegion" />
  220. </Card>
  221. );
  222. }`}</Code>
  223. </div>
  224. </div>
  225. <div className="mt-8 text-center">
  226. <p className="text-sm text-muted-foreground">
  227. The export includes{" "}
  228. <code className="text-foreground">package.json</code>, component
  229. files, styles, and everything needed to run independently.
  230. </p>
  231. </div>
  232. </div>
  233. </section>
  234. {/* Features */}
  235. <section className="border-t border-border">
  236. <div className="max-w-5xl mx-auto px-6 py-24">
  237. <h2 className="text-2xl font-semibold mb-12 text-center">Features</h2>
  238. <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-8">
  239. {[
  240. {
  241. title: "Generative UI",
  242. desc: "Generate dynamic, personalized interfaces from prompts with AI",
  243. },
  244. {
  245. title: "Guardrails",
  246. desc: "AI can only use components you define in the catalog",
  247. },
  248. {
  249. title: "Streaming",
  250. desc: "Progressive rendering as JSON streams from the model",
  251. },
  252. {
  253. title: "React & React Native",
  254. desc: "Render on web and mobile from the same catalog and spec format",
  255. },
  256. {
  257. title: "Data Binding",
  258. desc: "Connect props to state with $state, $item, $index, and two-way binding",
  259. },
  260. {
  261. title: "Code Export",
  262. desc: "Export as standalone React code with no runtime dependencies",
  263. },
  264. ].map((feature) => (
  265. <div key={feature.title}>
  266. <h3 className="font-semibold mb-2">{feature.title}</h3>
  267. <p className="text-sm text-muted-foreground">{feature.desc}</p>
  268. </div>
  269. ))}
  270. </div>
  271. </div>
  272. </section>
  273. {/* CTA */}
  274. <section className="border-t border-border">
  275. <div className="max-w-4xl mx-auto px-6 py-24 text-center">
  276. <h2 className="text-2xl font-semibold mb-4">Get started</h2>
  277. <div className="flex items-center justify-center gap-2 border border-border rounded px-4 py-3 mb-8 mx-auto w-fit">
  278. <code className="text-sm bg-transparent">
  279. npm install @json-render/core @json-render/react
  280. </code>
  281. <CopyButton text="npm install @json-render/core @json-render/react" />
  282. </div>
  283. <div>
  284. <Button asChild>
  285. <Link href="/docs">Documentation</Link>
  286. </Button>
  287. </div>
  288. </div>
  289. </section>
  290. </>
  291. );
  292. }