next

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

@json-render/next

@json-render/next

Next.js renderer that converts JSON specs into full Next.js applications with routes, pages, layouts, metadata, and SSR support.
该Next.js渲染器可将JSON规范转换为包含路由、页面、布局、元数据和SSR支持的完整Next.js应用。

Quick Start

快速开始

bash
npm install @json-render/core @json-render/react @json-render/next
bash
npm install @json-render/core @json-render/react @json-render/next

1. Define Your Spec

1. 定义你的规范

typescript
// lib/spec.ts
import type { NextAppSpec } from "@json-render/next";

export const spec: NextAppSpec = {
  metadata: {
    title: { default: "My App", template: "%s | My App" },
    description: "A json-render Next.js application",
  },
  layouts: {
    main: {
      root: "shell",
      elements: {
        shell: { type: "Container", props: {}, children: ["nav", "slot"] },
        nav: { type: "NavBar", props: { links: [
          { href: "/", label: "Home" },
          { href: "/about", label: "About" },
        ]}, children: [] },
        slot: { type: "Slot", props: {}, children: [] },
      },
    },
  },
  routes: {
    "/": {
      layout: "main",
      metadata: { title: "Home" },
      page: {
        root: "hero",
        elements: {
          hero: { type: "Card", props: { title: "Welcome" }, children: [] },
        },
      },
    },
    "/about": {
      layout: "main",
      metadata: { title: "About" },
      page: {
        root: "content",
        elements: {
          content: { type: "Card", props: { title: "About Us" }, children: [] },
        },
      },
    },
  },
};
typescript
// lib/spec.ts
import type { NextAppSpec } from "@json-render/next";

export const spec: NextAppSpec = {
  metadata: {
    title: { default: "My App", template: "%s | My App" },
    description: "A json-render Next.js application",
  },
  layouts: {
    main: {
      root: "shell",
      elements: {
        shell: { type: "Container", props: {}, children: ["nav", "slot"] },
        nav: { type: "NavBar", props: { links: [
          { href: "/", label: "Home" },
          { href: "/about", label: "About" },
        ]}, children: [] },
        slot: { type: "Slot", props: {}, children: [] },
      },
    },
  },
  routes: {
    "/": {
      layout: "main",
      metadata: { title: "Home" },
      page: {
        root: "hero",
        elements: {
          hero: { type: "Card", props: { title: "Welcome" }, children: [] },
        },
      },
    },
    "/about": {
      layout: "main",
      metadata: { title: "About" },
      page: {
        root: "content",
        elements: {
          content: { type: "Card", props: { title: "About Us" }, children: [] },
        },
      },
    },
  },
};

2. Create the App

2. 创建应用

typescript
// lib/app.ts
import { createNextApp } from "@json-render/next/server";
import { spec } from "./spec";

export const { Page, generateMetadata, generateStaticParams } = createNextApp({
  spec,
  loaders: {
    // Server-side data loaders (optional)
    loadPost: async ({ slug }) => {
      const post = await getPost(slug as string);
      return { post };
    },
  },
});
typescript
// lib/app.ts
import { createNextApp } from "@json-render/next/server";
import { spec } from "./spec";

export const { Page, generateMetadata, generateStaticParams } = createNextApp({
  spec,
  loaders: {
    // Server-side data loaders (optional)
    loadPost: async ({ slug }) => {
      const post = await getPost(slug as string);
      return { post };
    },
  },
});

3. Wire Up Route Files

3. 连接路由文件

tsx
// app/[[...slug]]/page.tsx
export { Page as default, generateMetadata, generateStaticParams } from "@/lib/app";
tsx
// app/[[...slug]]/layout.tsx
import { NextAppProvider } from "@json-render/next";
import { registry, handlers } from "@/lib/registry";

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <NextAppProvider registry={registry} handlers={handlers}>
          {children}
        </NextAppProvider>
      </body>
    </html>
  );
}
tsx
// app/[[...slug]]/page.tsx
export { Page as default, generateMetadata, generateStaticParams } from "@/lib/app";
tsx
// app/[[...slug]]/layout.tsx
import { NextAppProvider } from "@json-render/next";
import { registry, handlers } from "@/lib/registry";

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <NextAppProvider registry={registry} handlers={handlers}>
          {children}
        </NextAppProvider>
      </body>
    </html>
  );
}

Key Concepts

核心概念

NextAppSpec

NextAppSpec

The top-level spec defines an entire Next.js application:
  • metadata: Root-level SEO metadata (title template, description, OpenGraph)
  • layouts: Reusable layout element trees (each must include a
    Slot
    component)
  • routes: Route definitions keyed by URL pattern
  • state: Global initial state shared across all routes
顶层规范定义了完整的Next.js应用:
  • metadata: 根层级SEO元数据(标题模板、描述、OpenGraph)
  • layouts: 可复用的布局元素树(每个布局必须包含一个
    Slot
    组件)
  • routes: 以URL模式为键的路由定义
  • state: 所有路由共享的全局初始状态

Route Patterns

路由模式

Routes use Next.js URL conventions:
  • "/"
    -- home page
  • "/about"
    -- static route
  • "/blog/[slug]"
    -- dynamic segment
  • "/docs/[...path]"
    -- catch-all segment
  • "/settings/[[...path]]"
    -- optional catch-all segment
路由遵循Next.js URL约定:
  • "/"
    -- 首页
  • "/about"
    -- 静态路由
  • "/blog/[slug]"
    -- 动态段
  • "/docs/[...path]"
    -- 全匹配段
  • "/settings/[[...path]]"
    -- 可选全匹配段

Layouts

布局

Layouts wrap page content. Every layout MUST include a
Slot
component where page content will be rendered. Layouts are defined once in
spec.layouts
and referenced by routes via the
layout
field.
布局用于包裹页面内容。每个布局必须包含一个
Slot
组件,作为页面内容的渲染位置。布局在
spec.layouts
中定义一次,即可通过
layout
字段被路由引用。

Built-in Components

内置组件

  • Slot: Placeholder in layouts where page content is rendered
  • Link: Client-side navigation link (wraps
    next/link
    )
  • Slot: 布局中用于渲染页面内容的占位符
  • Link: 客户端导航链接(封装了
    next/link

Built-in Actions

内置操作

  • setState: Update state value. Params:
    { statePath, value }
  • pushState: Append to array. Params:
    { statePath, value, clearStatePath? }
  • removeState: Remove from array by index. Params:
    { statePath, index }
  • navigate: Client-side navigation. Params:
    { href }
  • setState: 更新状态值,参数:
    { statePath, value }
  • pushState: 向数组追加内容,参数:
    { statePath, value, clearStatePath? }
  • removeState: 根据索引删除数组元素,参数:
    { statePath, index }
  • navigate: 客户端导航,参数:
    { href }

Data Loaders

数据加载器

Server-side async functions that run in the Server Component before rendering. Results are merged into the page's initial state.
typescript
createNextApp({
  spec,
  loaders: {
    loadPost: async ({ slug }) => {
      const post = await db.post.findUnique({ where: { slug } });
      return { post };
    },
  },
});
服务端异步函数,在渲染前于服务端组件中运行,运行结果会合并到页面的初始状态中。
typescript
createNextApp({
  spec,
  loaders: {
    loadPost: async ({ slug }) => {
      const post = await db.post.findUnique({ where: { slug } });
      return { post };
    },
  },
});

SSR

SSR

Pages are server-rendered automatically. The
createNextApp
Page
component is an async Server Component that:
  1. Matches the route from the spec
  2. Runs server-side data loaders
  3. Generates metadata
  4. Passes the resolved spec to the client renderer for hydration
页面会自动进行服务端渲染。
createNextApp
生成的
Page
组件是异步服务端组件,会执行以下操作:
  1. 匹配规范中定义的路由
  2. 运行服务端数据加载器
  3. 生成元数据
  4. 将解析后的规范传递给客户端渲染器进行水合

Entry Points

入口点

  • @json-render/next
    -- Client components (NextAppProvider, PageRenderer, Link)
  • @json-render/next/server
    -- Server utilities (createNextApp, matchRoute, schema)
  • @json-render/next
    -- 客户端组件(NextAppProvider、PageRenderer、Link)
  • @json-render/next/server
    -- 服务端工具函数(createNextApp、matchRoute、schema)

API Reference

API 参考

Server Exports (
@json-render/next/server
)

服务端导出(
@json-render/next/server

  • createNextApp(options)
    -- Create Page, generateMetadata, generateStaticParams
  • schema
    -- Custom schema for Next.js apps (for AI catalog generation)
  • matchRoute(spec, pathname)
    -- Match a URL to a route spec
  • resolveMetadata(spec, route)
    -- Resolve metadata for a route
  • slugToPath(slug)
    -- Convert catch-all slug array to pathname
  • collectStaticParams(spec)
    -- Collect static params for all routes
  • createNextApp(options)
    -- 生成Page、generateMetadata、generateStaticParams
  • schema
    -- 适用于Next.js应用的自定义schema(用于AI目录生成)
  • matchRoute(spec, pathname)
    -- 将URL匹配到对应路由规范
  • resolveMetadata(spec, route)
    -- 解析路由对应的元数据
  • slugToPath(slug)
    -- 将全匹配slug数组转换为路径名
  • collectStaticParams(spec)
    -- 收集所有路由的静态参数

Client Exports (
@json-render/next
)

客户端导出(
@json-render/next

  • NextAppProvider
    -- Context provider for registry and handlers
  • PageRenderer
    -- Renders a page spec with optional layout
  • NextErrorBoundary
    -- Error boundary component
  • NextLoading
    -- Loading state component
  • NextNotFound
    -- Not-found component
  • Link
    -- Built-in navigation component (wraps next/link)
  • NextAppProvider
    -- 用于registry和handlers的上下文Provider
  • PageRenderer
    -- 渲染页面规范,支持可选布局
  • NextErrorBoundary
    -- 错误边界组件
  • NextLoading
    -- 加载状态组件
  • NextNotFound
    -- 未找到页面组件
  • Link
    -- 内置导航组件(封装了next/link)