展示 HN:从数据生成 Web 界面
Show HN: Generate Web Interfaces from Data

原始链接: https://github.com/puffinsoft/syntux

## Syntux:React & Next.js 的生成式 UI Syntux 是一个用于使用 React 和 Next.js 构建动态、生成式 Web UI 的库。它利用大型语言模型 (LLM) 设计根据您的数据定制的 UI,这些数据由 **React 界面模式 (RIS)** 表示——一种 JSON-DSL,用于定义 UI 结构,而无需生成实际代码。这确保了安全性、可重用性和可缓存性。 **主要特性:** * **生成式 UI:** 基于数据 (`value`) 和描述性 `hint` 创建 UI。 * **自定义组件:** 与您现有的 React 组件无缝集成。 * **缓存:** 允许通过简单的基于字符串的模式缓存系统重用生成的 UI。 * **LLM 支持:** 通过 Vercel AI SDK 与各种 LLM 提供商(如 Anthropic 的 Claude)合作。 * **服务器动作:** 允许将服务器端功能附加到 UI 事件。 * **成本优化:** 设计用于最大限度地减少与 LLM 的 token 使用量。 要使用,只需在 `` 组件中提供数据 `value`、LLM `model` 和描述所需 UI 的 `hint`。Syntux 是开源的(MIT 许可证),并提供用于组件定义和模式生成的工具。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 Show HN: 从数据生成Web界面 (github.com/puffinsoft) 6点 由 Goose78 34分钟前 | 隐藏 | 过去 | 收藏 | 讨论 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请YC | 联系 搜索:
相关文章

原文

syntux is the generative UI library for the web. It lets you build generative UIs that are consistent and flexible.


demo.mp4
  • Streamable - display UI as you generate.
  • 🎨 Custom Components - use your own React components.
  • 💾 Cacheable - reuse generated UIs with new values.

How does it work? syntux generates a JSON-DSL to represent the UI, known as the React Interface Schema. The specifics are in the FAQ below.


syntux is built for React and Next.js.

One component is all you need:

const valueToDisplay = {
    "username": "John",
    "email": "[email protected]",
    "age": 22
}

<GeneratedUI
    model={anthropic('claude-sonnet-4-5')}
    value={valueToDisplay}
    hint="UI should look like..."   
/>

syntux takes the value into consideration and designs a UI to best display it. value can be anything; an object, array or primitive.

Tip

If you are passing in a large array as a value, or an object with untrusted input, use the skeletonize property. See the explanation.

In the root of your project:

This will automatically install the required components in the lib/getsyntux folder.

We use the Vercel AI SDK to provide support for all LLM providers. To install the model providers:

$ npm i ai
$ npm i @ai-sdk/anthropic (if you're using Claude)

Generate a simple UI with a hint:

import { GeneratedUI } from "@/lib/getsyntux/GeneratedUI";
import { createAnthropic } from "@ai-sdk/anthropic";

/* this example uses Claude, but all models are supported! */
const anthropic = createAnthropic({ apiKey: ... })

export default function Home(){
    const valueToDisplay = { ... };
    return <GeneratedUI model={anthropic("claude-sonnet-4-5")} value={valueToDisplay} hint="UI should look like..." />
}

Cache generated UI based on a user ID:

const cache: Map<number, string> = new Map();
export default function Home(){
    const userID = 10;
    const valueToDisplay = { ... };
    return <GeneratedUI cached={cache.get(userID)} onGenerate={(result) => {
        cache.set(userID, result)
    }} model={anthropic("claude-sonnet-4-5")} value={valueToDisplay} />
}

Use your own components, or someone else's (a library):

import { CustomOne, CustomTwo } from '@/my_components'
export default function Home(){
   const valueToDisplay = { ... };

   <GeneratedUI components={[
    { name: 'Button', props: "{ color: string, text: string }", component: CustomOne },
    { name: 'Input', props: "{ initial: string, disabled: boolean }", component: CustomTwo, context: "Creates an input field with an (initial) value. Can be disabled." }
   ]} />
}

Note: the components array above can be generated automatically with npx getsyntux generate-defs <component.tsx>. See the documentation.

Perform server actions, attached automatically to component events:

import { defineTool } from "getsyntux";

export default function Home(){
   const valueToDisplay = { ... };

   <GeneratedUI actions = {{
    "delete": defineTool(async (id: string) => { "use server"; /* ... */ }, "id: string", "deletes post with id"),
    "refresh": defineTool(async () => { "use server"; /* ... */})
   }} />
}

Note: The name of the action should specify its purpose (it is seen by the LLM). Use defineTool to add further context to actions. See the documentation.


How expensive is generation?

syntux is highly optimized to save tokens. See here for a cost estimation table and an explanation.

How does generation work? (Does it generate source code?)

Generated UIs must be secure, reusable and cacheable.

As such, syntux does not generate source code. It generates a schema for the UI, known as a "React Interface Schema" (RIS). See the question below to get a better understanding.

This schema is tailored to the value that you provide. It is then hydrated by syntux and rendered.

How does caching work?

The generated UI is determined by the React Interface Schema (see the above question).

Thus, if the same schema is provided, the same UI will be generated.

For simplicity, the schema is simply a string. It is up to you how you wish to store it; in memory, in a file, in a database etc,.

Use the onGenerate and cached properties to retrieve/provide a cached schema respectively.

What about state? Can state be generated?

Generating state is an anti-pattern and leads to poorly performing, insecure applications.

If you need to handle state, wrap non-stateful components in stateful ones, then pass those as custom components to syntux.

What does the React Interface Schema look like?

It's a list of JSON objects, each delimited by a newline. Each object contains information about the element/component, props, and an id and parentId.

The RIS does not hardcode values. It binds to properties of the value and has built-in iterators (with the type field), making it reusable and token-efficient (for arrays).

Originally (pre-v0.2.x), the schema was a deep JSON tree. However, post-v0.2.x it was switched to a flat JSON list, as this allows for the UI to be built progressively (streamed).

As such, the id and parentId fields are used to construct the tree as-you-go.

Below is an example:

{"id":"loop_1", "parentId":"root", "type":"__ForEach__", "props":{"source":"authors"}}
{"id":"card_1", "parentId":"loop_1", "type":"div", "props":{"className":"card"}, "content": {"$bind": "$item.name"}}

To get a better understanding, or to implement your own parser, see the spec.


syntux is open source software, licensed under the MIT license.

联系我们 contact @ memedata.com