# 快速上手

下面是一个完整的单文件应用。点击预览中的按钮，体验界面和交互；切换到代码可以复制整个入口文件。

```js preview height=260 file="index.js"
export default async function render(root, platform) {
  const ui = platform.ui;
  const hint = ui.hint("这是运行在 Life OS 中的应用。");
  root.replaceChildren(ui.page([
    ui.card([
      ui.title("你好，Life OS"),
      hint,
      ui.button("开始使用", () => {
        hint.textContent = "接下来可以添加你的应用逻辑。";
        ui.toast("准备好了");
      }),
    ]),
  ]));
}
```

## 入口函数

文件必须默认导出一个函数，宿主打开应用时调用 `render(root, platform)`。`root` 是应用根节点，`platform` 提供数据、组件和宿主能力。

`platform.ui` 的组件返回 DOM 节点。通过 `root.replaceChildren(...)` 渲染页面，通过事件回调更新界面。这里不是 React 组件，不需要 JSX，也没有 npm 依赖安装过程。

## 安装到桌面

打开 Life OS 桌面的「构建应用」，描述应用或提供上面的源码，交给 Agent 创建。希望自己提交源码时，使用[安装与更新](/doc/install)中的开发接口。

打开应用后，桌面顶部会出现标签。切换到对话或其它标签时，应用保持运行。关闭标签再打开，入口函数会重新执行，内存状态随之重建。

## 添加数据

先在桌面的「数据库」中创建数据集，或者让构建应用会话中的 Agent 创建。应用通过 `platform.data.get(slug)` 找到数据集，再通过它的 `id` 查询或写入。

```js
const todos = await platform.data.get("todo");
const rows = await platform.data.query(todos.id, {
  where: { done: false },
  limit: 20,
});
```

这里的 `todo` 必须是已有数据集的实际 slug。`query` 返回数组，业务字段位于每条记录顶层，例如 `rows[0].title`。

复杂应用直接使用[多文件包](/doc/packages)，将数据访问与页面分别保存。
