构建并交付一个 omg.dev 应用
将用户的产品描述转化为可工作的、经过验证的结果。保持与代理的协作设置工作。仅询问那些能实质性改变结果的产品选择。
每次提问只问一个问题,并且只包含一个决策点。在同一次调用中提出第二个问题不会在所有客户端上显示给用户。如果用户没有说明应用应该做什么,用简单的语言询问并等待回答。不要用占位产品来替代。如果某个问题超时,在正常消息中再问一次并结束本轮对话。
建立项目
- 在快速聊天中,调用一次
omg_create_project,并提供一个简短描述性名称。对于 Expo 或通用移动应用,将template设置为expo。Expo 模板已经包含了一个可用的待办事项流程,数据存储在手机上,并集成了 Expo Router、Liquid Glass、Lucide 图标、Web 支持和 EAS 配置。使用返回的repo.cwd来执行所有命令、编辑、检查和部署。在不确定创建是否成功时,先检查omg_list_repos再重试。 - 在新项目会话中,当前目录已经是项目目录。它包含 Git、README 和此技能。不要创建第二个项目。
- 保留
.git。不要覆盖现有文件夹或将当前的快速聊天目录移动到新项目中。
选择交付路径
-
对于网站、Web 应用或 API,除非用户要求其他平台,否则使用支持的 omg.dev 运行时。在空白项目中,先搭建官方的 omg.dev React 模板,然后再编写产品代码。当前目录已包含 Git 和 omg.dev 说明,因此请在项目目录内创建一个临时目录来生成模板,将模板内容复制到项目中,然后仅删除该临时目录:
scaffold="$(mktemp -d .omg-web-scaffold-XXXXXX)" bunx --bun create-omg@latest "$scaffold" --template react-ts --no-install cp -a "$scaffold"/. . rm -rf "$scaffold" bun install此模板提供了
@omg-dev/vite-plugin、vibes-build、服务器函数、数据库支持和分析功能。不要用create-vite或手写的 Vite 脚手架替代。在选择额外包或 API 契约之前,请阅读https://docs.omg.dev/llms.txt以及https://docs.omg.dev/llms-full.txt的相关部分。 -
对于游戏(赛车、街机、益智、儿童学习、文字、3D),使用
template: "web-game"创建项目,并阅读.agents/skills/omg-web-game-builder/SKILL.md而不是自行设计引擎。其第一步在任何代码编辑之前:在后台端口 5174 上运行bun run dev,然后使用omg_expose_port暴露端口 5174(不带expoGo),然后告知用户预览已在下方的卡片中准备好。此技能中的 Expo 预览步骤(端口 8081,expoGo: true)不适用于 Web 游戏。仅当用户要求安装到 iPhone 或 Android 上的游戏,或明确提到 Expo 或原生应用时,才使用template: "expo-game"和.agents/skills/omg-game-builder/SKILL.md。 -
对于 Expo 应用,从受管理的
expo模板开始,并遵循下面的“Expo 应用:快速路径”。调整其屏幕和数据存储,而不是重新构建配置。将密钥保留在托管服务器路由中。生产原生构建需要部署在任何安全来源的服务器上;不要将沙盒隧道视为生产环境。 -
在云计算机上,使用一个正在运行的 Metro 服务器来同时服务 Expo Web 和 Expo Go。通过
omg_expose_port暴露其端口;不要假设存在全局 Expo CLI、Xcode、模拟器或特定于机器的工具。 -
当应用与 Expo Go 兼容时,
omg_expose_port会将exps://Expo Go 链接放在 omg.dev 应用中的预览卡片上。告知用户预览已准备好,并让他们从下方的卡片打开。不要在回复中粘贴原始的exps://URL;卡片已显示该链接。仅当用户无法看到卡片时(例如通过omg_send_to_origin发送到消息通道的回复),或用户明确请求链接时,才粘贴它。不要使用 Expo tunnel、LAN 暴露、exp.direct或 ngrok。如果 Expo Go 无法加载所需原生模块,则在授权后使用开发构建,或清楚地报告该限制。 -
TestFlight、App Store 提交、付费服务、域名和第三方生产账户是单独的交付操作。仅在用户请求并且所需账户可用时才执行这些操作。TestFlight 需要用户的 Expo 账户和付费的 Apple Developer 账户,但 EAS 云构建在沙盒中不需要 Xcode 或 Mac。使用支持的登录流程,切勿在聊天中索要密码或令牌。
Expo 应用:快速路径
新用户正在等待。第一个屏幕必须在大约 3 分钟内到达他们的手机,然后才能进行任何功能工作。请按顺序执行以下步骤:
- 使用
template: "expo"调用omg_create_project。如果node_modules缺失,运行一次bun install。 - 在编写任何代码之前先进行预览。使用端口 8081 和
expoGo: true调用omg_expose_port。然后在项目目录中运行bash scripts/start-expo-preview.sh <expoGo.proxyUrl> 8081,shell 超时设置为 240000 毫秒。当它打印出Sandbox proxy answers: HTTP 200时,首先显示 Web 预览:“您的应用已准备就绪。下方的卡片显示了它的运行情况,并且可以在任何设备上运行。”然后用一句话提到手机:“要在您自己的手机上试用,请点击卡片上的‘您的手机’。”当omg_expose_port的结果包含simulatorAvailable: true时,再添加一句话:“您也可以直接在卡片中试用 iPhone 模拟器:点击‘模拟器’。”当该字段为 false 或缺失时,不要提示模拟器。不要粘贴expoGo.url;卡片已显示它。Metro 会在每次保存时重新加载应用,因此预览将从此处跟随您的编辑。 - 编写屏幕,采用几次较大的编辑而不是每次一小步编辑。替换
src/app/index.tsx中的模板主页屏幕;不要添加第二个索引路由。 - 运行
bun run typecheck并修复其报告的问题。它还会检查路由,如果存在第二个主页屏幕或根app/文件夹,则会失败。然后运行bun run check:ui,打开其生成的 PNG 文件,并修复任何错误(参见构建步骤 4)。除非用户要求,否则不要编写自动化测试。 - 通过
omg_deploy部署一次(见下文)。数据保留在手机上,因此这是一个静态 Web 构建。 - 最后使用
omg_ship。
在首次预览之前,不要浏览 node_modules、获取文档或逐文件读取模板:下面的摘要已经足够。不要编写自己的浏览器测试循环或屏幕截图脚本:bun run check:ui 会执行这些操作。如果您无法查看图像,请仅阅读其文本报告。
该模板:
src/app/index.tsx:主页屏幕,也是/的唯一文件。用您的主页内容替换其内容。将所有屏幕保留在src/app/:当src/app存在时,Expo Router 会忽略根app/文件夹。对于标签页,将主页屏幕移动到src/app/(tabs)/index.tsx并删除src/app/index.tsx,因为两者都对应/,旧的那个会胜出。模板文件包含一个标题、一个带有添加按钮的输入框、一个带有切换和删除功能的列表、一个错误卡片和一个重新加载按钮。样式在底部的单个StyleSheet中;主题常量在顶部(INK、CORAL、BACKGROUND、SURFACE、SURFACE_BORDER)。src/app/_layout.tsx:一个不带标题的 Expo Router 栈,位于KeyboardProvider内部。新屏幕是src/app/中的一个新文件(stats.tsx对应于/stats)。使用router.push("/stats")或来自expo-router的<Link href="/stats">进行导航。src/lib/tasks.ts:数据,通过 AsyncStorage 存储在手机上(Web 上为 localStorage)。tasksApi.list()、create(title)、update(id, patch)、remove(id)。保留此文件。对于每种新类型的项,使用自己的存储键复制其形状。- 图标:
lucide-react-native,例如<Plus color={CORAL} size={22} />。玻璃表面:来自expo-glass-effect的GlassView。 - 颜色:在样式屏幕之前,根据设计设置每个主题常量。卡片、行和表格使用设计自己的表面颜色。模板的半透明白色
SURFACE仅适用于其浅色启动器;如果保留在深色或彩色设计上,每个卡片都会变成白色。仅在设计显示毛玻璃效果时才使用GlassView。在 Android 上它不会绘制玻璃效果,因此请为其赋予背景色。 - 安全区域:用来自
react-native-safe-area-context的SafeAreaView包裹每个屏幕,并设置edges={["top", "bottom"]},或使用useSafeAreaInsets()。切勿从react-native导入SafeAreaView:它仅限 iOS,因此在 Android 上标题会进入状态栏下方,标签栏会进入手势栏下方。 - 键盘:将带有文本输入的屏幕放入来自
src/lib/keyboard的KeyboardAwareScrollView中(bottomOffset={24}、keyboardShouldPersistTaps="handled"),就像模板所做的那样。对于固定在底部的字段,使用来自同一文件的KeyboardStickyView。从src/lib/keyboard导入它们,切勿直接从react-native-keyboard-controller导入:其.web.tsx副本可使静态 Web 导出正常工作。不要使用 React Native 的KeyboardAvoidingView:在 iOS 上,屏幕会在键盘之后缓慢移动。
数据:默认存储在手机上,使用 tasks.ts 模式。仅当用户要求使用账户或人们之间共享的数据时,才使用托管数据。然后使用 @omg-dev/sdk 和 schema.ts 中的 .scoped("user") 集合添加登录。切勿使用原始的 fetch 调用 /api/...:托管集合会针对匿名手机返回 401 Authentication required。
对于托管数据,安装最新的 @omg-dev/sdk 并在 Metr o 中测试共享数据之前部署后端。将 .omg/project.json 保留在项目目录中。托管的 Web 预览使用该注册的应用身份,并通过 SDK 自动登录其所有者。使用 <VibesAuthProvider> 和 SDK 请求。不要添加单独的预览登录、转发仪表板 cookie 或替换用户的应用权限。实体手机仍然需要应用的正常登录和已部署的后端来源。
Metro 规则:仅使用端口 8081 到 8099,因为 Expo Go 链接仅在该范围内工作。仅通过脚本启动 Metro;并非每台计算机上都安装了 npx 和 ss。
构建块 (Expo)
该模板附带了经过测试的辅助工具,位于 src/kit/ 中。直接导入它们;不要重写。它们适用于 iOS、Android 和 Web。每个文件的开头都有一条注释,说明其用法。
overlay.tsx:useConfirm()和useSheet()。<OverlayProvider>已在_layout.tsx中。对于每次删除或确认,使用if (await confirm({ title, destructive: true }))。带有按钮的Alert.alert在 Web 上没有任何作用。使用useSheet().open(node)来显示表格和表单。不要堆叠Modal组件:第二个会在第一个下面绘制,尤其是在 Web 上。ActionRow.tsx:一个可按压的行,旁边带有删除或其他操作。嵌套在可按压行内部的按钮也会在 Web 上触发该行。image.ts:await toPersistentImage(pickerAsset)。使用base64: true、quality: 0.5调用选择器,并存储返回的字符串。Web 上的选择器 URI 是blob:URL,在重新加载后就会消失。use-timer.ts:usePersistedTimer(key, durationMs),包含start、pause、resume、reset和formatClock。它存储结束时间,因此重新加载不会重置。用于每个计时器或倒计时。use-viewport.ts:useViewport()和useIsWide()。在静态 Web 导出中,useWindowDimensions()在首次渲染时可能会给出宽度 0。优先使用flex和maxWidth;仅在需要数字时才使用该 Hook。
人与人之间共享数据(共享列表、交易、群组):使用上面“数据”部分中的托管 @omg-dev/sdk 路径。不要编写本地服务器。如果不可避免需要本地服务器,请在每次响应中回答 OPTIONS 并发送以下头部:Access-Control-Allow-Origin 设置为请求的 Origin(或 *)、Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS 和 Access-Control-Allow-Headers: content-type,authorization。缺少 PUT 或 DELETE 仅在浏览器中会导致失败。
构建
- 将请求转化为小的可观察的完成条件。当用户未指定时,做出合理的视觉和技术选择。
- 在项目目录内进行脚手架搭建。对于受管理的 Expo 模板,安装其固定的依赖项并保留
.omg/template.json;不要用其他启动器替换它。对于空白项目,安装当前文档化的依赖项和配置。不要安装已退役的 omg.dev CLI 或向用户索要基础设施令牌;运行时工具提供了云凭据。 - 实现实际路径。如果产品需要共享数据、身份验证、上传或服务器工作,请使用文档化的托管 API 并验证持久性和访问控制。不要用模拟数据或仅浏览器存储来替换请求的共享行为。
- 除非用户要求,否则不要编写自动化测试。改为使用自检进行验证:运行
bun run typecheck,然后运行bun run check:ui。检查会构建 Web 导出,如果有server或backend脚本则启动它,以 390x844 分辨率打开每个路由,并在.omg/ui-check/中为每个路由保存一个 PNG。它会报告空白页面、错误边界、控制台错误、失败的请求、崩溃的服务器以及被其他元素覆盖的按钮或链接(例如标签栏下的“添加”按钮)。然后使用图像查看器打开每个 PNG,并将其与请求和任何设计参考进行比较。修复错误并再次运行检查,直到报告干净为止。说明您检查了哪个表面;Web 运行不能证明原生行为。 - 使用产品目的、本地运行命令、架构和交付说明更新 README。在本地提交完成的源代码,以便后来的 omg.dev 会话从完整的基线开始。
托管 Web 应用的登录
omg.dev 拥有 <slug>.omgs.app 上应用的登录。绝不要构建登录表单、密码字段或您自己的会话存储。
- 私有(默认):每位访客在应用打开之前登录 omg.dev。应用不需要登录 UI。
- 带登录的公开:当用户希望为访客提供登录页面时使用。将应用设置为
public...