page.tsx 10 KB

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