mirror of
https://github.com/vercel-labs/json-render.git
synced 2026-10-03 12:28:17 +08:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7a7bfb9ba |
+9
-2
@@ -6,8 +6,11 @@ node_modules
|
||||
.pnp.js
|
||||
|
||||
# Local env files
|
||||
.env*
|
||||
!.env.example
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
@@ -41,6 +44,10 @@ yarn-error.log*
|
||||
# opensrc - source code for packages
|
||||
opensrc/
|
||||
|
||||
# json-studio (separate repo)
|
||||
json-studio/
|
||||
.env*.local
|
||||
|
||||
# Stripe apps (generated from template + build artifacts)
|
||||
examples/stripe-app/*/stripe-app.json
|
||||
examples/stripe-app/*/.build
|
||||
|
||||
@@ -27,26 +27,6 @@ This ensures we don't install outdated versions that may have incompatible types
|
||||
- Do not use emojis in code or UI
|
||||
- Use shadcn CLI to add shadcn/ui components: `pnpm dlx shadcn@latest add <component>`
|
||||
|
||||
## Dev Servers
|
||||
|
||||
All apps and examples with dev servers use [portless](https://github.com/vercel-labs/portless) to avoid hardcoded ports. Portless assigns random ports and exposes each app via `.localhost` URLs.
|
||||
|
||||
Naming convention:
|
||||
- Main web app: `json-render` → `json-render.localhost:1355`
|
||||
- Examples: `[name]-demo.json-render` → `[name]-demo.json-render.localhost:1355`
|
||||
|
||||
When adding a new example that runs a dev server, wrap its `dev` script with `portless <name>`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "portless my-example-demo.json-render next dev --turbopack"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Do **not** add `--port` flags -- portless handles port assignment automatically. Do **not** add portless as a project dependency; it must be installed globally.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Run `pnpm type-check` after each turn to ensure type safety
|
||||
|
||||
@@ -343,9 +343,9 @@ pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- http://json-render.localhost:1355 - Docs & Playground
|
||||
- http://dashboard-demo.json-render.localhost:1355 - Example Dashboard
|
||||
- http://remotion-demo.json-render.localhost:1355 - Remotion Video Example
|
||||
- http://localhost:3000 - Docs & Playground
|
||||
- http://localhost:3001 - Example Dashboard
|
||||
- http://localhost:3002 - Remotion Video Example
|
||||
- Chat Example: run `pnpm dev` in `examples/chat`
|
||||
- React Native example: run `npx expo start` in `examples/react-native`
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ pnpm dev
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://json-render.localhost:1355](http://json-render.localhost:1355) with your browser to see the result.
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/a2ui")
|
||||
export const metadata = { title: "A2UI Integration" }
|
||||
|
||||
# A2UI Integration
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/adaptive-cards")
|
||||
export const metadata = { title: "Adaptive Cards Integration" }
|
||||
|
||||
# Adaptive Cards Integration
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/ag-ui")
|
||||
export const metadata = { title: "AG-UI Integration" }
|
||||
|
||||
# AG-UI Integration
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/ai-sdk")
|
||||
export const metadata = { title: "AI SDK Integration" }
|
||||
|
||||
# AI SDK Integration
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/codegen")
|
||||
export const metadata = { title: "@json-render/codegen API" }
|
||||
|
||||
# @json-render/codegen
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/core")
|
||||
export const metadata = { title: "@json-render/core API" }
|
||||
|
||||
# @json-render/core
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/react-native")
|
||||
export const metadata = { title: "@json-render/react-native API" }
|
||||
|
||||
# @json-render/react-native
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/react-pdf")
|
||||
export const metadata = { title: "@json-render/react-pdf API" }
|
||||
|
||||
# @json-render/react-pdf
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/react")
|
||||
export const metadata = { title: "@json-render/react API" }
|
||||
|
||||
# @json-render/react
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/remotion")
|
||||
export const metadata = { title: "@json-render/remotion API" }
|
||||
|
||||
# @json-render/remotion
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/api/shadcn")
|
||||
export const metadata = { title: "@json-render/shadcn API" }
|
||||
|
||||
# @json-render/shadcn
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/catalog")
|
||||
export const metadata = { title: "Catalog" }
|
||||
|
||||
# Catalog
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/changelog")
|
||||
export const metadata = { title: "Changelog" }
|
||||
|
||||
# Changelog
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/code-export")
|
||||
export const metadata = { title: "Code Export" }
|
||||
|
||||
# Code Export
|
||||
|
||||
@@ -135,6 +134,6 @@ Run the dashboard example and click "Export Project" to see code generation in a
|
||||
```bash
|
||||
cd examples/dashboard
|
||||
pnpm dev
|
||||
# Open http://dashboard-demo.json-render.localhost:1355
|
||||
# Open http://localhost:3001
|
||||
# Generate a widget, then click "Export Project"
|
||||
```
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/custom-schema")
|
||||
export const metadata = { title: "Custom Schema & Renderer" }
|
||||
|
||||
# Custom Schema & Renderer
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/data-binding")
|
||||
export const metadata = { title: "Data Binding" }
|
||||
|
||||
# Data Binding
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/generation-modes")
|
||||
export const metadata = { title: "Generation Modes" }
|
||||
|
||||
# Generation Modes
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/installation")
|
||||
export const metadata = { title: "Installation" }
|
||||
|
||||
# Installation
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/migration")
|
||||
export const metadata = { title: "Migration Guide" }
|
||||
|
||||
# Migration Guide
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/openapi")
|
||||
export const metadata = { title: "OpenAPI Integration" }
|
||||
|
||||
# OpenAPI Integration
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs")
|
||||
export const metadata = { title: "Introduction" }
|
||||
|
||||
# Introduction
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/quick-start")
|
||||
export const metadata = { title: "Quick Start" }
|
||||
|
||||
# Quick Start
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/registry")
|
||||
export const metadata = { title: "Registry" }
|
||||
|
||||
# Registry
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/schemas")
|
||||
export const metadata = { title: "Schemas" }
|
||||
|
||||
# Schemas
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/specs")
|
||||
export const metadata = { title: "Specs" }
|
||||
|
||||
# Specs
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/streaming")
|
||||
export const metadata = { title: "Streaming" }
|
||||
|
||||
# Streaming
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/validation")
|
||||
export const metadata = { title: "Validation" }
|
||||
|
||||
# Validation
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pageMetadata } from "@/lib/page-metadata"
|
||||
export const metadata = pageMetadata("docs/visibility")
|
||||
export const metadata = { title: "Visibility" }
|
||||
|
||||
# Visibility
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Metadata } from "next";
|
||||
import localFont from "next/font/local";
|
||||
import { GeistPixelSquare } from "geist/font/pixel";
|
||||
import "./globals.css";
|
||||
import { ThemeProvider } from "@/components/theme-provider";
|
||||
import { DocsChat } from "@/components/docs-chat";
|
||||
@@ -62,6 +61,7 @@ export const metadata: Metadata = {
|
||||
description:
|
||||
"The Generative UI framework. Generate dashboards, widgets, and apps from prompts — safely constrained to components you define.",
|
||||
images: ["/og"],
|
||||
creator: "@verabornnot",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
@@ -92,9 +92,7 @@ export default async function RootLayout({
|
||||
/>
|
||||
)}
|
||||
</head>
|
||||
<body
|
||||
className={`${geistSans.variable} ${geistMono.variable} ${GeistPixelSquare.variable}`}
|
||||
>
|
||||
<body className={`${geistSans.variable} ${geistMono.variable}`}>
|
||||
<ThemeProvider>
|
||||
{children}
|
||||
<DocsChat defaultOpen={chatOpen} defaultWidth={chatWidth} />
|
||||
|
||||
@@ -57,7 +57,7 @@ export function Header() {
|
||||
</svg>
|
||||
</span>
|
||||
<Link href="/">
|
||||
<span className="font-medium tracking-tight text-lg font-(family-name:--font-geist-pixel-square)">
|
||||
<span className="font-medium tracking-tight text-lg">
|
||||
json-render
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import type { Metadata } from "next";
|
||||
import { PAGE_TITLES } from "./page-titles";
|
||||
|
||||
const DESCRIPTION =
|
||||
"The Generative UI framework. Generate dashboards, widgets, and apps from prompts — safely constrained to components you define.";
|
||||
|
||||
export function pageMetadata(slug: string): Metadata {
|
||||
const title = PAGE_TITLES[slug];
|
||||
if (!title) return {};
|
||||
|
||||
const displayTitle = title.replace(/\n/g, " ");
|
||||
const fullTitle = `${displayTitle} | json-render`;
|
||||
const ogImageUrl = slug ? `/og/${slug}` : "/og";
|
||||
|
||||
return {
|
||||
title: displayTitle,
|
||||
openGraph: {
|
||||
type: "website",
|
||||
locale: "en_US",
|
||||
siteName: "json-render",
|
||||
title: fullTitle,
|
||||
description: DESCRIPTION,
|
||||
images: [
|
||||
{
|
||||
url: ogImageUrl,
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: `${displayTitle} - json-render`,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: fullTitle,
|
||||
description: DESCRIPTION,
|
||||
images: [ogImageUrl],
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -42,7 +42,6 @@ export const PAGE_TITLES: Record<string, string> = {
|
||||
"docs/api/react-native": "@json-render/react-native API",
|
||||
"docs/api/codegen": "@json-render/codegen API",
|
||||
"docs/api/remotion": "@json-render/remotion API",
|
||||
"docs/api/shadcn": "@json-render/shadcn API",
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"dev": "portless json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
@@ -33,7 +33,6 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"geist": "1.7.0",
|
||||
"just-bash": "2.9.6",
|
||||
"lucide-react": "^0.562.0",
|
||||
"next": "16.1.1",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "portless chat-demo.json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "portless dashboard-demo.json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "portless no-ai-demo.json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack --port 3003",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "portless react-pdf-demo.json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack --port 3005",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"check-types": "tsc --noEmit"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "portless remotion-demo.json-render next dev --turbopack",
|
||||
"dev": "next dev --turbopack --port 3002",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"check-types": "tsc --noEmit"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "portless stripe-api-demo.json-render next dev",
|
||||
"dev": "next dev --port 3001",
|
||||
"build": "next build",
|
||||
"start": "next start --port 3001"
|
||||
},
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export const API_GENERATE_URL =
|
||||
"http://stripe-api-demo.json-render.localhost:1355/api/generate";
|
||||
export const API_GENERATE_URL = "http://localhost:3001/api/generate";
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export const API_GENERATE_URL =
|
||||
"http://stripe-api-demo.json-render.localhost:1355/api/generate";
|
||||
export const API_GENERATE_URL = "http://localhost:3001/api/generate";
|
||||
|
||||
Generated
-12
@@ -113,9 +113,6 @@ importers:
|
||||
embla-carousel-react:
|
||||
specifier: ^8.6.0
|
||||
version: 8.6.0(react@19.2.3)
|
||||
geist:
|
||||
specifier: 1.7.0
|
||||
version: 1.7.0(next@16.1.1(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
|
||||
just-bash:
|
||||
specifier: 2.9.6
|
||||
version: 2.9.6
|
||||
@@ -6947,11 +6944,6 @@ packages:
|
||||
fzf@0.5.2:
|
||||
resolution: {integrity: sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==}
|
||||
|
||||
geist@1.7.0:
|
||||
resolution: {integrity: sha512-ZaoiZwkSf0DwwB1ncdLKp+ggAldqxl5L1+SXaNIBGkPAqcu+xjVJLxlf3/S8vLt9UHx1xu5fz3lbzKCj5iOVdQ==}
|
||||
peerDependencies:
|
||||
next: '>=13.2.0'
|
||||
|
||||
generator-function@2.0.1:
|
||||
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -18955,10 +18947,6 @@ snapshots:
|
||||
|
||||
fzf@0.5.2: {}
|
||||
|
||||
geist@1.7.0(next@16.1.1(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)):
|
||||
dependencies:
|
||||
next: 16.1.1(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
|
||||
generator-function@2.0.1: {}
|
||||
|
||||
gensync@1.0.0-beta.2: {}
|
||||
|
||||
Reference in New Issue
Block a user