From 421f19bfd0021060bdad0305a9f1208df3b1bc61 Mon Sep 17 00:00:00 2001 From: shaun Date: Fri, 27 Mar 2026 16:39:17 +0800 Subject: [PATCH 01/15] update --- docusaurus.config.js | 19 +- i18n/en/code.json | 213 +++++++++-- i18n/zh-CN/code.json | 210 ++++++++-- src/components/HomepageCliEntry/index.tsx | 10 +- src/components/HomepageCodexBlocks/index.tsx | 98 +++++ .../HomepageCodexBlocks/styles.module.scss | 361 ++++++++++++++++++ .../HomepageProductComparison/index.tsx | 5 +- src/components/StudioDetailContent/index.tsx | 148 +++---- .../StudioDetailContent/styles.module.scss | 45 +++ src/pages/cloud/index.tsx | 253 ++++++++++++ src/pages/cloud/styles.module.scss | 356 +++++++++++++++++ src/pages/index.tsx | 10 +- src/pages/studio/index.tsx | 220 +++++++++++ src/pages/studio/styles.module.scss | 343 +++++++++++++++++ src/theme/Navbar/index.tsx | 163 +++++++- src/theme/Navbar/styles.module.scss | 136 +++++++ 16 files changed, 2407 insertions(+), 183 deletions(-) create mode 100644 src/components/HomepageCodexBlocks/index.tsx create mode 100644 src/components/HomepageCodexBlocks/styles.module.scss create mode 100644 src/pages/cloud/index.tsx create mode 100644 src/pages/cloud/styles.module.scss create mode 100644 src/pages/studio/index.tsx create mode 100644 src/pages/studio/styles.module.scss diff --git a/docusaurus.config.js b/docusaurus.config.js index 12cf0011..bf292ba3 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -176,13 +176,30 @@ const config = { srcDark: "img/logo-en-dark.svg", }, items: [ + { + label: "Product", + position: "left", + className: "productDropdown", + items: [ + { + to: "/studio", + label: "navbar.oomol-studio", + className: "productDropdownItem productDropdownItemStudio", + }, + { + to: "/cloud", + label: "navbar.oomol-cloud", + className: "productDropdownItem productDropdownItemCloud", + }, + ], + }, + { to: "/downloads", label: "navbar.download", position: "left" }, { type: "doc", docId: "overview", position: "left", label: "Docs", }, - { to: "/downloads", label: "navbar.download", position: "left" }, { to: "/pricing", label: "navbar.pricing", position: "left" }, { to: "/updates", label: "Updates", position: "left" }, { to: "/blog", label: "Blog", position: "left" }, diff --git a/i18n/en/code.json b/i18n/en/code.json index 40912342..7d06bb8b 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -27,16 +27,16 @@ "message": "Community" }, "HOME.page.title": { - "message": "OOMOL - Write Functions in Studio and Let AI Use Them" + "message": "OOMOL - Build and Deliver Capabilities for Agents" }, "HOME.FirstScreen.slogan": { - "message": "Write Function. Deliver Service." + "message": "Build and Deliver Capabilities for Agents" }, "HOME.FirstScreen.kicker": { - "message": "A Studio + CLI workflow for developers" + "message": "A capability production and delivery path for developers" }, "HOME.FirstScreen.script": { - "message": "Write functions in Studio, validate them locally, then publish them to OOMOL Cloud. After that, sign in with the OOMOL CLI so Codex or Claude Code can call those cloud functions directly, while the same capability remains available as an API, MCP tool, or automation task." + "message": "Start with ready-made capabilities in oo-cli, create your own blocks in OOMOL Studio, then deploy and deliver them privately through Cloud." }, "HOME.FirstScreen.pill1": { "message": "No new DSL" @@ -873,10 +873,10 @@ "message": "//#region generated meta\ntype Inputs = {\n};\ntype Outputs = {\n};\n//#endregion\n\nimport type { Context } from \"@oomol/types/oocana\";\n\nexport default async function(\n params: Inputs,\n context: Context\n): Promise | undefined | void> {\n // Fusion API Base URL\n const api_url = \"https://fusion-api.oomol.com/v1/fal-nano-banana-edit/submit\"\n\n // LLM Base URL, can use openai sdk\n const llm_base_url = \"https://llm.oomol.com/v1\"\n\n // Get OOMOL token from context (no need for manual API key input)\n const api_token = await context.getOomolToken()\n // return { output: \"output_value\" };\n};" }, "HOME.GetStartedPrompt.title": { - "message": "Start with your next function and let AI use it" + "message": "Get the first path working" }, "HOME.GetStartedPrompt.subtitle": { - "message": "Download OOMOL Studio, write and validate your function locally, publish it to OOMOL Cloud, then sign in with the OOMOL CLI to use it from Codex or Claude Code, or keep delivering it as an API, MCP tool, or automation task." + "message": "Start with oo-cli to use published capabilities. When you need more, write your own blocks in OOMOL Studio and deploy them through Cloud." }, "HOME.Pricing.title": { "message": "Pricing" @@ -2467,10 +2467,10 @@ "message": "Containerized deployment to private cloud or K8s clusters, supporting CI/CD pipelines for continuous delivery and operations of enterprise-grade API services." }, "HOME.ProductComparison.title": { - "message": "Cloud keeps the function running reliably online" + "message": "Cloud exists for delivery, not just hosting" }, "HOME.ProductComparison.subtitle": { - "message": "If Studio is where you write the function, then OOMOL Cloud is the shared runtime and delivery layer. After sign-in, the CLI calls the cloud functions deployed there from Codex or Claude Code." + "message": "Cloud is not just where code runs. It is where validated blocks become capabilities you can keep providing to yourself, your team, or your customers." }, "HOME.ChatAgent.title": { "message": "OOMOL Chat & Agent Ecosystem" @@ -2515,43 +2515,43 @@ "message": "Install locally and use immediately, with a built-in container environment that keeps development and validation in one place." }, "HOME.ProductComparison.cloud.stage": { - "message": "Launch faster, manage less" + "message": "Deploy and deliver" }, "HOME.ProductComparison.cloud.capability": { - "message": "Turn a validated function into a shared online capability for CLI, APIs, and automation without rebuilding interfaces, runtimes, and scaling layers." + "message": "Deploy validated blocks as cloud functions and keep providing them reliably without rebuilding another service layer around the same capability." }, "HOME.ProductComparison.cloud.scenario": { - "message": "For developers and small teams that want to provide functions reliably to AI tools, applications, or automation tasks." + "message": "For developers and small teams that want to extend CLI workflows, provide shared capabilities internally, or deliver skills and CLI services to customers." }, "HOME.ProductComparison.cloud.tech": { - "message": "Reuse the implementation you already validated in Studio while OOMOL Cloud handles runtime, auth, and external delivery. The CLI signs in and calls the cloud functions from this layer." + "message": "Reuse the implementation you already validated in Studio while OOMOL Cloud handles runtime and external delivery. When needed, the same capability can keep expanding through API or MCP." }, "HOME.ProductComparison.cta": { - "message": "Explore OOMOL Cloud" + "message": "Explore Cloud Function" }, "HOME.ProductComparison.outputIntro": { - "message": "Delivery Targets" + "message": "Keep the same capability expanding" }, "HOME.ProductComparison.outputSummary": { - "message": "The same validated function can keep shipping as an API, MCP tool, or automation task, acting as one stable capability layer for both AI tools and applications." + "message": "The same validated block can keep being consumed and integrated in different ways." }, "HOME.ProductComparison.output1.title": { - "message": "API Services" + "message": "CLI Usage" }, "HOME.ProductComparison.output1.description": { - "message": "Expose the function directly as a callable API without building a separate service framework or runtime layer." + "message": "Search, inspect, and run deployed capabilities directly through oo-cli." }, "HOME.ProductComparison.output2.title": { - "message": "MCP Tools" + "message": "API Integration" }, "HOME.ProductComparison.output2.description": { - "message": "Let the same implementation enter the call chain of agents and AI apps directly instead of maintaining a second tool service." + "message": "Carry the same capability into your own applications, services, or automation code." }, "HOME.ProductComparison.output3.title": { - "message": "Automation Tasks" + "message": "MCP Integration" }, "HOME.ProductComparison.output3.description": { - "message": "Turn the same implementation into scheduled jobs or automation flows so online runs and later iteration keep reusing one capability." + "message": "When needed, keep exposing the same capability to other agent and tool systems." }, "HOME.ProductComparison.benefit1.label": { "message": "Delivery Overhead" @@ -2629,13 +2629,13 @@ "message": "Explore OOMOL Cloud" }, "HOME.CliEntry.badge": { - "message": "CLI QUICKSTART" + "message": "CLI FIRST" }, "HOME.CliEntry.title": { - "message": "Install oo-cli, sign in once, then start calling published functions." + "message": "Use first, then decide whether to build your own" }, "HOME.CliEntry.subtitle": { - "message": "Install the CLI, then get the first search and run working." + "message": "oo-cli is the fastest way into OOMOL. Search, inspect, and run published capabilities directly from the terminal." }, "HOME.CliEntry.bridge": { "message": "Publish the function to OOMOL Cloud first. Then let CLI handle sign-in, discovery, and execution. That relationship only needs to be stated once." @@ -2644,31 +2644,31 @@ "message": "Install oo-cli" }, "HOME.CliEntry.step1.description": { - "message": "Set up the CLI entry point." + "message": "Install the entry point for using published capabilities." }, "HOME.CliEntry.step2.title": { "message": "Sign in to your account" }, "HOME.CliEntry.step2.description": { - "message": "Run oo login." + "message": "Sign in, then start searching and running capabilities." }, "HOME.CliEntry.step3.title": { - "message": "Search and run a published function" + "message": "Search and run a capability" }, "HOME.CliEntry.step3.description": { - "message": "Search, then run." + "message": "Check what it does and what input it needs, then run it directly." }, "HOME.CliEntry.action.primary": { - "message": "Open CLI Quickstart" + "message": "Open oo-cli" }, "HOME.CliEntry.action.secondary": { - "message": "See How Cloud Delivery Works" + "message": "Explore Cloud Function" }, "HOME.CliEntry.setup.eyebrow": { "message": "INSTALL ONCE" }, "HOME.CliEntry.setup.title": { - "message": "Two commands to install and sign in" + "message": "Two commands to install and sign in to oo-cli" }, "HOME.CliEntry.setup.pill": { "message": "30 sec" @@ -2680,7 +2680,7 @@ "message": "FIRST RUN DEMO" }, "HOME.CliEntry.demo.title": { - "message": "Compress the first run into search, inspect, and run" + "message": "Reduce the first run to three steps" }, "HOME.CliEntry.demo.badge": { "message": "Usage Flow" @@ -2710,7 +2710,7 @@ "message": "Run" }, "HOME.CliEntry.demo.stage3.title": { - "message": "Run and fetch result" + "message": "Run and get the result" }, "HOME.CliEntry.demo.stage3.description": { "message": "Cloud executes the function. CLI is the layer that sends the task and pulls the result back into the current workflow." @@ -2724,12 +2724,75 @@ "HOME.CliEntry.terminal.note": { "message": "CLI is not just another entry point. After sign-in, it is the layer that connects cloud functions deployed on OOMOL Cloud to Codex, Claude Code, and other terminal workflows in a stable way." }, + "HOME.CodexBlocks.badge": { + "message": "CODEX EXAMPLES" + }, + "HOME.CodexBlocks.title": { + "message": "Start with representative blocks in Codex" + }, + "HOME.CodexBlocks.subtitle": { + "message": "Instead of the old proof section, show the kinds of blocks that better define OOMOL's capability surface. Search, inspect, and run them in Codex first, then decide whether you need to build your own." + }, + "HOME.CodexBlocks.action.primary": { + "message": "Open oo-cli" + }, + "HOME.CodexBlocks.action.secondary": { + "message": "Explore Cloud Function" + }, + "HOME.CodexBlocks.terminal": { + "message": "Run in Codex" + }, + "HOME.CodexBlocks.video": { + "message": "Video demo" + }, + "HOME.CodexBlocks.card1.eyebrow": { + "message": "Comic" + }, + "HOME.CodexBlocks.card1.title": { + "message": "Comic Translation and Redraw" + }, + "HOME.CodexBlocks.card1.description": { + "message": "Call a block from Codex to translate a full comic page, clean text, reflow layout, and return a readable result for serialized pages or promo art." + }, + "HOME.CodexBlocks.card1.previewTitle": { + "message": "Comic Translation Demo" + }, + "HOME.CodexBlocks.card1.previewNote": { + "message": "This area will be replaced with video to show the full path from a Codex call to the translated output." + }, + "HOME.CodexBlocks.card2.eyebrow": { + "message": "Paper Figure" + }, + "HOME.CodexBlocks.card2.title": { + "message": "PaperBanana Illustrations" + }, + "HOME.CodexBlocks.card2.description": { + "message": "Generate paper-style figures from method descriptions, notes, or rough sketches for papers, slides, and technical writing." + }, + "HOME.CodexBlocks.card2.previewTitle": { + "message": "PaperBanana Demo" + }, + "HOME.CodexBlocks.card2.previewNote": { + "message": "This area will be replaced with video to show the full path from method description to generated paper figure." + }, + "HOME.CodexBlocks.card3.eyebrow": { + "message": "Books" + }, + "HOME.CodexBlocks.card3.title": { + "message": "PDF / EPUB Translation" + }, + "HOME.CodexBlocks.card3.description": { + "message": "Translate long-form documents into bilingual EPUB or Markdown outputs that stay usable for reading instead of returning only raw text." + }, "CLOUD.hero.title": { "message": "OOMOL Cloud" }, "CLOUD.hero.description": { "message": "Turn the function you already validated locally into a service, without rebuilding backend scaffolding, deployment flow, and operations from scratch." }, + "CLOUD.hero.kicker": { + "message": "Cloud Function" + }, "CLOUD.hero.stat1": { "message": "Direct Publish" }, @@ -2745,6 +2808,9 @@ "CLOUD.hero.cta.docs": { "message": "Learn More" }, + "CLOUD.hero.cta.console": { + "message": "Open Cloud Console" + }, "CLOUD.painPoints.title": { "message": "Delivery Shouldn't Be Torture" }, @@ -2760,6 +2826,9 @@ "CLOUD.solution.subtitle": { "message": "The same capability can be delivered as an API, an MCP tool, or an automation task." }, + "CLOUD.solution.kicker": { + "message": "Delivery Paths" + }, "CLOUD.modes.library.title": { "message": "Publish as Automation" }, @@ -2784,9 +2853,18 @@ "CLOUD.pricing.description": { "message": "No expensive server fees, no complex prepaid plans. We charge by call count. Save money, save effort, and focus on the joy of programming." }, + "CLOUD.pricing.kicker": { + "message": "Pricing" + }, "CLOUD.pricing.cta": { "message": "View Pricing" }, + "CLOUD.cta.primary": { + "message": "Start in Studio" + }, + "CLOUD.cta.secondary": { + "message": "Open Cloud Console" + }, "CLOUD.opensource.title": { "message": "Open Source Infrastructure" }, @@ -2895,6 +2973,36 @@ "STUDIO.manifesto.subtitle": { "message": "A real coding environment where AI helps generate functions, validate them locally, and deliver them as APIs, MCP tools, or automation tasks." }, + "STUDIO.manifesto.cta.download": { + "message": "Download OOMOL Studio" + }, + "STUDIO.product.hero.kicker": { + "message": "OOMOL Studio" + }, + "STUDIO.product.hero.secondary": { + "message": "View Downloads" + }, + "STUDIO.product.story.kicker": { + "message": "Real developer environment" + }, + "STUDIO.product.story.title": { + "message": "Not another platform that asks developers to adapt" + }, + "STUDIO.product.principles.kicker": { + "message": "Core principles" + }, + "STUDIO.product.principles.title": { + "message": "Why Studio works better for building blocks" + }, + "STUDIO.product.cta.title": { + "message": "Start with your next block" + }, + "STUDIO.product.cta.description": { + "message": "Write, debug, and validate your own blocks in a real coding environment. When you are ready to deliver, carry them forward through Cloud." + }, + "STUDIO.product.cta.secondary": { + "message": "Explore Cloud" + }, "STUDIO.story.paragraph1": { "message": "What we want is not another tool that asks developers to adapt to the platform, but a working environment where you can actually write functions, orchestrate nodes, debug dependencies, and validate results." }, @@ -2913,6 +3021,45 @@ "STUDIO.story.paragraph3": { "message": "So Studio has a clear role: not to replace engineering workflow, but to bring function generation, local validation, and delivery back inside it." }, + "HOME.StudioChain.title": { + "message": "From blocks to deployment to delivery" + }, + "HOME.StudioChain.subtitle": { + "message": "When ready-made capabilities are not enough, OOMOL lets you keep moving: build blocks in Studio, deploy through Cloud, and deliver the capability with one continuous path." + }, + "HOME.StudioChain.lead": { + "message": "Do not just connect capabilities. Build them and deliver them." + }, + "HOME.StudioChain.summary": { + "message": "In OOMOL, you can start with ready-made capabilities, create your own blocks in Studio, then deploy and deliver them privately to yourself, your team, or your customers." + }, + "HOME.StudioChain.card1.title": { + "message": "OOMOL Studio" + }, + "HOME.StudioChain.card1.description": { + "message": "Write, debug, and validate your own blocks in a familiar environment for code, dependencies, and inputs." + }, + "HOME.StudioChain.card2.title": { + "message": "Cloud" + }, + "HOME.StudioChain.card2.description": { + "message": "Deploy validated blocks as cloud functions and keep providing them reliably without exposing your source code." + }, + "HOME.StudioChain.action.studio": { + "message": "Explore Studio" + }, + "HOME.StudioChain.action.cloud": { + "message": "Explore Cloud" + }, + "Theme.Navbar.product.studio.description": { + "message": "Build, debug, and validate your blocks" + }, + "Theme.Navbar.product.cloud.description": { + "message": "Deploy and deliver capabilities privately" + }, + "Theme.Navbar.product.label": { + "message": "Product" + }, "STUDIO.principle1.title": { "message": "1. Nodes Are Functions. Flows Are Composition." }, diff --git a/i18n/zh-CN/code.json b/i18n/zh-CN/code.json index 5353670d..d53207e3 100644 --- a/i18n/zh-CN/code.json +++ b/i18n/zh-CN/code.json @@ -27,16 +27,16 @@ "message": "社区" }, "HOME.page.title": { - "message": "OOMOL - 用 Studio 写函数,让 AI 直接调用" + "message": "OOMOL - 为 agent 构建并交付你的能力" }, "HOME.FirstScreen.slogan": { - "message": "写好函数,直接交付" + "message": "为 agent 构建并交付你的能力" }, "HOME.FirstScreen.kicker": { - "message": "给开发者的 Studio + CLI 函数工作流" + "message": "给开发者的能力生产与交付链路" }, "HOME.FirstScreen.script": { - "message": "用 OOMOL Studio 的 AI Agent 写好业务函数,发布到 Cloud 后,再通过 oo-cli 在 Codex 或 Claude Code 中直接调用这些能力。" + "message": "先通过 oo-cli 使用现成能力,再在 OOMOL Studio 中编写自己的 block,最后通过 Cloud 私有部署并交付出去。" }, "HOME.FirstScreen.pill1": { "message": "不学新 DSL" @@ -958,10 +958,10 @@ "message": "//#region generated meta\ntype Inputs = {\n};\ntype Outputs = {\n};\n//#endregion\n\nimport type { Context } from \"@oomol/types/oocana\";\n\nexport default async function(\n params: Inputs,\n context: Context\n): Promise | undefined | void> {\n // 融合 API 基础地址\n const api_url = \"https://fusion-api.oomol.com/v1/fal-nano-banana-edit/submit\"\n\n // 大模型基础地址,可使用 openai sdk\n const llm_base_url = \"https://llm.oomol.com/v1\"\n\n // 从 context 获取 OOMOL token(无需手动输入 API key)\n const api_token = await context.getOomolToken()\n // return { output: \"output_value\" };\n};" }, "HOME.GetStartedPrompt.title": { - "message": "从下一个函数开始,让 AI 直接调用" + "message": "先把第一条链路跑通" }, "HOME.GetStartedPrompt.subtitle": { - "message": "下载 OOMOL Studio,用 AI Agent 写好业务函数并发布到 Cloud,再通过 oo-cli 在 Codex 或 Claude Code 中直接调用。" + "message": "先下载 oo-cli,使用已经发布好的能力。需要时,再用 OOMOL Studio 写自己的 block,并通过 Cloud 部署出去。" }, "HOME.Pricing.title": { "message": "价格" @@ -2554,10 +2554,10 @@ "message": "容器化部署到私有云或 K8s 集群,支持 CI/CD 流水线,实现企业级 API 服务的持续交付和运维。" }, "HOME.ProductComparison.title": { - "message": "Cloud 负责把函数稳定跑在线上" + "message": "不是为了上云,而是为了交付" }, "HOME.ProductComparison.subtitle": { - "message": "如果 Studio 负责把函数写出来,那么 OOMOL Cloud 就是统一的运行和交付层。CLI 登录之后,Codex / Claude Code 实际调用的也是这里部署的云函数。" + "message": "Cloud 的意义,不只是把代码放到云上,而是让已经验证过的 block 可以持续提供给自己、团队或客户使用。" }, "HOME.ChatAgent.title": { "message": "OOMOL Chat & Agent 生态" @@ -2602,43 +2602,43 @@ "message": "本地安装即用,内置容器环境,适合把开发和验证先收拢在一处。" }, "HOME.ProductComparison.cloud.stage": { - "message": "更快上线,更少运维" + "message": "部署并交付" }, "HOME.ProductComparison.cloud.capability": { - "message": "把已经跑通的函数托管成统一的线上能力,作为 CLI、API 和自动化任务共用的运行层,不必再重搭接口、运行时和扩缩容。" + "message": "把已经验证过的 block 部署为云函数,稳定提供给自己、团队或客户使用,不必再围着同一份能力重做一层服务。" }, "HOME.ProductComparison.cloud.scenario": { - "message": "适合希望把函数稳定提供给 AI、应用或自动化任务的开发者和小团队。" + "message": "适合给自己扩展 CLI 能力、给团队提供统一能力,或给客户提供 skill 与 CLI 服务的开发者和小团队。" }, "HOME.ProductComparison.cloud.tech": { - "message": "沿用 Studio 中已经跑通的实现,由 OOMOL Cloud 承接运行、鉴权和对外交付,CLI 登录后调用的也是这里的云函数。" + "message": "沿用 Studio 中已经跑通的实现,由 OOMOL Cloud 承接运行和对外交付;如果需要,同一份能力也可以继续通过 API 或 MCP 接出去。" }, "HOME.ProductComparison.cta": { - "message": "查看 OOMOL Cloud" + "message": "查看 Cloud Function" }, "HOME.ProductComparison.outputIntro": { - "message": "云端交付" + "message": "同一份能力,按需继续扩展" }, "HOME.ProductComparison.outputSummary": { - "message": "同一份已经验证过的函数实现,可以继续交付为 API、MCP 工具或自动化任务,作为 AI 和应用都能稳定调用的统一能力层。" + "message": "同一份已经验证过的 block,可以继续通过不同方式被消费和集成。" }, "HOME.ProductComparison.output1.title": { - "message": "API 服务" + "message": "CLI 使用" }, "HOME.ProductComparison.output1.description": { - "message": "把函数直接交付成可调用的接口,不必单独搭服务框架和运行层。" + "message": "通过 oo-cli 直接搜索、查看和运行已经部署好的能力。" }, "HOME.ProductComparison.output2.title": { - "message": "MCP 工具" + "message": "API 接入" }, "HOME.ProductComparison.output2.description": { - "message": "让同一份实现直接进入 Agent 和 AI 应用的调用链,而不是另外维护一套工具服务。" + "message": "把同一份能力继续接进自己的应用、服务或自动化代码。" }, "HOME.ProductComparison.output3.title": { - "message": "自动化任务" + "message": "MCP 接入" }, "HOME.ProductComparison.output3.description": { - "message": "把同一份实现继续交付为定时任务或自动化流程,让线上运行和后续迭代复用同一份能力。" + "message": "在需要时,把同一份能力继续接入其他 agent 和工具系统。" }, "HOME.ProductComparison.benefit1.label": { "message": "交付负担" @@ -2716,13 +2716,13 @@ "message": "查看 Cloud 交付" }, "HOME.CliEntry.badge": { - "message": "CLI QUICKSTART" + "message": "CLI FIRST" }, "HOME.CliEntry.title": { - "message": "安装 oo-cli,登录后开始调用已发布函数。" + "message": "先用,再决定要不要自己做" }, "HOME.CliEntry.subtitle": { - "message": "先装上 CLI,再把第一次搜索和运行跑通。" + "message": "oo-cli 是 OOMOL 最快的使用入口。你可以先搜索、查看、运行已经发布好的能力,在终端里直接开始使用。" }, "HOME.CliEntry.bridge": { "message": "函数先发布到 OOMOL Cloud,CLI 再负责登录、搜索和调用。这层关系说一遍就够,重点是让你第一次跑通。" @@ -2731,31 +2731,31 @@ "message": "安装 oo-cli" }, "HOME.CliEntry.step1.description": { - "message": "先装好命令行入口。" + "message": "先把使用入口装好。" }, "HOME.CliEntry.step2.title": { "message": "登录账号" }, "HOME.CliEntry.step2.description": { - "message": "执行 oo login。" + "message": "登录后开始搜索和运行已发布能力。" }, "HOME.CliEntry.step3.title": { - "message": "搜索并运行已发布函数" + "message": "搜索并运行能力" }, "HOME.CliEntry.step3.description": { - "message": "先搜,再跑。" + "message": "先看清楚能力做什么、需要什么输入,再直接运行。" }, "HOME.CliEntry.action.primary": { - "message": "查看 CLI 快速开始" + "message": "查看 oo-cli" }, "HOME.CliEntry.action.secondary": { - "message": "查看如何发布到 Cloud" + "message": "查看 Cloud Function" }, "HOME.CliEntry.setup.eyebrow": { "message": "INSTALL ONCE" }, "HOME.CliEntry.setup.title": { - "message": "两条命令,先把 CLI 装好并登录" + "message": "两条命令,先把 oo-cli 装好并登录" }, "HOME.CliEntry.setup.pill": { "message": "30 秒" @@ -2767,7 +2767,7 @@ "message": "FIRST RUN DEMO" }, "HOME.CliEntry.demo.title": { - "message": "把第一次使用压缩成搜索、检查、运行三段" + "message": "把第一次使用压缩成搜索、查看、运行三步" }, "HOME.CliEntry.demo.badge": { "message": "Usage Flow" @@ -2797,7 +2797,7 @@ "message": "Run" }, "HOME.CliEntry.demo.stage3.title": { - "message": "运行并取回结果" + "message": "运行并获取结果" }, "HOME.CliEntry.demo.stage3.description": { "message": "函数交给 Cloud 执行,CLI 负责把任务发出去,并在当前工作流里把结果取回来。" @@ -2811,12 +2811,75 @@ "HOME.CliEntry.terminal.note": { "message": "CLI 不只是另一个入口。它是在登录之后,把部署在 OOMOL Cloud 上的云函数稳定接到 Codex、Claude Code 和其他终端工作流里的那一层。" }, + "HOME.CodexBlocks.badge": { + "message": "CODEX EXAMPLES" + }, + "HOME.CodexBlocks.title": { + "message": "在 Codex 里先调用这些代表性 block" + }, + "HOME.CodexBlocks.subtitle": { + "message": "这里不再展示旧案例说明,而是直接展示几类更能代表 OOMOL 能力边界的 block。先在 Codex 里搜、看、跑,再决定要不要继续扩展自己的能力。" + }, + "HOME.CodexBlocks.action.primary": { + "message": "查看 oo-cli" + }, + "HOME.CodexBlocks.action.secondary": { + "message": "查看 Cloud Function" + }, + "HOME.CodexBlocks.terminal": { + "message": "在 Codex 中调用" + }, + "HOME.CodexBlocks.video": { + "message": "视频演示" + }, + "HOME.CodexBlocks.card1.eyebrow": { + "message": "Comic" + }, + "HOME.CodexBlocks.card1.title": { + "message": "漫画翻译与重绘" + }, + "HOME.CodexBlocks.card1.description": { + "message": "在 Codex 里直接调用 block,把整页漫画翻译、擦字、重排并输出可读版本。适合翻译连载页、宣传图和嵌字内容。" + }, + "HOME.CodexBlocks.card1.previewTitle": { + "message": "漫画翻译 Demo" + }, + "HOME.CodexBlocks.card1.previewNote": { + "message": "这里会替换成视频,用来展示从 Codex 发起调用到返回翻译结果的完整过程。" + }, + "HOME.CodexBlocks.card2.eyebrow": { + "message": "Paper Figure" + }, + "HOME.CodexBlocks.card2.title": { + "message": "PaperBanana 论文插图" + }, + "HOME.CodexBlocks.card2.description": { + "message": "根据论文段落、方法说明或草图生成统一风格的论文配图,用于 paper、slides 和技术博客。" + }, + "HOME.CodexBlocks.card2.previewTitle": { + "message": "PaperBanana Demo" + }, + "HOME.CodexBlocks.card2.previewNote": { + "message": "这里会替换成视频,用来展示从方法描述到论文插图生成的完整调用过程。" + }, + "HOME.CodexBlocks.card3.eyebrow": { + "message": "Books" + }, + "HOME.CodexBlocks.card3.title": { + "message": "PDF / EPUB 翻译" + }, + "HOME.CodexBlocks.card3.description": { + "message": "把长文档翻译成可继续阅读的双语 EPUB 或 Markdown 输出,而不是只拿回一段文本结果。" + }, "CLOUD.hero.title": { "message": "OOMOL Cloud" }, "CLOUD.hero.description": { "message": "把已经在本地跑通的函数直接交付成服务,不必再重搭后端、部署框架和运维流程。" }, + "CLOUD.hero.kicker": { + "message": "Cloud Function" + }, "CLOUD.hero.stat1": { "message": "直接发布" }, @@ -2832,6 +2895,9 @@ "CLOUD.hero.cta.docs": { "message": "了解更多" }, + "CLOUD.hero.cta.console": { + "message": "打开 Cloud 控制台" + }, "CLOUD.painPoints.title": { "message": "交付代码不该是折磨" }, @@ -2847,6 +2913,9 @@ "CLOUD.solution.subtitle": { "message": "写好的函数能力,可以继续交付为 API、MCP 工具或自动化任务。" }, + "CLOUD.solution.kicker": { + "message": "交付方式" + }, "CLOUD.modes.library.title": { "message": "发布成自动化任务" }, @@ -2871,9 +2940,18 @@ "CLOUD.pricing.description": { "message": "没有昂贵的服务器租用费,没有复杂的预付费套餐。我们按调用次数收取费用,真正做到省钱省力,让你专注于享受编程的乐趣。" }, + "CLOUD.pricing.kicker": { + "message": "价格" + }, "CLOUD.pricing.cta": { "message": "查看详细价格" }, + "CLOUD.cta.primary": { + "message": "在 Studio 中开始" + }, + "CLOUD.cta.secondary": { + "message": "打开 Cloud 控制台" + }, "CLOUD.opensource.title": { "message": "开源基础设施" }, @@ -2979,6 +3057,33 @@ "STUDIO.manifesto.cta.download": { "message": "下载 OOMOL Studio" }, + "STUDIO.product.hero.kicker": { + "message": "OOMOL Studio" + }, + "STUDIO.product.hero.secondary": { + "message": "查看下载" + }, + "STUDIO.product.story.kicker": { + "message": "真实开发环境" + }, + "STUDIO.product.story.title": { + "message": "不是另一个要求开发者迁就的平台" + }, + "STUDIO.product.principles.kicker": { + "message": "核心原则" + }, + "STUDIO.product.principles.title": { + "message": "Studio 为什么更适合生产 block" + }, + "STUDIO.product.cta.title": { + "message": "从下一个 block 开始" + }, + "STUDIO.product.cta.description": { + "message": "在真实 coding 环境里写、调试和验证自己的 block。需要交付时,再继续通过 Cloud 部署出去。" + }, + "STUDIO.product.cta.secondary": { + "message": "查看 Cloud" + }, "STUDIO.story.paragraph1": { "message": "我们想要的,不是另一个要求开发者迁就平台的工具,而是一个能真正写函数、编排节点、调试依赖、验证结果的工作环境。" }, @@ -2997,6 +3102,45 @@ "STUDIO.story.paragraph3": { "message": "所以 Studio 的角色很明确:它不是为了替代工程环境,而是把函数生成、本地验证和后续交付重新放回工程环境里。" }, + "HOME.StudioChain.title": { + "message": "从 block,到部署,再到交付" + }, + "HOME.StudioChain.subtitle": { + "message": "当现成能力不够时,OOMOL 让你继续往下走: 在 OOMOL Studio 里生产 block,在 Cloud 里部署,并把能力稳定交付出去。" + }, + "HOME.StudioChain.lead": { + "message": "不只是连接能力,更是把能力做出来并交付出去。" + }, + "HOME.StudioChain.summary": { + "message": "在 OOMOL 里,你可以先使用现成能力,再在 Studio 里编写和验证自己的 block,最后通过 Cloud 私有部署并交付给自己、团队或客户使用。" + }, + "HOME.StudioChain.card1.title": { + "message": "OOMOL Studio" + }, + "HOME.StudioChain.card1.description": { + "message": "在 Studio 里编写、调试和验证自己的 block,用熟悉的方式组织代码、依赖和输入输出。" + }, + "HOME.StudioChain.card2.title": { + "message": "Cloud" + }, + "HOME.StudioChain.card2.description": { + "message": "把已经验证过的 block 部署为云函数,稳定提供给自己、团队或客户使用。" + }, + "HOME.StudioChain.action.studio": { + "message": "了解 Studio" + }, + "HOME.StudioChain.action.cloud": { + "message": "了解 Cloud" + }, + "Theme.Navbar.product.studio.description": { + "message": "编写、调试并验证你的 block" + }, + "Theme.Navbar.product.cloud.description": { + "message": "部署并私有交付你的能力" + }, + "Theme.Navbar.product.label": { + "message": "产品" + }, "STUDIO.principle1.title": { "message": "1. 节点即函数,编排即组合" }, diff --git a/src/components/HomepageCliEntry/index.tsx b/src/components/HomepageCliEntry/index.tsx index a65e067e..f0b664e3 100644 --- a/src/components/HomepageCliEntry/index.tsx +++ b/src/components/HomepageCliEntry/index.tsx @@ -86,16 +86,10 @@ export default function HomepageCliEntry() {
- + {translate({ message: "HOME.CliEntry.action.primary" })} - + {translate({ message: "HOME.CliEntry.action.secondary" })}
diff --git a/src/components/HomepageCodexBlocks/index.tsx b/src/components/HomepageCodexBlocks/index.tsx new file mode 100644 index 00000000..e0aaf7f9 --- /dev/null +++ b/src/components/HomepageCodexBlocks/index.tsx @@ -0,0 +1,98 @@ +import styles from "./styles.module.scss"; + +import Link from "@docusaurus/Link"; +import { translate } from "@docusaurus/Translate"; +import React from "react"; + +const showcaseItems = [ + { + icon: "i-lucide-panels-top-left", + eyebrow: translate({ message: "HOME.CodexBlocks.card1.eyebrow" }), + title: translate({ message: "HOME.CodexBlocks.card1.title" }), + description: translate({ message: "HOME.CodexBlocks.card1.description" }), + previewTitle: translate({ message: "HOME.CodexBlocks.card1.previewTitle" }), + previewNote: translate({ message: "HOME.CodexBlocks.card1.previewNote" }), + }, + { + icon: "i-lucide-orbit", + eyebrow: translate({ message: "HOME.CodexBlocks.card2.eyebrow" }), + title: translate({ message: "HOME.CodexBlocks.card2.title" }), + description: translate({ message: "HOME.CodexBlocks.card2.description" }), + previewTitle: translate({ message: "HOME.CodexBlocks.card2.previewTitle" }), + previewNote: translate({ message: "HOME.CodexBlocks.card2.previewNote" }), + }, +]; + +export default function HomepageCodexBlocks() { + return ( +
+
+
+
+ {translate({ message: "HOME.CodexBlocks.badge" })} +
+

+ {translate({ message: "HOME.CodexBlocks.title" })} +

+

+ {translate({ message: "HOME.CodexBlocks.subtitle" })} +

+
+ + {translate({ message: "HOME.CodexBlocks.action.primary" })} + + + {translate({ message: "HOME.CodexBlocks.action.secondary" })} + +
+
+ +
+ {showcaseItems.map(item => ( +
+
+ +
{item.eyebrow}
+
+ +

{item.title}

+

{item.description}

+ +
+
+
+ +
+ {translate({ message: "HOME.CodexBlocks.video" })} +
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+
{item.previewTitle}
+

{item.previewNote}

+
+
+
+ ))} +
+
+
+ ); +} diff --git a/src/components/HomepageCodexBlocks/styles.module.scss b/src/components/HomepageCodexBlocks/styles.module.scss new file mode 100644 index 00000000..fc026338 --- /dev/null +++ b/src/components/HomepageCodexBlocks/styles.module.scss @@ -0,0 +1,361 @@ +.section { + padding: clamp(4rem, 8vw, 6rem) 0 clamp(2.5rem, 5vw, 4rem); + background: + radial-gradient( + circle at 85% 20%, + rgba(124, 132, 225, 0.08) 0%, + rgba(124, 132, 225, 0) 26% + ), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-layout) 90%, white 10%) 0%, + color-mix(in srgb, var(--oomol-bg-base) 96%, white 4%) 100% + ); +} + +.container { + max-width: 1280px; + margin: 0 auto; + padding: 0 24px; + display: grid; + gap: 1.6rem; +} + +.header { + display: grid; + gap: 0.9rem; + max-width: 52rem; +} + +.badge { + display: inline-flex; + width: fit-content; + align-items: center; + gap: 0.65rem; + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--oomol-text-secondary); + + &::before { + content: ""; + width: 0.8rem; + height: 1px; + background: var(--oomol-primary); + } +} + +.title { + margin: 0; + max-width: 12ch; + font-family: var(--oomol-font-display); + font-size: clamp(2.55rem, 4.8vw, 4.2rem); + line-height: 0.98; + letter-spacing: -0.045em; + color: var(--oomol-text-primary); +} + +.subtitle { + margin: 0; + max-width: 48rem; + font-size: 1rem; + line-height: 1.72; + color: var(--oomol-text-secondary); +} + +.headerActions { + display: flex; + flex-wrap: wrap; + gap: 0.85rem; + padding-top: 0.25rem; +} + +.primaryAction, +.secondaryAction { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.85rem; + padding: 0 1rem; + border-radius: 999px; + text-decoration: none; + font-size: 0.96rem; + font-weight: 650; + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; + + &:hover { + text-decoration: none; + transform: translateY(-1px); + } +} + +.primaryAction { + color: var(--oomol-white); + border: 1px solid color-mix(in srgb, var(--oomol-primary-active) 64%, black 12%); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-primary) 78%, white 14%) 0%, + color-mix(in srgb, var(--oomol-primary-active) 88%, black 12%) 100% + ); +} + +.secondaryAction { + color: var(--oomol-text-primary); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); + border: 1px solid var(--oomol-divider); +} + +.grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem; +} + +.card { + display: grid; + align-content: start; + gap: 0.9rem; + min-height: 100%; + padding: 1.15rem; + border-radius: 1.45rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 93%, white 7%); + box-shadow: var(--oomol-shadow-sm); +} + +.cardTop { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.iconWrap { + width: 2.6rem; + height: 2.6rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 0.95rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-layout) 90%, white 10%); + color: var(--oomol-primary); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.6), + 0 8px 16px rgba(77, 88, 124, 0.08); + + i { + font-size: 1.15rem; + } +} + +.cardEyebrow { + font-size: 0.74rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-text-secondary); +} + +.cardTitle { + margin: 0; + font-size: 1.38rem; + line-height: 1.18; + color: var(--oomol-text-primary); +} + +.cardDescription { + margin: 0; + font-size: 0.96rem; + line-height: 1.7; + color: var(--oomol-text-secondary); +} + +.videoBlock { + display: grid; + gap: 0.9rem; +} + +.videoFrame { + position: relative; + overflow: hidden; + aspect-ratio: 16 / 9; + border-radius: 1.25rem; + border: 1px solid rgba(52, 59, 84, 0.16); + background: linear-gradient(180deg, #252b3b 0%, #1c2230 100%); + box-shadow: + 0 24px 60px rgba(24, 29, 44, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.05); +} + +.videoChrome { + display: flex; + align-items: center; + gap: 0.4rem; + min-height: 2.25rem; + padding: 0 0.9rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); +} + +.videoDot { + width: 0.42rem; + height: 0.42rem; + border-radius: 999px; + background: rgba(222, 228, 245, 0.38); +} + +.videoCanvas { + position: absolute; + inset: 2.25rem 0 0; + display: grid; + place-items: center; + padding: 1rem; +} + +.videoGradient { + position: absolute; + inset: 0; + background: + radial-gradient( + circle at 20% 18%, + rgba(137, 162, 255, 0.18) 0%, + rgba(137, 162, 255, 0) 30% + ), + radial-gradient( + circle at 80% 78%, + rgba(123, 213, 184, 0.16) 0%, + rgba(123, 213, 184, 0) 28% + ), + linear-gradient(180deg, rgba(39, 45, 63, 0.92) 0%, rgba(28, 34, 48, 0.98) 100%); +} + +.videoTracks { + position: relative; + z-index: 1; + width: 100%; + display: grid; + gap: 0.8rem; + + span { + display: block; + height: 0.85rem; + border-radius: 999px; + background: linear-gradient( + 90deg, + rgba(246, 248, 255, 0.92) 0%, + rgba(246, 248, 255, 0.58) 100% + ); + + &:nth-child(2) { + width: 78%; + } + + &:nth-child(3) { + width: 56%; + } + } +} + +.videoOverlay { + position: absolute; + inset: 0; + z-index: 2; + display: grid; + place-items: center; + gap: 0.7rem; + align-content: center; +} + +.playButton { + width: 3.35rem; + height: 3.35rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + background: rgba(255, 255, 255, 0.14); + border: 1px solid rgba(255, 255, 255, 0.16); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.22), + 0 12px 28px rgba(8, 12, 22, 0.2); + backdrop-filter: blur(8px); + + i { + font-size: 1.2rem; + color: rgba(245, 248, 255, 0.96); + transform: translateX(1px); + } +} + +.videoLabel { + padding: 0.38rem 0.7rem; + border-radius: 999px; + background: rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.12); + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: rgba(224, 230, 242, 0.76); +} + +.videoMeta { + display: grid; + gap: 0.35rem; +} + +.videoMetaTitle { + font-size: 0.82rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-text-secondary); +} + +.videoMetaNote { + margin: 0; + font-size: 0.92rem; + line-height: 1.58; + color: var(--oomol-text-secondary); +} + +:global(html[lang="en"]) .title { + max-width: 18ch; + font-size: clamp(2.2rem, 4vw, 3.6rem); + line-height: 1.03; +} + +@media (max-width: 996px) { + .grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 768px) { + .section { + padding: 3rem 0 2.4rem; + } + + .container { + padding: 0 20px; + } + + .title { + max-width: 100%; + font-size: clamp(2.15rem, 9.4vw, 3rem); + line-height: 1.08; + letter-spacing: -0.03em; + text-wrap: pretty; + } + + .subtitle, + .cardDescription, + .videoMetaNote { + font-size: 0.93rem; + line-height: 1.58; + } +} diff --git a/src/components/HomepageProductComparison/index.tsx b/src/components/HomepageProductComparison/index.tsx index 58d6f909..434de1ba 100644 --- a/src/components/HomepageProductComparison/index.tsx +++ b/src/components/HomepageProductComparison/index.tsx @@ -87,10 +87,7 @@ export default function HomepageProductComparison() { })}

- + {translate({ message: "HOME.ProductComparison.cta" })}
diff --git a/src/components/StudioDetailContent/index.tsx b/src/components/StudioDetailContent/index.tsx index 5465febb..2304c431 100644 --- a/src/components/StudioDetailContent/index.tsx +++ b/src/components/StudioDetailContent/index.tsx @@ -1,12 +1,10 @@ import styles from "./styles.module.scss"; -import type { DocusaurusContext } from "@docusaurus/types"; - +import Link from "@docusaurus/Link"; import { translate } from "@docusaurus/Translate"; import useBaseUrl from "@docusaurus/useBaseUrl"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import ThemedImage from "@theme/ThemedImage"; -import React, { useState } from "react"; +import React from "react"; type StudioDetailContentProps = { variant?: "page" | "home"; @@ -57,13 +55,6 @@ const principles = [ export default function StudioDetailContent({ variant = "page", }: StudioDetailContentProps) { - const { i18n } = useDocusaurusContext() as unknown as DocusaurusContext & { - i18n: { currentLocale: string }; - }; - const isZh = i18n.currentLocale === "zh-CN"; - const [expandedPrinciple, setExpandedPrinciple] = useState( - null - ); const studioPreviewLight = useBaseUrl("/img/pages/studio/studio-light.png"); const studioPreviewDark = useBaseUrl("/img/pages/studio/studio-dark.png"); const principle1Light = useBaseUrl("/img/pages/studio/code-light.png"); @@ -78,41 +69,62 @@ export default function StudioDetailContent({ { light: principle2Light, dark: principle2Dark }, { light: principle3Light, dark: principle3Dark }, ]; + const publishPreviewLight = useBaseUrl("/img/pages/home/publish-light.png"); + const publishPreviewDark = useBaseUrl("/img/pages/home/publish-dark.png"); if (variant === "home") { + const homeCards = [ + { + title: translate({ message: "HOME.StudioChain.card1.title" }), + description: translate({ + message: "HOME.StudioChain.card1.description", + }), + image: { + light: principle1Light, + dark: principle1Dark, + }, + alt: "Build blocks in OOMOL Studio", + }, + { + title: translate({ message: "HOME.StudioChain.card2.title" }), + description: translate({ + message: "HOME.StudioChain.card2.description", + }), + image: { + light: publishPreviewLight, + dark: publishPreviewDark, + }, + alt: "Deploy blocks with OOMOL Cloud", + }, + ]; + return (

- {translate({ message: "STUDIO.manifesto.title" })} + {translate({ message: "HOME.StudioChain.title" })}

- {translate({ message: "STUDIO.manifesto.subtitle" })} + {translate({ message: "HOME.StudioChain.subtitle" })}

- {translate({ message: "STUDIO.story.paragraph1" })} + {translate({ message: "HOME.StudioChain.lead" })}

- -
-

- {translate({ message: "STUDIO.story.frustration.line1" })} -

-

- {translate({ message: "STUDIO.story.frustration.line2" })} -

-

- {translate({ message: "STUDIO.story.frustration.line3" })} -

-
-
-

{translate({ message: "STUDIO.story.paragraph2" })}

-

{translate({ message: "STUDIO.story.paragraph3" })}

+

{translate({ message: "HOME.StudioChain.summary" })}

+
+
+ + {translate({ message: "HOME.StudioChain.action.studio" })} + + + {translate({ message: "HOME.StudioChain.action.cloud" })} +
@@ -131,69 +143,21 @@ export default function StudioDetailContent({
- {principles.map((principle, index) => { - const [firstParagraph, ...extraParagraphs] = - principle.paragraphKeys; - const isExpanded = expandedPrinciple === index; - - return ( -
-
- -
-
-

- {translate({ - message: principle.titleKey, - })} -

-

- {translate({ - message: firstParagraph, - })} -

-
- {extraParagraphs.map(key => ( -

- {translate({ - message: key, - })} -

- ))} -
- -
-
- ); - })} + {homeCards.map(card => ( +
+
+ +
+
+

{card.title}

+

{card.description}

+
+
+ ))}
diff --git a/src/components/StudioDetailContent/styles.module.scss b/src/components/StudioDetailContent/styles.module.scss index 348a3b58..483ce838 100644 --- a/src/components/StudioDetailContent/styles.module.scss +++ b/src/components/StudioDetailContent/styles.module.scss @@ -87,6 +87,51 @@ gap: 0.9rem; } +.homeActions { + display: flex; + flex-wrap: wrap; + gap: 0.8rem; +} + +.homePrimaryAction, +.homeSecondaryAction { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.85rem; + padding: 0 1rem; + border-radius: 999px; + text-decoration: none; + font-size: 0.95rem; + font-weight: 650; + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; + + &:hover { + text-decoration: none; + transform: translateY(-1px); + } +} + +.homePrimaryAction { + color: var(--oomol-white); + border: 1px solid color-mix(in srgb, var(--oomol-primary-active) 64%, black 12%); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-primary) 78%, white 14%) 0%, + color-mix(in srgb, var(--oomol-primary-active) 88%, black 12%) 100% + ); +} + +.homeSecondaryAction { + color: var(--oomol-text-primary); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); + border: 1px solid var(--oomol-divider); +} + .homePreviewCard { min-width: 0; padding: 0.9rem; diff --git a/src/pages/cloud/index.tsx b/src/pages/cloud/index.tsx new file mode 100644 index 00000000..24c39118 --- /dev/null +++ b/src/pages/cloud/index.tsx @@ -0,0 +1,253 @@ +import styles from "./styles.module.scss"; + +import Head from "@docusaurus/Head"; +import Link from "@docusaurus/Link"; +import { translate } from "@docusaurus/Translate"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import ThemedImage from "@theme/ThemedImage"; +import React from "react"; + +import Layout from "../../theme/Layout"; + +const deliveryModes = [ + { + index: "01", + titleKey: "CLOUD.modes.serverless.title", + descriptionKey: "CLOUD.modes.serverless.description", + }, + { + index: "02", + titleKey: "CLOUD.modes.mcp.title", + descriptionKey: "CLOUD.modes.mcp.description", + }, + { + index: "03", + titleKey: "CLOUD.modes.library.title", + descriptionKey: "CLOUD.modes.library.description", + }, +]; + +const openSourceProjects = [ + { + titleKey: "CLOUD.opensource.ovm.title", + descriptionKey: "CLOUD.opensource.ovm.description", + }, + { + titleKey: "CLOUD.opensource.ovm-core.title", + descriptionKey: "CLOUD.opensource.ovm-core.description", + }, + { + titleKey: "CLOUD.opensource.ovm-win.title", + descriptionKey: "CLOUD.opensource.ovm-win.description", + }, + { + titleKey: "CLOUD.opensource.ovm-mac.title", + descriptionKey: "CLOUD.opensource.ovm-mac.description", + }, +]; + +export default function CloudPage() { + const publishLight = useBaseUrl("/img/pages/home/publish-light.png"); + const publishDark = useBaseUrl("/img/pages/home/publish-dark.png"); + const cloudConsoleUrl = "https://console.oomol.com/cloud-function"; + + return ( + + + {translate({ message: "CLOUD.hero.title" })} + + +
+
+
+
+
+ {translate({ message: "CLOUD.hero.kicker" })} +
+

+ {translate({ message: "CLOUD.hero.title" })} +

+

+ {translate({ message: "CLOUD.hero.description" })} +

+ +
+
+ + {translate({ message: "CLOUD.hero.stat1" })} + +
+
+ + {translate({ message: "CLOUD.hero.stat2" })} + +
+
+ + {translate({ message: "CLOUD.hero.stat3" })} + +
+
+ +
+ + {translate({ message: "CLOUD.hero.cta.start" })} + + + {translate({ message: "CLOUD.hero.cta.console" })} + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+ {translate({ message: "CLOUD.painPoints.subtitle" })} +
+

+ {translate({ message: "CLOUD.painPoints.title" })} +

+
+

+ {translate({ message: "CLOUD.painPoints.description" })} +

+
+
+ +
+
+
+
+ {translate({ message: "CLOUD.solution.kicker" })} +
+

+ {translate({ message: "CLOUD.solution.title" })} +

+

+ {translate({ message: "CLOUD.solution.subtitle" })} +

+
+ +
+ {deliveryModes.map(mode => ( +
+
{mode.index}
+

+ {translate({ message: mode.titleKey })} +

+

+ {translate({ message: mode.descriptionKey })} +

+
+ ))} +
+
+
+ +
+
+
+
+ {translate({ message: "CLOUD.pricing.kicker" })} +
+

+ {translate({ message: "CLOUD.pricing.title" })} +

+

+ {translate({ message: "CLOUD.pricing.description" })} +

+ + {translate({ message: "CLOUD.pricing.cta" })} + +
+
+
+ +
+
+
+
+ {translate({ message: "CLOUD.opensource.projects.title" })} +
+

+ {translate({ message: "CLOUD.opensource.title" })} +

+

+ {translate({ message: "CLOUD.opensource.subtitle" })} +

+
+

+ {translate({ message: "CLOUD.opensource.description" })} +

+ +
+ {openSourceProjects.map(project => ( +
+

+ {translate({ message: project.titleKey })} +

+

+ {translate({ message: project.descriptionKey })} +

+
+ ))} +
+
+
+ +
+
+
+

+ {translate({ message: "HOME.ProductComparison.title" })} +

+

+ {translate({ message: "HOME.ProductComparison.subtitle" })} +

+
+ + {translate({ message: "CLOUD.cta.primary" })} + + + {translate({ message: "CLOUD.cta.secondary" })} + +
+
+
+
+
+
+ ); +} diff --git a/src/pages/cloud/styles.module.scss b/src/pages/cloud/styles.module.scss new file mode 100644 index 00000000..99a585d6 --- /dev/null +++ b/src/pages/cloud/styles.module.scss @@ -0,0 +1,356 @@ +@use "../../css/custom.scss" as *; + +.page { + background: + radial-gradient( + circle at top left, + rgba(155, 174, 226, 0.12) 0%, + rgba(155, 174, 226, 0) 34% + ), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-layout) 92%, white 8%) 0%, + var(--oomol-bg-base) 100% + ); +} + +.hero { + padding: clamp(5rem, 9vw, 7.5rem) 0 clamp(3rem, 6vw, 4.5rem); +} + +.heroContainer, +.sectionContainer { + width: min(1280px, calc(100% - 48px)); + margin: 0 auto; +} + +.heroContainer { + display: grid; + grid-template-columns: minmax(0, 0.84fr) minmax(0, 1.16fr); + gap: clamp(1.6rem, 4vw, 3.5rem); + align-items: center; +} + +.heroCopy { + display: grid; + gap: 1.2rem; + max-width: 40rem; +} + +.kicker, +.sectionLabel { + display: inline-flex; + align-items: center; + gap: 0.7rem; + width: fit-content; + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--oomol-text-secondary); + + &::before { + content: ""; + width: 0.8rem; + height: 1px; + background: var(--oomol-primary); + } +} + +.heroTitle, +.sectionTitle, +.ctaTitle { + margin: 0; + font-family: var(--oomol-font-display); + letter-spacing: -0.045em; + color: var(--oomol-text-primary); +} + +.heroTitle { + max-width: 10ch; + font-size: clamp(3.1rem, 6vw, 5.35rem); + line-height: 0.95; +} + +.heroDescription, +.sectionSubtitle, +.sectionBody, +.ctaDescription { + margin: 0; + line-height: 1.72; + color: var(--oomol-text-secondary); +} + +.heroDescription { + max-width: 38rem; + font-size: 1.08rem; +} + +.stats { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; +} + +.stat { + display: inline-flex; + align-items: center; + min-height: 2.6rem; + padding: 0 0.95rem; + border-radius: 999px; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%); +} + +.statValue { + font-size: 0.94rem; + font-weight: 650; + color: var(--oomol-text-primary); +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 0.85rem; + padding-top: 0.3rem; +} + +.primaryAction, +.secondaryAction, +.inlineLink { + display: inline-flex; + align-items: center; + justify-content: center; + text-decoration: none; + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; + + &:hover { + text-decoration: none; + transform: translateY(-1px); + } +} + +.primaryAction, +.secondaryAction { + min-height: 2.95rem; + padding: 0 1rem; + border-radius: 999px; + font-size: 0.96rem; + font-weight: 650; +} + +.primaryAction { + color: var(--oomol-white); + border: 1px solid color-mix(in srgb, var(--oomol-primary-active) 64%, black 12%); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-primary) 78%, white 14%) 0%, + color-mix(in srgb, var(--oomol-primary-active) 88%, black 12%) 100% + ); +} + +.secondaryAction { + color: var(--oomol-text-primary); + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); +} + +.heroVisual { + min-width: 0; +} + +.visualFrame { + padding: 0.9rem; + border-radius: 1.9rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 95%, white 5%); + box-shadow: var(--oomol-shadow-lg); +} + +.visualImage { + display: block; + width: 100%; + height: auto; + border-radius: 1.2rem; + border: 1px solid var(--oomol-divider); +} + +.narrativeSection, +.deliverySection, +.pricingSection, +.openSourceSection, +.ctaSection { + padding: clamp(2.8rem, 6vw, 4.8rem) 0; +} + +.sectionHeader { + display: grid; + gap: 0.9rem; + margin-bottom: 1.4rem; +} + +.sectionTitle { + max-width: 12ch; + font-size: clamp(2.4rem, 4.8vw, 4rem); + line-height: 0.98; +} + +.sectionSubtitle { + max-width: 48rem; + font-size: 1rem; +} + +.sectionBody { + max-width: 52rem; + font-size: 1rem; +} + +.modeGrid, +.projectGrid { + display: grid; + gap: 1rem; +} + +.modeGrid { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.modeCard, +.projectCard, +.pricingCard, +.ctaCard { + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%); + box-shadow: var(--oomol-shadow-md); +} + +.modeCard, +.projectCard { + border-radius: 1.4rem; + padding: 1.2rem 1.15rem 1.3rem; +} + +.modeIndex { + font-family: var(--oomol-font-display); + font-size: 1.45rem; + line-height: 1; + letter-spacing: -0.06em; + color: color-mix(in srgb, var(--oomol-primary) 78%, var(--oomol-text-primary)); +} + +.modeTitle, +.projectTitle { + margin: 0.9rem 0 0.45rem; + font-size: 1.15rem; + line-height: 1.25; + color: var(--oomol-text-primary); +} + +.modeDescription, +.projectDescription { + margin: 0; + font-size: 0.95rem; + line-height: 1.68; + color: var(--oomol-text-secondary); +} + +.pricingCard, +.ctaCard { + padding: clamp(1.6rem, 3.5vw, 2.4rem); + border-radius: 1.8rem; +} + +.inlineLink { + margin-top: 1rem; + width: fit-content; + font-size: 0.95rem; + font-weight: 650; + color: var(--oomol-primary-text); +} + +.projectGrid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-top: 1.4rem; +} + +.ctaCard { + background: + radial-gradient( + circle at top left, + rgba(132, 138, 208, 0.2) 0%, + rgba(132, 138, 208, 0) 32% + ), + linear-gradient(180deg, #1a1b28 0%, #12131d 100%); + border-color: rgba(214, 221, 236, 0.12); +} + +.ctaTitle { + max-width: 11ch; + font-size: clamp(2.4rem, 4.6vw, 4rem); + line-height: 0.96; + color: rgba(243, 239, 248, 0.98); +} + +.ctaDescription { + max-width: 42rem; + padding-top: 0.9rem; + color: rgba(221, 214, 231, 0.8); +} + +.ctaCard .secondaryAction { + color: rgba(243, 239, 248, 0.94); + border-color: rgba(243, 239, 248, 0.14); + background: rgba(243, 239, 248, 0.08); +} + +:global(html[lang="en"]) .heroTitle { + max-width: 13ch; + font-size: clamp(2.8rem, 5.4vw, 4.8rem); + line-height: 0.98; +} + +:global(html[lang="en"]) .sectionTitle { + max-width: 16ch; + font-size: clamp(2.1rem, 4vw, 3.45rem); + line-height: 1.02; +} + +:global(html[lang="en"]) .ctaTitle { + max-width: 16ch; + font-size: clamp(2.2rem, 4vw, 3.55rem); + line-height: 1.03; +} + +@media (max-width: 996px) { + .heroContainer, + .modeGrid, + .projectGrid { + grid-template-columns: 1fr; + } + + .heroContainer { + gap: 1.5rem; + } +} + +@media (max-width: 768px) { + .heroContainer, + .sectionContainer { + width: min(100%, calc(100% - 40px)); + } + + .hero { + padding-top: 4rem; + } + + .heroTitle, + .sectionTitle, + .ctaTitle { + max-width: 100%; + text-wrap: pretty; + } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a152dd10..bdcadd1c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,12 +1,9 @@ import Head from "@docusaurus/Head"; import { translate } from "@docusaurus/Translate"; import HomepageCliEntry from "@site/src/components/HomepageCliEntry"; -import HomepageCommunityShare from "@site/src/components/HomepageCommunityShare"; -import HomepageDeliveryGap from "@site/src/components/HomepageDeliveryGap"; -import HomepageDeveloperBenefits from "@site/src/components/HomepageDeveloperBenefits"; +import HomepageCodexBlocks from "@site/src/components/HomepageCodexBlocks"; import HomepageFirstScreen from "@site/src/components/HomepageFirstScreen"; import HomepageProductComparison from "@site/src/components/HomepageProductComparison"; -import HomepageProofLayer from "@site/src/components/HomepageProofLayer"; import StudioDetailContent from "@site/src/components/StudioDetailContent"; import React from "react"; @@ -27,11 +24,8 @@ export default function Home() { - - - - + diff --git a/src/pages/studio/index.tsx b/src/pages/studio/index.tsx new file mode 100644 index 00000000..ae7a2841 --- /dev/null +++ b/src/pages/studio/index.tsx @@ -0,0 +1,220 @@ +import styles from "./styles.module.scss"; + +import Head from "@docusaurus/Head"; +import Link from "@docusaurus/Link"; +import { translate } from "@docusaurus/Translate"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import ThemedImage from "@theme/ThemedImage"; +import React from "react"; + +import { DownloadButton } from "../../components/DownloadButton"; +import Layout from "../../theme/Layout"; + +const principles = [ + { + titleKey: "STUDIO.principle1.title", + paragraphs: [ + "STUDIO.principle1.paragraph1", + "STUDIO.principle1.paragraph2", + "STUDIO.principle1.paragraph3", + ], + image: { + light: "/img/pages/studio/code-light.png", + dark: "/img/pages/studio/code-dark.png", + }, + alt: "Write blocks with code in OOMOL Studio", + }, + { + titleKey: "STUDIO.principle2.title", + paragraphs: [ + "STUDIO.principle2.paragraph1", + "STUDIO.principle2.paragraph2", + "STUDIO.principle2.paragraph3", + ], + image: { + light: "/img/pages/studio/edit-light.png", + dark: "/img/pages/studio/edit-dark.png", + }, + alt: "Developer experience in OOMOL Studio", + }, + { + titleKey: "STUDIO.principle3.title", + paragraphs: [ + "STUDIO.principle3.paragraph1", + "STUDIO.principle3.paragraph2", + "STUDIO.principle3.paragraph3", + ], + image: { + light: "/img/pages/studio/package-light.png", + dark: "/img/pages/studio/package-dark.png", + }, + alt: "Local and cloud continuity in OOMOL Studio", + }, +]; + +const frustrations = [ + "STUDIO.story.frustration.line1", + "STUDIO.story.frustration.line2", + "STUDIO.story.frustration.line3", +]; + +export default function StudioPage() { + const studioPreviewLight = useBaseUrl("/img/pages/studio/studio-light.png"); + const studioPreviewDark = useBaseUrl("/img/pages/studio/studio-dark.png"); + const principle1Light = useBaseUrl("/img/pages/studio/code-light.png"); + const principle1Dark = useBaseUrl("/img/pages/studio/code-dark.png"); + const principle2Light = useBaseUrl("/img/pages/studio/edit-light.png"); + const principle2Dark = useBaseUrl("/img/pages/studio/edit-dark.png"); + const principle3Light = useBaseUrl("/img/pages/studio/package-light.png"); + const principle3Dark = useBaseUrl("/img/pages/studio/package-dark.png"); + const principleImages = [ + { light: principle1Light, dark: principle1Dark }, + { light: principle2Light, dark: principle2Dark }, + { light: principle3Light, dark: principle3Dark }, + ]; + + return ( + + + {translate({ message: "STUDIO.page.title" })} + + +
+
+
+
+
+ {translate({ message: "STUDIO.product.hero.kicker" })} +
+

+ {translate({ message: "STUDIO.manifesto.title" })} +

+

+ {translate({ message: "STUDIO.manifesto.subtitle" })} +

+ +
+ + + {translate({ message: "STUDIO.product.hero.secondary" })} + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+ {translate({ message: "STUDIO.product.story.kicker" })} +
+

+ {translate({ message: "STUDIO.product.story.title" })} +

+
+ +
+
+

+ {translate({ message: "STUDIO.story.paragraph1" })} +

+

+ {translate({ message: "STUDIO.story.paragraph2" })} +

+

+ {translate({ message: "STUDIO.story.paragraph3" })} +

+
+ +
+ {frustrations.map(key => ( +
+ {translate({ message: key })} +
+ ))} +
+
+
+
+ +
+
+
+
+ {translate({ message: "STUDIO.product.principles.kicker" })} +
+

+ {translate({ message: "STUDIO.product.principles.title" })} +

+
+ +
+ {principles.map((principle, index) => ( +
+
+ +
+
+

+ {translate({ message: principle.titleKey })} +

+
+ {principle.paragraphs.map(key => ( +

+ {translate({ message: key })} +

+ ))} +
+
+
+ ))} +
+
+
+ +
+
+
+

+ {translate({ message: "STUDIO.product.cta.title" })} +

+

+ {translate({ message: "STUDIO.product.cta.description" })} +

+
+ + + {translate({ message: "STUDIO.product.cta.secondary" })} + +
+
+
+
+
+
+ ); +} diff --git a/src/pages/studio/styles.module.scss b/src/pages/studio/styles.module.scss new file mode 100644 index 00000000..bda92573 --- /dev/null +++ b/src/pages/studio/styles.module.scss @@ -0,0 +1,343 @@ +@use "../../css/custom.scss" as *; + +.page { + background: + radial-gradient( + circle at top left, + rgba(161, 191, 235, 0.14) 0%, + rgba(161, 191, 235, 0) 36% + ), + linear-gradient( + 180deg, + rgba(251, 253, 255, 0.96) 0%, + rgba(244, 247, 251, 0.92) 100% + ); +} + +.hero { + padding: clamp(5rem, 9vw, 7.4rem) 0 clamp(3rem, 6vw, 4.8rem); +} + +.heroContainer, +.sectionContainer { + width: min(1280px, calc(100% - 48px)); + margin: 0 auto; +} + +.heroContainer { + display: grid; + grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); + gap: clamp(1.8rem, 4vw, 3.8rem); + align-items: center; +} + +.heroCopy { + display: grid; + gap: 1.15rem; + max-width: 40rem; +} + +.kicker, +.sectionLabel { + display: inline-flex; + align-items: center; + gap: 0.72rem; + width: fit-content; + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--oomol-text-secondary); + + &::before { + content: ""; + width: 0.8rem; + height: 1px; + background: var(--oomol-primary); + } +} + +.heroTitle, +.sectionTitle, +.ctaTitle { + margin: 0; + font-family: var(--oomol-font-display); + letter-spacing: -0.045em; + color: var(--oomol-text-primary); +} + +.heroTitle { + max-width: 11ch; + font-size: clamp(3rem, 5.8vw, 5.1rem); + line-height: 0.95; +} + +.heroDescription, +.sectionSubtitle, +.storyLead, +.storyBody, +.principleText, +.ctaDescription { + margin: 0; + line-height: 1.74; + color: var(--oomol-text-secondary); +} + +.heroDescription { + max-width: 38rem; + font-size: 1.08rem; +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 0.85rem; + padding-top: 0.35rem; +} + +.secondaryAction { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.95rem; + padding: 0 1rem; + border-radius: 999px; + font-size: 0.96rem; + font-weight: 650; + text-decoration: none; + color: var(--oomol-text-primary); + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; + + &:hover { + text-decoration: none; + transform: translateY(-1px); + } +} + +.heroVisual { + min-width: 0; +} + +.visualFrame { + padding: 0.9rem; + border-radius: 1.9rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 95%, white 5%); + box-shadow: var(--oomol-shadow-lg); +} + +.visualImage { + display: block; + width: 100%; + height: auto; + border-radius: 1.2rem; + border: 1px solid var(--oomol-divider); +} + +.storySection, +.principlesSection, +.ctaSection { + padding: clamp(2.8rem, 6vw, 4.8rem) 0; +} + +.sectionHeader { + display: grid; + gap: 0.9rem; + margin-bottom: 1.6rem; +} + +.sectionTitle { + max-width: 13ch; + font-size: clamp(2.35rem, 4.8vw, 3.9rem); + line-height: 0.98; +} + +.storyGrid { + display: grid; + grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); + gap: 1.4rem; + align-items: start; +} + +.storyCopy { + display: grid; + gap: 1rem; +} + +.storyLead { + font-size: 1.04rem; +} + +.quoteStack { + display: grid; + gap: 0.9rem; +} + +.quoteCard { + margin: 0; + padding: 1.15rem 1.1rem; + border-radius: 1.3rem; + border: 1px solid var(--oomol-primary-border); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-primary-bg) 76%, var(--oomol-bg-elevated)) 0%, + color-mix(in srgb, var(--oomol-primary-bg) 48%, var(--oomol-bg-elevated)) 100% + ); + font-size: 0.96rem; + line-height: 1.66; + color: var(--oomol-text-secondary); + font-style: italic; +} + +.principlesGrid { + display: grid; + gap: 1.25rem; +} + +.principleCard { + display: grid; + grid-template-columns: minmax(420px, 1.14fr) minmax(320px, 0.86fr); + gap: 1.5rem; + align-items: center; + padding-top: 1rem; + border-top: 1px solid var(--oomol-divider); + + &:nth-child(even) { + grid-template-columns: minmax(320px, 0.86fr) minmax(420px, 1.14fr); + + .principleMedia { + order: 2; + } + + .principleContent { + order: 1; + } + } +} + +.principleMedia { + border-radius: 1.4rem; + padding: 0.65rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 96%, white 4%); +} + +.principleImage { + display: block; + width: 100%; + aspect-ratio: 16 / 10; + object-fit: cover; + object-position: top center; + border-radius: 1rem; + border: 1px solid var(--oomol-divider); +} + +.principleContent { + display: grid; + gap: 0.8rem; + max-width: 35rem; +} + +.principleTitle { + margin: 0; + max-width: 18ch; + font-size: 1.6rem; + line-height: 1.24; + color: var(--oomol-text-primary); +} + +.principleParagraphs { + display: grid; + gap: 0.55rem; +} + +.ctaCard { + padding: clamp(1.8rem, 3.8vw, 2.6rem); + border-radius: 1.9rem; + border: 1px solid rgba(214, 221, 236, 0.12); + background: + radial-gradient( + circle at top left, + rgba(132, 138, 208, 0.2) 0%, + rgba(132, 138, 208, 0) 32% + ), + linear-gradient(180deg, #1a1b28 0%, #12131d 100%); + box-shadow: var(--oomol-shadow-lg); +} + +.ctaTitle { + max-width: 12ch; + font-size: clamp(2.35rem, 4.6vw, 3.9rem); + line-height: 0.96; + color: rgba(243, 239, 248, 0.98); +} + +.ctaDescription { + max-width: 40rem; + padding-top: 0.9rem; + color: rgba(221, 214, 231, 0.8); +} + +.ctaCard .secondaryAction { + color: rgba(243, 239, 248, 0.94); + border-color: rgba(243, 239, 248, 0.14); + background: rgba(243, 239, 248, 0.08); +} + +:global(html[lang="en"]) .heroTitle { + max-width: 15ch; + font-size: clamp(2.7rem, 5vw, 4.55rem); + line-height: 0.98; +} + +:global(html[lang="en"]) .sectionTitle { + max-width: 17ch; + font-size: clamp(2.05rem, 4vw, 3.35rem); + line-height: 1.02; +} + +:global(html[lang="en"]) .ctaTitle { + max-width: 18ch; + font-size: clamp(2.1rem, 4vw, 3.45rem); + line-height: 1.03; +} + +@media (max-width: 996px) { + .heroContainer, + .storyGrid, + .principleCard, + .principleCard:nth-child(even) { + grid-template-columns: 1fr; + } + + .principleCard:nth-child(even) { + .principleMedia, + .principleContent { + order: initial; + } + } +} + +@media (max-width: 768px) { + .heroContainer, + .sectionContainer { + width: min(100%, calc(100% - 40px)); + } + + .hero { + padding-top: 4rem; + } + + .heroTitle, + .sectionTitle, + .ctaTitle { + max-width: 100%; + text-wrap: pretty; + } +} diff --git a/src/theme/Navbar/index.tsx b/src/theme/Navbar/index.tsx index e7df9be4..c233dda0 100644 --- a/src/theme/Navbar/index.tsx +++ b/src/theme/Navbar/index.tsx @@ -15,10 +15,18 @@ import NavbarItem from "@theme/NavbarItem"; import SearchBar from "@theme/SearchBar"; import ThemedImage from "@theme/ThemedImage"; import { clsx } from "clsx"; -import React, { memo, useMemo } from "react"; +import React, { memo, useEffect, useMemo, useRef, useState } from "react"; interface NavbarProps {} +type ProductMenuEntry = { + description: string; + href: string; + iconClassName: string; + key: string; + label: string; +}; + const DefaultNavItemPosition = "right"; function splitNavItemsByPosition( @@ -39,6 +47,9 @@ function splitNavItemsByPosition( const NavbarComponent: React.FC = memo(() => { const mobileSidebar = useNavbarMobileSidebar(); + const [productMenuOpen, setProductMenuOpen] = useState(false); + const productMenuRef = useRef(null); + const productMenuCloseTimeoutRef = useRef(null); const { siteConfig: { @@ -85,6 +96,91 @@ const NavbarComponent: React.FC = memo(() => { [items] ); + const productMenuItem = useMemo( + () => + leftItems.find(item => + String(item.className ?? "").includes("productDropdown") + ), + [leftItems] + ); + + const productMenuEntries = useMemo( + () => [ + { + key: "studio", + href: "/studio", + label: translate({ + id: "item.label.navbar.oomol-studio", + message: "OOMOL Studio", + }), + description: translate({ + message: "Theme.Navbar.product.studio.description", + }), + iconClassName: "i-lucide-square-terminal", + }, + { + key: "cloud", + href: "/cloud", + label: translate({ + id: "item.label.navbar.oomol-cloud", + message: "OOMOL Cloud", + }), + description: translate({ + message: "Theme.Navbar.product.cloud.description", + }), + iconClassName: "i-lucide-cloud-upload", + }, + ], + [] + ); + + useEffect(() => { + setProductMenuOpen(false); + }, [location.pathname]); + + useEffect(() => { + const handlePointerDown = (event: MouseEvent) => { + if ( + productMenuRef.current && + !productMenuRef.current.contains(event.target as Node) + ) { + setProductMenuOpen(false); + } + }; + + document.addEventListener("mousedown", handlePointerDown); + return () => { + document.removeEventListener("mousedown", handlePointerDown); + }; + }, []); + + useEffect(() => { + return () => { + if (productMenuCloseTimeoutRef.current !== null) { + window.clearTimeout(productMenuCloseTimeoutRef.current); + } + }; + }, []); + + const openProductMenu = () => { + if (productMenuCloseTimeoutRef.current !== null) { + window.clearTimeout(productMenuCloseTimeoutRef.current); + productMenuCloseTimeoutRef.current = null; + } + setProductMenuOpen(true); + }; + + const closeProductMenu = () => { + if (productMenuCloseTimeoutRef.current !== null) { + window.clearTimeout(productMenuCloseTimeoutRef.current); + } + + productMenuCloseTimeoutRef.current = window.setTimeout(() => { + setProductMenuOpen(false); + productMenuCloseTimeoutRef.current = null; + }, 120); + }; + const isSignedIn = () => { const cookies = document.cookie.split(";").map(cookie => cookie.trim()); return cookies.some(cookie => cookie.includes("oomol-signed-in")); @@ -157,9 +253,68 @@ const NavbarComponent: React.FC = memo(() => { - {leftItems.map((item, i) => ( - - ))} + {leftItems.map((item, i) => { + if (item === productMenuItem) { + const isProductActive = + location.pathname.startsWith("/studio") || + location.pathname.startsWith(`/${locale}/studio`) || + location.pathname.startsWith("/cloud") || + location.pathname.startsWith(`/${locale}/cloud`); + + return ( +
+ + +
+ {productMenuEntries.map(entry => ( + + + + + + + {entry.label} + + + {entry.description} + + + + ))} +
+
+ ); + } + + return ; + })}
{/* 当路由与文档路径匹配时,显示文档搜索框 */} diff --git a/src/theme/Navbar/styles.module.scss b/src/theme/Navbar/styles.module.scss index bdcffe44..a9b99d5d 100644 --- a/src/theme/Navbar/styles.module.scss +++ b/src/theme/Navbar/styles.module.scss @@ -152,6 +152,142 @@ gap: 12px; } +.productMenuWrapper { + position: relative; + display: flex; + align-items: center; + + &::after { + content: ""; + position: absolute; + top: 100%; + left: 0; + width: 100%; + height: 0.75rem; + } +} + +.productMenuTrigger { + display: inline-flex; + align-items: center; + gap: 0.52rem; + min-height: 42px; + padding: 0.52rem 0.9rem; + margin: 0 0.18rem; + border: 0; + border-radius: 999px; + background: transparent; + color: var(--oomol-text-primary); + font-weight: 600; + font-size: 14px; + cursor: pointer; + transition: + background 0.2s ease, + color 0.2s ease; + + &:hover { + color: var(--oomol-primary); + background: color-mix(in srgb, var(--oomol-primary-bg) 58%, transparent); + } +} + +.productMenuTriggerActive { + color: var(--oomol-primary); + background: color-mix(in srgb, var(--oomol-primary-bg) 76%, transparent); +} + +.productMenuCaret { + width: 0.45rem; + height: 0.45rem; + margin-left: 0.08rem; + border-right: 2px solid currentColor; + border-bottom: 2px solid currentColor; + transform: rotate(45deg) translateY(-1px); + opacity: 0.82; +} + +.productMenuPanel { + position: absolute; + top: calc(100% + 0.2rem); + left: 0; + min-width: 18rem; + padding: 0.55rem; + border-radius: 1.1rem; + border: 1px solid color-mix(in srgb, var(--oomol-border-default) 78%, white); + background: color-mix(in srgb, var(--oomol-bg-elevated) 96%, white 4%); + box-shadow: var(--oomol-shadow-lg); + opacity: 0; + pointer-events: none; + transform: translateY(-4px); + transition: + opacity 0.18s ease, + transform 0.18s ease; + z-index: 120; +} + +.productMenuPanelOpen { + opacity: 1; + pointer-events: auto; + transform: translateY(0); +} + +.productMenuEntry { + display: grid; + grid-template-columns: auto 1fr; + gap: 0.9rem; + align-items: start; + min-height: 4rem; + padding: 0.85rem 0.9rem; + border-radius: 0.95rem; + text-decoration: none; + transition: + background 0.18s ease, + transform 0.18s ease; + + &:hover { + text-decoration: none; + background: color-mix(in srgb, var(--oomol-primary-bg) 64%, transparent); + transform: translateY(-1px); + } +} + +.productMenuEntryIcon { + width: 2.15rem; + height: 2.15rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 0.8rem; + background: color-mix(in srgb, var(--oomol-bg-layout) 90%, white 10%); + border: 1px solid var(--oomol-divider); + color: var(--oomol-primary); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.7), + 0 8px 18px rgba(77, 88, 124, 0.08); + + i { + font-size: 1.05rem; + } +} + +.productMenuEntryText { + display: grid; + gap: 0.2rem; +} + +.productMenuEntryLabel { + color: var(--oomol-text-primary); + font-size: 0.96rem; + font-weight: 700; + line-height: 1.2; +} + +.productMenuEntryDescription { + color: var(--oomol-text-secondary); + font-size: 0.82rem; + line-height: 1.45; +} + .brand { display: flex; align-items: center; From 5dbfb68e1e2a56f640144e37ab1a0f1041a7fa9d Mon Sep 17 00:00:00 2001 From: shaun Date: Sat, 28 Mar 2026 16:50:15 +0800 Subject: [PATCH 02/15] update --- .impeccable.md | 21 - docusaurus.config.js | 8 +- i18n/en/code.json | 180 ++++--- i18n/zh-CN/code.json | 180 ++++--- src/components/DownloadButton/index.tsx | 18 +- .../DownloadButton/styles.module.scss | 10 + src/components/GetStartedPrompt/index.tsx | 8 +- .../GetStartedPrompt/styles.module.scss | 33 ++ src/components/HomepageCliEntry/index.tsx | 23 +- .../HomepageCliEntry/styles.module.scss | 109 ++++- src/components/HomepageFirstScreen/index.tsx | 123 +++-- .../HomepageFirstScreen/styles.module.scss | 447 +++++++++++------ src/components/HomepageLinearFlow/index.tsx | 452 ++++++++++++++++++ .../HomepageLinearFlow/styles.module.scss | 436 +++++++++++++++++ src/pages/app/index.tsx | 33 +- src/pages/cloud/index.tsx | 41 +- src/pages/cloud/styles.module.scss | 28 ++ src/pages/index.tsx | 12 +- 18 files changed, 1749 insertions(+), 413 deletions(-) delete mode 100644 .impeccable.md create mode 100644 src/components/HomepageLinearFlow/index.tsx create mode 100644 src/components/HomepageLinearFlow/styles.module.scss diff --git a/.impeccable.md b/.impeccable.md deleted file mode 100644 index 0c24a32b..00000000 --- a/.impeccable.md +++ /dev/null @@ -1,21 +0,0 @@ -## Design Context - -### Users - -OOMOL 的主要用户是希望把真实任务做成自动化流程的开发者、技术型团队成员和 AI 工作流重度用户。对文档页来说,用户通常处在“我现在就要完成一个任务”的上下文里,不是为了系统性学习平台而来,而是为了快速找到下一步动作。 - -### Brand Personality - -品牌应当给人这几种感受:直接、可靠、专业。表达上优先强调可执行性和工程感,而不是夸张营销。页面应该让用户感到“这个产品能立刻帮我做事”,而不是“我还要先花很多时间学习它”。 - -### Aesthetic Direction - -延续当前官网和文档站已经建立的方向:冷静的技术产品气质、浅色阅读界面、克制的品牌紫色点缀、较高的信息密度和清晰的层级。避免花哨的大面积营销视觉,优先让关键结论、操作路径和演示内容在首屏就被看见。 - -### Design Principles - -1. 首屏先给结论,再给解释。 -2. 所有视觉强调都必须服务于“下一步做什么”。 -3. 保持工程产品的可信感,避免过度装饰。 -4. 文档体验优先可扫描、可定位、可回看,而不是追求页面表演感。 -5. 在延续现有站点语言的前提下,用更直接的结构减少阅读负担。 diff --git a/docusaurus.config.js b/docusaurus.config.js index bf292ba3..4cf1b0d6 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -10,7 +10,7 @@ const darkTheme = themes.dracula; /** @type {import('@docusaurus/types').Config} */ const config = { title: "OOMOL", - tagline: "Write a function. Ship a service.", + tagline: "Build cloud skills. Keep the code.", favicon: "img/favicon.ico", // Set the production url of your site here @@ -70,7 +70,7 @@ const config = { "@context": "https://schema.org", "@type": "Organization", name: "OOMOL", - tagline: "Write a function. Ship a service.", + tagline: "Build cloud skills. Keep the code.", favicon: "img/favicon.ico", url: "https://oomol.com", sameAs: ["https://hub.oomol.com"], @@ -153,12 +153,12 @@ const config = { { name: "keywords", content: - "function to service, ai-native developer tools, local validation, api publishing, mcp tools, automation tasks, containerized development, function delivery, OOMOL", + "cloud skill, skill distribution, closed-source skill delivery, ai-native developer tools, local validation, oo-cli, mcp tools, automation tasks, containerized development, OOMOL", }, { name: "description", content: - "Generate functions in a real coding environment, validate locally, and publish the same capability as an API, MCP tool, or automation task.", + "Build cloud skills in a real coding environment, validate locally, and publish them for oo-cli, agents, APIs, and automation without exposing your source code.", }, ], diff --git a/i18n/en/code.json b/i18n/en/code.json index 7d06bb8b..fa882558 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -27,7 +27,7 @@ "message": "Community" }, "HOME.page.title": { - "message": "OOMOL - Build and Deliver Capabilities for Agents" + "message": "OOMOL - Build and publish cloud skills" }, "HOME.FirstScreen.slogan": { "message": "Build and Deliver Capabilities for Agents" @@ -38,6 +38,21 @@ "HOME.FirstScreen.script": { "message": "Start with ready-made capabilities in oo-cli, create your own blocks in OOMOL Studio, then deploy and deliver them privately through Cloud." }, + "HOME.FirstScreen.heroTitle": { + "message": "Let agents use your skill while you keep full control of the code" + }, + "HOME.FirstScreen.heroSubtitle": { + "message": "We call this a cloud skill: a capability that runs in the cloud and can be used directly from terminals and agent workflows." + }, + "HOME.FirstScreen.heroLead": { + "message": "A cloud skill is a capability that runs in the cloud, stays reusable, and can be used directly from terminals and agent workflows." + }, + "HOME.FirstScreen.heroAdvantage": { + "message": "Open source or closed source," + }, + "HOME.FirstScreen.heroAdvantageHighlight": { + "message": "the decision stays yours." + }, "HOME.FirstScreen.pill1": { "message": "No new DSL" }, @@ -177,7 +192,7 @@ "message": "only supports x64" }, "HOME.FirstScreen.cta.secondary": { - "message": "Start Building" + "message": "Start with oo-cli" }, "HOME.ValueProps.localCompute.title": { "message": "Turn Local Compute Into Your Private AI Cloud" @@ -876,7 +891,7 @@ "message": "Get the first path working" }, "HOME.GetStartedPrompt.subtitle": { - "message": "Start with oo-cli to use published capabilities. When you need more, write your own blocks in OOMOL Studio and deploy them through Cloud." + "message": "Start with oo-cli to run published cloud skills. When you need your own, generate and validate it in OOMOL Studio, then publish it through Cloud." }, "HOME.Pricing.title": { "message": "Pricing" @@ -921,13 +936,13 @@ "message": "CLI" }, "HOME.Downloads.cli.title": { - "message": "Prefer the terminal? Use oo-cli to consume cloud functions directly." + "message": "Prefer terminal workflows? Start with oo-cli." }, "HOME.Downloads.cli.subtitle": { - "message": "Install oo-cli in Codex, Claude Code, or any local terminal to search packages, inspect inputs, run cloud functions, and fetch results without wiring API or MCP first." + "message": "Install oo-cli in Codex, Claude Code, or any local terminal to search packages, inspect inputs, run cloud skills, and fetch results without wiring API or MCP first." }, "HOME.Downloads.cli.action.guide": { - "message": "Open CLI Guide" + "message": "Open oo-cli Guide" }, "HOME.Downloads.cli.action.github": { "message": "View oo-cli on GitHub" @@ -2467,10 +2482,10 @@ "message": "Containerized deployment to private cloud or K8s clusters, supporting CI/CD pipelines for continuous delivery and operations of enterprise-grade API services." }, "HOME.ProductComparison.title": { - "message": "Cloud exists for delivery, not just hosting" + "message": "Cloud is where a skill becomes deliverable" }, "HOME.ProductComparison.subtitle": { - "message": "Cloud is not just where code runs. It is where validated blocks become capabilities you can keep providing to yourself, your team, or your customers." + "message": "OOMOL Cloud is not just runtime. It is the delivery layer that turns a validated implementation into a cloud skill you can provide privately to yourself, your team, or your customers." }, "HOME.ChatAgent.title": { "message": "OOMOL Chat & Agent Ecosystem" @@ -2518,58 +2533,58 @@ "message": "Deploy and deliver" }, "HOME.ProductComparison.cloud.capability": { - "message": "Deploy validated blocks as cloud functions and keep providing them reliably without rebuilding another service layer around the same capability." + "message": "Deploy validated blocks as cloud skills that run remotely, so users get the capability without receiving your source code." }, "HOME.ProductComparison.cloud.scenario": { - "message": "For developers and small teams that want to extend CLI workflows, provide shared capabilities internally, or deliver skills and CLI services to customers." + "message": "For developers and small teams that want to share, sell, or operate reusable skills without rebuilding a separate SaaS around each one." }, "HOME.ProductComparison.cloud.tech": { - "message": "Reuse the implementation you already validated in Studio while OOMOL Cloud handles runtime and external delivery. When needed, the same capability can keep expanding through API or MCP." + "message": "Reuse the implementation you already validated in Studio while OOMOL Cloud handles runtime, access, and external delivery. When needed, the same cloud skill can still expand through API or MCP." }, "HOME.ProductComparison.cta": { - "message": "Explore Cloud Function" + "message": "Explore Cloud" }, "HOME.ProductComparison.outputIntro": { - "message": "Keep the same capability expanding" + "message": "One cloud skill, multiple surfaces" }, "HOME.ProductComparison.outputSummary": { - "message": "The same validated block can keep being consumed and integrated in different ways." + "message": "The same validated implementation can be consumed through terminal, apps, agents, and automation without splitting into separate products." }, "HOME.ProductComparison.output1.title": { - "message": "CLI Usage" + "message": "CLI and Agents" }, "HOME.ProductComparison.output1.description": { - "message": "Search, inspect, and run deployed capabilities directly through oo-cli." + "message": "Search, inspect, and run deployed cloud skills directly through oo-cli and agent terminal workflows." }, "HOME.ProductComparison.output2.title": { - "message": "API Integration" + "message": "API and App Integration" }, "HOME.ProductComparison.output2.description": { - "message": "Carry the same capability into your own applications, services, or automation code." + "message": "Carry the same cloud skill into your own application surfaces, backend services, or product integrations." }, "HOME.ProductComparison.output3.title": { - "message": "MCP Integration" + "message": "MCP and Automation" }, "HOME.ProductComparison.output3.description": { - "message": "When needed, keep exposing the same capability to other agent and tool systems." + "message": "Expose the same cloud skill to agent ecosystems or keep it running on schedules and triggers." }, "HOME.ProductComparison.benefit1.label": { - "message": "Delivery Overhead" + "message": "Commercialization Path" }, "HOME.ProductComparison.benefit1.value": { - "message": "Less service rebuilding" + "message": "Ship the skill, keep the code" }, "HOME.ProductComparison.benefit1.description": { - "message": "Cloud takes over the online runtime and delivery layer so you do not need to rebuild another interface stack around the same function." + "message": "Cloud lets you provide the capability without shipping the implementation, so distribution does not force you into open-sourcing or rebuilding the product as SaaS." }, "HOME.ProductComparison.benefit2.label": { - "message": "Runtime Overhead" + "message": "Delivery Overhead" }, "HOME.ProductComparison.benefit2.value": { - "message": "More stable online usage" + "message": "Less product rebuilding" }, "HOME.ProductComparison.benefit2.description": { - "message": "Stay focused on the function itself instead of spending more time on environments, scheduling, scaling, and production maintenance." + "message": "Stay focused on the skill itself instead of rebuilding auth, hosting, scheduling, and interface layers around the same implementation." }, "HOME.DeveloperBenefits.badge": { "message": "Developer Benefits" @@ -2632,10 +2647,22 @@ "message": "CLI FIRST" }, "HOME.CliEntry.title": { - "message": "Use first, then decide whether to build your own" + "message": "oo-cli is the default way to discover and run cloud skills" }, "HOME.CliEntry.subtitle": { - "message": "oo-cli is the fastest way into OOMOL. Search, inspect, and run published capabilities directly from the terminal." + "message": "Install once in Codex, Claude Code, or any terminal. Search packages, inspect inputs, run cloud skills, and get results before you wire API or MCP." + }, + "HOME.CliEntry.benefit1.label": { + "message": "Start from published skills" + }, + "HOME.CliEntry.benefit1.description": { + "message": "Search, inspect, and run skills other developers have already published instead of building your own path on day one." + }, + "HOME.CliEntry.benefit2.label": { + "message": "Publish your own when needed" + }, + "HOME.CliEntry.benefit2.description": { + "message": "When existing skills are not enough, use Studio to generate, validate, and publish your own cloud skill." }, "HOME.CliEntry.bridge": { "message": "Publish the function to OOMOL Cloud first. Then let CLI handle sign-in, discovery, and execution. That relationship only needs to be stated once." @@ -2644,25 +2671,25 @@ "message": "Install oo-cli" }, "HOME.CliEntry.step1.description": { - "message": "Install the entry point for using published capabilities." + "message": "Install the default entry point for using published cloud skills." }, "HOME.CliEntry.step2.title": { "message": "Sign in to your account" }, "HOME.CliEntry.step2.description": { - "message": "Sign in, then start searching and running capabilities." + "message": "Sign in, then start searching and running cloud skills." }, "HOME.CliEntry.step3.title": { - "message": "Search and run a capability" + "message": "Search and run a skill" }, "HOME.CliEntry.step3.description": { - "message": "Check what it does and what input it needs, then run it directly." + "message": "Check what it does and what input it needs, then run it directly from the terminal." }, "HOME.CliEntry.action.primary": { "message": "Open oo-cli" }, "HOME.CliEntry.action.secondary": { - "message": "Explore Cloud Function" + "message": "See Cloud Delivery" }, "HOME.CliEntry.setup.eyebrow": { "message": "INSTALL ONCE" @@ -2785,16 +2812,19 @@ "message": "Translate long-form documents into bilingual EPUB or Markdown outputs that stay usable for reading instead of returning only raw text." }, "CLOUD.hero.title": { - "message": "OOMOL Cloud" + "message": "Publish private cloud skills" }, "CLOUD.hero.description": { - "message": "Turn the function you already validated locally into a service, without rebuilding backend scaffolding, deployment flow, and operations from scratch." + "message": "Take the skill you already validated locally and run it in the cloud, so users can use the capability without getting your source code or a custom service stack." }, "CLOUD.hero.kicker": { - "message": "Cloud Function" + "message": "Cloud Skill Runtime" + }, + "CLOUD.hero.note": { + "message": "Users get the skill through oo-cli, apps, or agents. Your implementation stays on the server." }, "CLOUD.hero.stat1": { - "message": "Direct Publish" + "message": "Private Delivery" }, "CLOUD.hero.stat2": { "message": "Pay-as-you-go" @@ -2803,7 +2833,7 @@ "message": "Less Ops" }, "CLOUD.hero.cta.start": { - "message": "Start Building" + "message": "Build a Cloud Skill" }, "CLOUD.hero.cta.docs": { "message": "Learn More" @@ -2812,46 +2842,46 @@ "message": "Open Cloud Console" }, "CLOUD.painPoints.title": { - "message": "Delivery Shouldn't Be Torture" + "message": "Shipping a skill should not mean rebuilding a SaaS" }, "CLOUD.painPoints.subtitle": { "message": "We know the struggle as developers" }, "CLOUD.painPoints.description": { - "message": "What slows delivery is usually not the function itself, but the repeated work required to wrap it as a service: building interfaces, preparing environments, scaling it, and keeping it available. Cloud is built to compress that part." + "message": "What slows delivery is usually not the skill itself, but the work around it: packaging a user surface, hosting it reliably, handling access, and keeping operations stable. Cloud is built to compress that layer." }, "CLOUD.solution.title": { - "message": "One Function, Three Delivery Paths" + "message": "One skill, three consumption paths" }, "CLOUD.solution.subtitle": { - "message": "The same capability can be delivered as an API, an MCP tool, or an automation task." + "message": "The same cloud skill can be consumed through API, MCP, or automation while staying backed by one implementation." }, "CLOUD.solution.kicker": { - "message": "Delivery Paths" + "message": "Consumption Paths" }, "CLOUD.modes.library.title": { - "message": "Publish as Automation" + "message": "Run as Automation" }, "CLOUD.modes.library.description": { - "message": "Run the same function on triggers or schedules so it keeps working as an ongoing task instead of staying local and manual." + "message": "Run the same cloud skill on triggers or schedules so it keeps delivering value beyond local and manual execution." }, "CLOUD.modes.serverless.title": { - "message": "Publish as API Service" + "message": "Use through API" }, "CLOUD.modes.serverless.description": { - "message": "Deliver the function directly as a callable API without building a separate service framework, while OOMOL handles runtime and scaling." + "message": "Give applications direct API access to the same cloud skill without rebuilding a separate backend surface." }, "CLOUD.modes.mcp.title": { - "message": "Publish as MCP Tool" + "message": "Use through MCP" }, "CLOUD.modes.mcp.description": { - "message": "Expose the function as an MCP tool for agents and AI apps so the same implementation enters the call chain directly." + "message": "Expose the same cloud skill to agents and AI apps as an MCP tool when agent-native integration matters." }, "CLOUD.pricing.title": { - "message": "Pay Per Call, No Upfront Cost" + "message": "Start small, pay when the skill is used" }, "CLOUD.pricing.description": { - "message": "No expensive server fees, no complex prepaid plans. We charge by call count. Save money, save effort, and focus on the joy of programming." + "message": "You do not need dedicated servers just to test distribution. Publish first, validate demand, and pay as usage grows." }, "CLOUD.pricing.kicker": { "message": "Pricing" @@ -2866,13 +2896,13 @@ "message": "Open Cloud Console" }, "CLOUD.opensource.title": { - "message": "Open Source Infrastructure" + "message": "Open runtime, flexible deployment" }, "CLOUD.opensource.subtitle": { - "message": "OOMOL's underlying runtime kernel is fully open source, giving you complete control over your deployment environment" + "message": "The runtime foundation stays open source even when the cloud skill you publish stays private." }, "CLOUD.opensource.description": { - "message": "We believe in the power of open source. OOMOL's virtual machine and runtime core code are completely open source, allowing you to freely view, modify, and deploy. Whether it's a personal NAS, private server, or public cloud, you have complete deployment freedom." + "message": "OOMOL's virtual machine and runtime core stay open source, so you keep deployment freedom across personal servers, private infrastructure, or public cloud environments while choosing how each skill is delivered." }, "CLOUD.opensource.projects.title": { "message": "Open Source Projects" @@ -2904,16 +2934,16 @@ "STUDIO.hero.description": { "message": "Local development environment for developers, VSCode-based visual programming tool with FRP protocol for P2P computing power sharing" }, - "APP.new.hero.title": { "message": "OOMOL App" }, + "APP.new.hero.title": { "message": "OOMOL App Surfaces" }, "APP.new.hero.subtitle": { - "message": "Direct Product Surfaces for Your Functions" + "message": "Product surfaces for cloud skills" }, "APP.new.hero.description": { - "message": "Turn function capabilities directly into Chat skills or Applet entry points, without building separate UI from scratch." + "message": "A single cloud skill can be delivered through chat or structured applets, without building separate product surfaces from scratch." }, - "APP.new.concept.title": { "message": "Code is Product" }, + "APP.new.concept.title": { "message": "One skill, different surfaces" }, "APP.new.concept.description": { - "message": "OOMOL wraps function capabilities into usable product surfaces. You focus on the function; we connect it to the user." + "message": "OOMOL turns the same cloud skill into usable entry points. You focus on the implementation; we connect it to the user." }, "APP.new.chat.pill": { "message": "Chat Surface · Skill" }, "APP.new.chat.title": { "message": "OOMOL Chat" }, @@ -2921,37 +2951,37 @@ "message": "AI Assistant · Exploratory Interaction" }, "APP.new.chat.description": { - "message": "When user intent is still vague, let AI choose and call your function capabilities through conversation." + "message": "When user intent is still vague, let AI choose and run the right cloud skill through conversation." }, "APP.new.chat.meta1.label": { "message": "For Whom" }, "APP.new.chat.meta1.value": { - "message": "Best when capabilities need to be exposed through conversation and intent needs clarification first" + "message": "Best when a cloud skill should be used through conversation and intent needs clarification first" }, "APP.new.chat.meta2.label": { "message": "Core Experience" }, "APP.new.chat.meta2.value": { - "message": "Understand intent first, then call the right service with less user setup" + "message": "Understand intent first, then call the right cloud skill with less setup" }, "APP.new.chat.devValue": { - "message": "Functions as Skills: your functions become AI-callable capabilities." + "message": "Cloud skill as agent tool: the same implementation becomes an AI-callable surface." }, - "APP.new.applet.pill": { "message": "Parameterized Surface · Applet" }, + "APP.new.applet.pill": { "message": "Structured Surface · Applet" }, "APP.new.applet.title": { "message": "OOMOL Applet" }, "APP.new.applet.subtitle": { "message": "Form Applet · Deterministic Interaction" }, "APP.new.applet.description": { - "message": "When inputs are clear, call the function directly through structured parameters for more reliable delivery." + "message": "When inputs are clear, run the same cloud skill through structured parameters for more reliable delivery." }, "APP.new.applet.meta1.label": { "message": "For Whom" }, "APP.new.applet.meta1.value": { - "message": "Best for teams delivering fixed-input function capabilities to internal or external users" + "message": "Best for teams delivering fixed-input cloud skills to internal or external users" }, "APP.new.applet.meta2.label": { "message": "Core Experience" }, "APP.new.applet.meta2.value": { - "message": "Wrap a function as a fillable, executable, and reusable product entry point" + "message": "Wrap the same cloud skill as a fillable, executable, and reusable entry point" }, "APP.new.applet.devValue": { - "message": "Function as App: auto-generated parameter UI with less frontend boilerplate." + "message": "Cloud skill as app: auto-generated parameter UI with less frontend boilerplate." }, "APP.new.hero.cta.web": { "message": "Use in Web" @@ -3022,28 +3052,28 @@ "message": "So Studio has a clear role: not to replace engineering workflow, but to bring function generation, local validation, and delivery back inside it." }, "HOME.StudioChain.title": { - "message": "From blocks to deployment to delivery" + "message": "From idea to cloud skill" }, "HOME.StudioChain.subtitle": { - "message": "When ready-made capabilities are not enough, OOMOL lets you keep moving: build blocks in Studio, deploy through Cloud, and deliver the capability with one continuous path." + "message": "When ready-made skills are not enough, OOMOL gives you one continuous path: generate in Studio, validate locally, publish through Cloud, and deliver through oo-cli." }, "HOME.StudioChain.lead": { - "message": "Do not just connect capabilities. Build them and deliver them." + "message": "Do not stop at local automation. Build a skill people can actually use." }, "HOME.StudioChain.summary": { - "message": "In OOMOL, you can start with ready-made capabilities, create your own blocks in Studio, then deploy and deliver them privately to yourself, your team, or your customers." + "message": "In OOMOL, you can start with ready-made skills, create your own implementation in Studio, validate it locally, then publish it privately to yourself, your team, or your customers." }, "HOME.StudioChain.card1.title": { "message": "OOMOL Studio" }, "HOME.StudioChain.card1.description": { - "message": "Write, debug, and validate your own blocks in a familiar environment for code, dependencies, and inputs." + "message": "Describe, write, debug, and validate your own skill in a real coding environment for code, dependencies, and inputs." }, "HOME.StudioChain.card2.title": { "message": "Cloud" }, "HOME.StudioChain.card2.description": { - "message": "Deploy validated blocks as cloud functions and keep providing them reliably without exposing your source code." + "message": "Publish the validated implementation as a cloud skill and keep serving it without exposing your source code." }, "HOME.StudioChain.action.studio": { "message": "Explore Studio" @@ -3055,7 +3085,7 @@ "message": "Build, debug, and validate your blocks" }, "Theme.Navbar.product.cloud.description": { - "message": "Deploy and deliver capabilities privately" + "message": "Publish and deliver cloud skills privately" }, "Theme.Navbar.product.label": { "message": "Product" diff --git a/i18n/zh-CN/code.json b/i18n/zh-CN/code.json index d53207e3..cc2e7c3a 100644 --- a/i18n/zh-CN/code.json +++ b/i18n/zh-CN/code.json @@ -27,7 +27,7 @@ "message": "社区" }, "HOME.page.title": { - "message": "OOMOL - 为 agent 构建并交付你的能力" + "message": "OOMOL - 构建并发布 cloud skill" }, "HOME.FirstScreen.slogan": { "message": "为 agent 构建并交付你的能力" @@ -38,6 +38,21 @@ "HOME.FirstScreen.script": { "message": "先通过 oo-cli 使用现成能力,再在 OOMOL Studio 中编写自己的 block,最后通过 Cloud 私有部署并交付出去。" }, + "HOME.FirstScreen.heroTitle": { + "message": "让 Agent 用上你的 Skill,\n代码依然由你掌控。" + }, + "HOME.FirstScreen.heroSubtitle": { + "message": "我们把这种运行在云端、可被终端和 agent 工作流直接使用的能力,叫做 cloud skill。" + }, + "HOME.FirstScreen.heroLead": { + "message": "cloud skill 是一种运行在云端、可复用,并且能被终端和 agent 工作流直接使用的能力。" + }, + "HOME.FirstScreen.heroAdvantage": { + "message": "开源还是闭源," + }, + "HOME.FirstScreen.heroAdvantageHighlight": { + "message": "都由你自己决定。" + }, "HOME.FirstScreen.pill1": { "message": "不学新 DSL" }, @@ -262,7 +277,7 @@ "message": "仅支持 x64 版本" }, "HOME.FirstScreen.cta.secondary": { - "message": "开始构建" + "message": "先用 oo-cli" }, "HOME.ValueProps.localCompute.title": { "message": "将本地算力转化为你的私有 AI 云" @@ -961,7 +976,7 @@ "message": "先把第一条链路跑通" }, "HOME.GetStartedPrompt.subtitle": { - "message": "先下载 oo-cli,使用已经发布好的能力。需要时,再用 OOMOL Studio 写自己的 block,并通过 Cloud 部署出去。" + "message": "先通过 oo-cli 运行已经发布好的 cloud skill。需要时,再回到 OOMOL Studio 里生成并验证自己的实现,再通过 Cloud 发布出去。" }, "HOME.Pricing.title": { "message": "价格" @@ -1006,13 +1021,13 @@ "message": "CLI" }, "HOME.Downloads.cli.title": { - "message": "更想直接在终端里用?通过 oo-cli 直接消费云函数。" + "message": "更偏终端工作流?先从 oo-cli 开始。" }, "HOME.Downloads.cli.subtitle": { - "message": "在 Codex、Claude Code 或任意本地终端中安装 oo-cli,就可以先搜包、看输入、执行云函数,再拿结果,不必一开始就接 API 或 MCP。" + "message": "在 Codex、Claude Code 或任意本地终端中安装 oo-cli,就可以先搜包、看输入、执行 cloud skill,再拿结果,不必一开始就接 API 或 MCP。" }, "HOME.Downloads.cli.action.guide": { - "message": "打开 CLI 指南" + "message": "打开 oo-cli 指南" }, "HOME.Downloads.cli.action.github": { "message": "查看 oo-cli GitHub" @@ -2554,10 +2569,10 @@ "message": "容器化部署到私有云或 K8s 集群,支持 CI/CD 流水线,实现企业级 API 服务的持续交付和运维。" }, "HOME.ProductComparison.title": { - "message": "不是为了上云,而是为了交付" + "message": "Cloud 不是托管层,而是 skill 的交付层" }, "HOME.ProductComparison.subtitle": { - "message": "Cloud 的意义,不只是把代码放到云上,而是让已经验证过的 block 可以持续提供给自己、团队或客户使用。" + "message": "OOMOL Cloud 不只是代码运行的地方,而是把已经验证过的实现变成 cloud skill,并私有交付给自己、团队或客户的那一层。" }, "HOME.ChatAgent.title": { "message": "OOMOL Chat & Agent 生态" @@ -2605,58 +2620,58 @@ "message": "部署并交付" }, "HOME.ProductComparison.cloud.capability": { - "message": "把已经验证过的 block 部署为云函数,稳定提供给自己、团队或客户使用,不必再围着同一份能力重做一层服务。" + "message": "把已经验证过的 block 发布为 cloud skill,让用户拿到能力,而不是拿到你的源码。" }, "HOME.ProductComparison.cloud.scenario": { - "message": "适合给自己扩展 CLI 能力、给团队提供统一能力,或给客户提供 skill 与 CLI 服务的开发者和小团队。" + "message": "适合想把 skill 共享、售卖或持续运营出去,但又不想围着每个能力重做一层 SaaS 的开发者和小团队。" }, "HOME.ProductComparison.cloud.tech": { - "message": "沿用 Studio 中已经跑通的实现,由 OOMOL Cloud 承接运行和对外交付;如果需要,同一份能力也可以继续通过 API 或 MCP 接出去。" + "message": "沿用 Studio 中已经跑通的实现,由 OOMOL Cloud 承接运行、访问控制和对外交付;如果需要,同一份 cloud skill 也可以继续通过 API 或 MCP 接出去。" }, "HOME.ProductComparison.cta": { - "message": "查看 Cloud Function" + "message": "了解 Cloud" }, "HOME.ProductComparison.outputIntro": { - "message": "同一份能力,按需继续扩展" + "message": "一个 cloud skill,多种消费面" }, "HOME.ProductComparison.outputSummary": { - "message": "同一份已经验证过的 block,可以继续通过不同方式被消费和集成。" + "message": "同一份已经验证过的实现,可以继续被终端、应用、agent 和自动化消费,而不用拆成多个产品。" }, "HOME.ProductComparison.output1.title": { - "message": "CLI 使用" + "message": "CLI 与 Agent" }, "HOME.ProductComparison.output1.description": { - "message": "通过 oo-cli 直接搜索、查看和运行已经部署好的能力。" + "message": "通过 oo-cli 和 agent 终端工作流,直接搜索、查看和运行已经部署好的 cloud skill。" }, "HOME.ProductComparison.output2.title": { - "message": "API 接入" + "message": "API 与应用接入" }, "HOME.ProductComparison.output2.description": { - "message": "把同一份能力继续接进自己的应用、服务或自动化代码。" + "message": "把同一份 cloud skill 接进自己的应用界面、后端服务或产品集成里。" }, "HOME.ProductComparison.output3.title": { - "message": "MCP 接入" + "message": "MCP 与自动化" }, "HOME.ProductComparison.output3.description": { - "message": "在需要时,把同一份能力继续接入其他 agent 和工具系统。" + "message": "在需要时,把同一份 cloud skill 接入 agent 生态,或让它持续按触发器和定时器运行。" }, "HOME.ProductComparison.benefit1.label": { - "message": "交付负担" + "message": "商业化路径" }, "HOME.ProductComparison.benefit1.value": { - "message": "少补一层服务" + "message": "交付 skill,不交付源码" }, "HOME.ProductComparison.benefit1.description": { - "message": "Cloud 承接函数的线上运行和对外交付,让你不用再围着同一份能力重做一套接口工程。" + "message": "Cloud 让你交付能力而不交付实现,分发不再逼着你不是开源,就是重做成完整 SaaS。" }, "HOME.ProductComparison.benefit2.label": { - "message": "运行负担" + "message": "交付负担" }, "HOME.ProductComparison.benefit2.value": { - "message": "更稳定地在线上用" + "message": "少重做产品外壳" }, "HOME.ProductComparison.benefit2.description": { - "message": "把精力放回函数本身,而不是持续处理环境、调度、扩缩容和线上维护。" + "message": "把精力放回 skill 本身,而不是持续重做鉴权、托管、调度和交互外壳。" }, "HOME.DeveloperBenefits.badge": { "message": "开发者福利" @@ -2719,10 +2734,22 @@ "message": "CLI FIRST" }, "HOME.CliEntry.title": { - "message": "先用,再决定要不要自己做" + "message": "oo-cli 是发现和运行 cloud skill 的默认入口" }, "HOME.CliEntry.subtitle": { - "message": "oo-cli 是 OOMOL 最快的使用入口。你可以先搜索、查看、运行已经发布好的能力,在终端里直接开始使用。" + "message": "在 Codex、Claude Code 或任意终端里装一次,就可以搜索包、查看输入、运行 cloud skill,再决定要不要接 API 或 MCP。" + }, + "HOME.CliEntry.benefit1.label": { + "message": "先用现成 skill" + }, + "HOME.CliEntry.benefit1.description": { + "message": "先从别人已经发布好的 skill 开始搜索、查看和运行,不必第一天就自己重做一套。" + }, + "HOME.CliEntry.benefit2.label": { + "message": "需要时再发布自己的" + }, + "HOME.CliEntry.benefit2.description": { + "message": "如果现成 skill 不够,就回到 Studio 里生成、验证并发布自己的 cloud skill。" }, "HOME.CliEntry.bridge": { "message": "函数先发布到 OOMOL Cloud,CLI 再负责登录、搜索和调用。这层关系说一遍就够,重点是让你第一次跑通。" @@ -2731,25 +2758,25 @@ "message": "安装 oo-cli" }, "HOME.CliEntry.step1.description": { - "message": "先把使用入口装好。" + "message": "先把使用已发布 cloud skill 的默认入口装好。" }, "HOME.CliEntry.step2.title": { "message": "登录账号" }, "HOME.CliEntry.step2.description": { - "message": "登录后开始搜索和运行已发布能力。" + "message": "登录后开始搜索和运行已发布的 cloud skill。" }, "HOME.CliEntry.step3.title": { - "message": "搜索并运行能力" + "message": "搜索并运行 skill" }, "HOME.CliEntry.step3.description": { - "message": "先看清楚能力做什么、需要什么输入,再直接运行。" + "message": "先看清楚 skill 做什么、需要什么输入,再直接在终端里运行。" }, "HOME.CliEntry.action.primary": { "message": "查看 oo-cli" }, "HOME.CliEntry.action.secondary": { - "message": "查看 Cloud Function" + "message": "了解 Cloud 交付" }, "HOME.CliEntry.setup.eyebrow": { "message": "INSTALL ONCE" @@ -2872,16 +2899,19 @@ "message": "把长文档翻译成可继续阅读的双语 EPUB 或 Markdown 输出,而不是只拿回一段文本结果。" }, "CLOUD.hero.title": { - "message": "OOMOL Cloud" + "message": "发布私有的 cloud skill" }, "CLOUD.hero.description": { - "message": "把已经在本地跑通的函数直接交付成服务,不必再重搭后端、部署框架和运维流程。" + "message": "把已经在本地验证过的 skill 放到云端运行,让用户用到能力,而不用拿到你的源码或一套单独搭出来的服务。" }, "CLOUD.hero.kicker": { - "message": "Cloud Function" + "message": "Cloud Skill Runtime" + }, + "CLOUD.hero.note": { + "message": "用户通过 oo-cli、应用或 agent 使用 skill,而你的实现继续留在服务器端。" }, "CLOUD.hero.stat1": { - "message": "直接发布" + "message": "私有交付" }, "CLOUD.hero.stat2": { "message": "按量计费" @@ -2890,7 +2920,7 @@ "message": "少管运维" }, "CLOUD.hero.cta.start": { - "message": "开始使用" + "message": "开始构建 Cloud Skill" }, "CLOUD.hero.cta.docs": { "message": "了解更多" @@ -2899,46 +2929,46 @@ "message": "打开 Cloud 控制台" }, "CLOUD.painPoints.title": { - "message": "交付代码不该是折磨" + "message": "交付一个 skill,不该等于重做一个 SaaS" }, "CLOUD.painPoints.subtitle": { "message": "作为开发者,我们深知你的苦恼" }, "CLOUD.painPoints.description": { - "message": "真正拖慢交付的,往往不是函数本身,而是把它包成服务的那一大段重复工作:准备接口、部署环境、配置扩缩容、维护可用性。Cloud 的目标就是把这段工作缩到最短。" + "message": "真正拖慢交付的,往往不是 skill 本身,而是围绕它补出来的那层东西:给用户做入口、让它稳定在线、控制访问、承担运维。Cloud 的目标就是把这一层压到最短。" }, "CLOUD.solution.title": { - "message": "同一份函数,三种交付方式" + "message": "一个 skill,三种消费路径" }, "CLOUD.solution.subtitle": { - "message": "写好的函数能力,可以继续交付为 API、MCP 工具或自动化任务。" + "message": "同一个 cloud skill 可以继续通过 API、MCP 或自动化被消费,同时仍然只维护一份实现。" }, "CLOUD.solution.kicker": { - "message": "交付方式" + "message": "消费路径" }, "CLOUD.modes.library.title": { - "message": "发布成自动化任务" + "message": "作为自动化运行" }, "CLOUD.modes.library.description": { - "message": "按触发器或定时器运行同一份函数能力,让它持续执行,而不是停留在本地手动运行。" + "message": "让同一个 cloud skill 按触发器或定时器持续运行,而不是只停留在本地手动执行。" }, "CLOUD.modes.serverless.title": { - "message": "发布成 API 服务" + "message": "通过 API 使用" }, "CLOUD.modes.serverless.description": { - "message": "不必再单独搭服务框架,直接把函数交付为可调用 API,并由 OOMOL 负责运行和扩缩容。" + "message": "让应用直接通过 API 调用同一个 cloud skill,而不用围绕它再补一层独立后端。" }, "CLOUD.modes.mcp.title": { - "message": "发布成 MCP 工具" + "message": "通过 MCP 使用" }, "CLOUD.modes.mcp.description": { - "message": "把函数能力作为 MCP Tool 暴露给 Agent 和 AI 应用,让同一份实现直接进入调用链。" + "message": "当 agent-native 集成更重要时,把同一个 cloud skill 作为 MCP Tool 暴露给 Agent 和 AI 应用。" }, "CLOUD.pricing.title": { - "message": "按调用收费,不用预支" + "message": "先发布,按使用增长再付费" }, "CLOUD.pricing.description": { - "message": "没有昂贵的服务器租用费,没有复杂的预付费套餐。我们按调用次数收取费用,真正做到省钱省力,让你专注于享受编程的乐趣。" + "message": "你不需要为了验证分发这件事先养一台服务器。先把 skill 发布出去,验证需求,再随着使用量增长付费。" }, "CLOUD.pricing.kicker": { "message": "价格" @@ -2953,13 +2983,13 @@ "message": "打开 Cloud 控制台" }, "CLOUD.opensource.title": { - "message": "开源基础设施" + "message": "开放运行时,灵活部署" }, "CLOUD.opensource.subtitle": { - "message": "OOMOL 的底层运行时内核全部开源,让你完全掌控部署环境" + "message": "即使你发布的 cloud skill 是私有的,底层运行时基础仍然保持开源。" }, "CLOUD.opensource.description": { - "message": "我们坚信开源的力量。OOMOL 的虚拟机和运行时核心代码完全开源,你可以自由查看、修改和部署。无论是个人 NAS、私有服务器还是公有云,你都拥有完全的部署自由。" + "message": "OOMOL 的虚拟机和运行时核心持续开源,所以无论你用个人服务器、私有基础设施还是公有云,都依然保有部署自由,同时为每个 skill 单独决定如何交付。" }, "CLOUD.opensource.projects.title": { "message": "开源项目" @@ -2991,48 +3021,48 @@ "STUDIO.hero.description": { "message": "面向开发者的本地开发环境,基于 VSCode 的可视化编程工具,结合 FRP 协议实现 P2P 算力共享" }, - "APP.new.hero.title": { "message": "OOMOL App" }, - "APP.new.hero.subtitle": { "message": "把函数直接交付给用户" }, + "APP.new.hero.title": { "message": "OOMOL App Surfaces" }, + "APP.new.hero.subtitle": { "message": "cloud skill 的产品化入口" }, "APP.new.hero.description": { - "message": "无需单独开发 UI,把函数能力直接交付为 Chat 技能或 Applet 入口,让用户立刻可以使用。" + "message": "一个 cloud skill 可以继续通过对话入口或结构化 applet 被使用,而不用为每种产品形态重做一套界面。" }, - "APP.new.concept.title": { "message": "代码即产品" }, + "APP.new.concept.title": { "message": "一个 skill,多种入口" }, "APP.new.concept.description": { - "message": "OOMOL 把函数能力封装成可直接使用的产品入口。你专注写函数,我们负责把它连接到用户。" + "message": "OOMOL 把同一个 cloud skill 包装成不同的可用入口。你专注实现本身,我们负责把它连接到用户。" }, "APP.new.chat.pill": { "message": "对话入口 · Chat Skill" }, "APP.new.chat.title": { "message": "OOMOL Chat" }, "APP.new.chat.subtitle": { "message": "AI 助手 · 探索性交互" }, "APP.new.chat.description": { - "message": "当用户需求还不够明确时,让 AI 在对话中选择并调用你的函数能力。" + "message": "当用户意图还不够明确时,让 AI 在对话中选择并运行合适的 cloud skill。" }, "APP.new.chat.meta1.label": { "message": "适合谁" }, "APP.new.chat.meta1.value": { - "message": "适合通过对话暴露函数能力、逐步澄清需求的场景" + "message": "适合通过对话暴露 cloud skill,并先逐步澄清用户意图的场景" }, "APP.new.chat.meta2.label": { "message": "核心体验" }, "APP.new.chat.meta2.value": { - "message": "先理解意图,再调用服务,降低用户上手门槛" + "message": "先理解意图,再调用正确的 cloud skill,降低用户上手门槛" }, "APP.new.chat.devValue": { - "message": "函数即技能:你的函数就是 AI 可调用的能力" + "message": "cloud skill 即 agent tool:同一份实现可以直接变成 AI 可调用入口" }, - "APP.new.applet.pill": { "message": "参数入口 · Applet" }, + "APP.new.applet.pill": { "message": "结构化入口 · Applet" }, "APP.new.applet.title": { "message": "OOMOL Applet" }, "APP.new.applet.subtitle": { "message": "表单小程序 · 确定性交互" }, "APP.new.applet.description": { - "message": "当用户输入明确时,用结构化参数直接调用函数能力,交付更稳定。" + "message": "当用户输入明确时,用结构化参数运行同一个 cloud skill,交付更稳定。" }, "APP.new.applet.meta1.label": { "message": "适合谁" }, "APP.new.applet.meta1.value": { - "message": "适合把固定输入输出的函数能力交付给团队或最终用户" + "message": "适合把固定输入输出的 cloud skill 交付给团队或最终用户" }, "APP.new.applet.meta2.label": { "message": "核心体验" }, "APP.new.applet.meta2.value": { - "message": "把函数包装成可填写、可执行、可复用的产品入口" + "message": "把同一个 cloud skill 包装成可填写、可执行、可复用的产品入口" }, "APP.new.applet.devValue": { - "message": "函数即应用:自动生成参数入口,减少前端样板" + "message": "cloud skill 即应用:自动生成参数入口,减少前端样板" }, "APP.new.hero.cta.web": { "message": "在网页中使用" @@ -3103,28 +3133,28 @@ "message": "所以 Studio 的角色很明确:它不是为了替代工程环境,而是把函数生成、本地验证和后续交付重新放回工程环境里。" }, "HOME.StudioChain.title": { - "message": "从 block,到部署,再到交付" + "message": "从想法,到 cloud skill" }, "HOME.StudioChain.subtitle": { - "message": "当现成能力不够时,OOMOL 让你继续往下走: 在 OOMOL Studio 里生产 block,在 Cloud 里部署,并把能力稳定交付出去。" + "message": "当现成 skill 不够时,OOMOL 给你一条连续的路径:在 Studio 里生成,在本地验证,通过 Cloud 发布,再由 oo-cli 交付出去。" }, "HOME.StudioChain.lead": { - "message": "不只是连接能力,更是把能力做出来并交付出去。" + "message": "不要停在本地自动化,把它做成别人真的能用的 skill。" }, "HOME.StudioChain.summary": { - "message": "在 OOMOL 里,你可以先使用现成能力,再在 Studio 里编写和验证自己的 block,最后通过 Cloud 私有部署并交付给自己、团队或客户使用。" + "message": "在 OOMOL 里,你可以先使用现成 skill,再在 Studio 里生成并验证自己的实现,最后通过 Cloud 私有发布给自己、团队或客户使用。" }, "HOME.StudioChain.card1.title": { "message": "OOMOL Studio" }, "HOME.StudioChain.card1.description": { - "message": "在 Studio 里编写、调试和验证自己的 block,用熟悉的方式组织代码、依赖和输入输出。" + "message": "在 Studio 里描述、编写、调试和验证自己的 skill,用真实工程环境管理代码、依赖和输入输出。" }, "HOME.StudioChain.card2.title": { "message": "Cloud" }, "HOME.StudioChain.card2.description": { - "message": "把已经验证过的 block 部署为云函数,稳定提供给自己、团队或客户使用。" + "message": "把已经验证过的实现发布为 cloud skill,持续提供给自己、团队或客户使用,而不暴露源码。" }, "HOME.StudioChain.action.studio": { "message": "了解 Studio" @@ -3136,7 +3166,7 @@ "message": "编写、调试并验证你的 block" }, "Theme.Navbar.product.cloud.description": { - "message": "部署并私有交付你的能力" + "message": "私有发布并交付你的 cloud skill" }, "Theme.Navbar.product.label": { "message": "产品" diff --git a/src/components/DownloadButton/index.tsx b/src/components/DownloadButton/index.tsx index cdf87fa0..21aa33f0 100644 --- a/src/components/DownloadButton/index.tsx +++ b/src/components/DownloadButton/index.tsx @@ -27,19 +27,29 @@ function detectOSAndArchitecture(): OS { export interface DownloadButtonProps { stableTag?: boolean; + centered?: boolean; } -export const DownloadButton = ({ stableTag }: DownloadButtonProps) => { +export const DownloadButton = ({ + stableTag, + centered, +}: DownloadButtonProps) => { const downloadIcon = (
diff --git a/src/components/GetStartedPrompt/styles.module.scss b/src/components/GetStartedPrompt/styles.module.scss index 276807f6..f7c56f71 100644 --- a/src/components/GetStartedPrompt/styles.module.scss +++ b/src/components/GetStartedPrompt/styles.module.scss @@ -54,6 +54,39 @@ padding-bottom: 0.6rem; } +.actions { + display: grid; + gap: 0.85rem; + justify-items: start; +} + +.secondaryLink { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.8rem; + padding: 0 1rem; + border-radius: 999px; + border: 1px solid rgba(243, 239, 248, 0.16); + background: rgba(243, 239, 248, 0.08); + color: rgba(243, 239, 248, 0.94); + font-size: 0.95rem; + font-weight: 650; + text-decoration: none; + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease; + + &:hover { + transform: translateY(-1px); + text-decoration: none; + background: rgba(243, 239, 248, 0.12); + border-color: rgba(243, 239, 248, 0.22); + color: rgba(243, 239, 248, 0.98); + } +} + .imageWrapper, .image { display: none; diff --git a/src/components/HomepageCliEntry/index.tsx b/src/components/HomepageCliEntry/index.tsx index f0b664e3..211c9560 100644 --- a/src/components/HomepageCliEntry/index.tsx +++ b/src/components/HomepageCliEntry/index.tsx @@ -72,6 +72,24 @@ export default function HomepageCliEntry() {

{translate({ message: "HOME.CliEntry.subtitle" })}

+
+
+
+ {translate({ message: "HOME.CliEntry.benefit1.label" })} +
+

+ {translate({ message: "HOME.CliEntry.benefit1.description" })} +

+
+
+
+ {translate({ message: "HOME.CliEntry.benefit2.label" })} +
+

+ {translate({ message: "HOME.CliEntry.benefit2.description" })} +

+
+
{steps.map(step => ( @@ -86,7 +104,10 @@ export default function HomepageCliEntry() {
- + {translate({ message: "HOME.CliEntry.action.primary" })} diff --git a/src/components/HomepageCliEntry/styles.module.scss b/src/components/HomepageCliEntry/styles.module.scss index 2871d296..2a2facaa 100644 --- a/src/components/HomepageCliEntry/styles.module.scss +++ b/src/components/HomepageCliEntry/styles.module.scss @@ -51,9 +51,9 @@ .title { margin: 0; - max-width: 12ch; + max-width: 13ch; font-family: var(--oomol-font-display); - font-size: clamp(2.4rem, 4.6vw, 4rem); + font-size: clamp(2.2rem, 4.2vw, 3.55rem); line-height: 1; letter-spacing: -0.045em; color: var(--oomol-text-primary); @@ -61,16 +61,61 @@ .subtitle { margin: 0; - max-width: 38rem; - font-size: 1.02rem; - line-height: 1.75; + max-width: 40rem; + font-size: 1.04rem; + line-height: 1.72; + color: var(--oomol-text-secondary); +} + +.benefitGrid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.85rem; + margin-top: 0.2rem; +} + +.benefitCard { + display: grid; + gap: 0.42rem; + padding: 0.95rem 1rem 1rem; + border: 1px solid color-mix(in srgb, var(--oomol-border-default) 82%, white); + border-radius: 1.1rem; + background: + linear-gradient( + 180deg, + rgba(255, 255, 255, 0.72), + rgba(255, 255, 255, 0.4) + ), + color-mix(in srgb, var(--oomol-bg-elevated) 88%, white 12%); + box-shadow: 0 14px 26px rgba(130, 142, 181, 0.08); +} + +.benefitLabel { + display: inline-flex; + width: fit-content; + align-items: center; + min-height: 1.7rem; + padding: 0 0.62rem; + border-radius: 999px; + background: color-mix(in srgb, var(--oomol-primary-bg) 60%, white); + color: var(--oomol-primary-text); + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.benefitDescription { + margin: 0; + font-size: 0.94rem; + line-height: 1.62; color: var(--oomol-text-secondary); } .stepList { display: grid; gap: 0.85rem; - margin-top: 0.5rem; + margin-top: 0.35rem; } .stepCard { @@ -158,7 +203,11 @@ 0 12px 24px rgba(52, 57, 94, 0.14); &:hover { - border-color: color-mix(in srgb, var(--oomol-primary-active) 72%, black 16%); + border-color: color-mix( + in srgb, + var(--oomol-primary-active) 72%, + black 16% + ); background: linear-gradient( 180deg, color-mix(in srgb, var(--oomol-primary) 72%, white 12%) 0%, @@ -434,6 +483,10 @@ .title { max-width: 14ch; } + + .benefitGrid { + grid-template-columns: 1fr; + } } @media (max-width: 640px) { @@ -449,6 +502,10 @@ flex-direction: column; } + .benefitCard { + padding: 0.88rem 0.92rem 0.94rem; + } + .setupCard, .demoCard { border-radius: 1.45rem; @@ -475,6 +532,10 @@ max-width: 42rem; } +:global(html[lang="en"]) .benefitLabel { + letter-spacing: 0.06em; +} + [data-theme="dark"] { .section { background: @@ -537,6 +598,40 @@ inset 0 1px 0 rgba(255, 255, 255, 0.04); } + .benefitCard { + border-color: color-mix( + in srgb, + var(--oomol-border-default) 76%, + var(--oomol-divider) + ); + background: linear-gradient( + 180deg, + color-mix( + in srgb, + var(--oomol-bg-container) 84%, + var(--oomol-bg-elevated) 16% + ) + 0%, + color-mix(in srgb, var(--oomol-bg-elevated) 90%, black 10%) 100% + ); + box-shadow: + 0 14px 30px rgba(0, 0, 0, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.04); + } + + .benefitLabel { + background: color-mix( + in srgb, + var(--oomol-primary-bg) 28%, + var(--oomol-bg-container) 72% + ); + color: color-mix(in srgb, var(--oomol-primary-text) 88%, white 12%); + } + + .benefitDescription { + color: color-mix(in srgb, var(--oomol-text-secondary) 90%, white 10%); + } + .demoStage { border-color: rgba(255, 255, 255, 0.09); background: diff --git a/src/components/HomepageFirstScreen/index.tsx b/src/components/HomepageFirstScreen/index.tsx index a7ed5b45..40a8ebc2 100644 --- a/src/components/HomepageFirstScreen/index.tsx +++ b/src/components/HomepageFirstScreen/index.tsx @@ -1,62 +1,105 @@ import styles from "./styles.module.scss"; +import Link from "@docusaurus/Link"; import { translate } from "@docusaurus/Translate"; import useBaseUrl from "@docusaurus/useBaseUrl"; -import ThemedImage from "@theme/ThemedImage"; -import React from "react"; +import React, { useRef, useState } from "react"; import { DownloadButton } from "../DownloadButton"; -function parseHighlightText(text: string) { - const parts = text.split(/(\*\*.*?\*\*)/g); - return parts.map((part, index) => { - if (part.startsWith("**") && part.endsWith("**")) { - const content = part.slice(2, -2); - return ( - - {content} - - ); +export default function HomepageFirstScreen() { + const [isPlaying, setIsPlaying] = useState(false); + const videoRef = useRef(null); + const heroVideoUrl = useBaseUrl( + "/img/docs/cn/get-started/zero-to-one/merge-into-a-reusable-block-light.mp4" + ); + + const handlePlay = async () => { + if (!videoRef.current) { + return; } - return {part}; - }); -} -export default function HomepageFirstScreen() { - const scriptText = translate({ - message: "HOME.FirstScreen.script", - }); + try { + await videoRef.current.play(); + setIsPlaying(true); + } catch { + setIsPlaying(false); + } + }; return (
-
-
- {translate({ - message: "HOME.FirstScreen.kicker", - })} -
+

{translate({ - message: "HOME.FirstScreen.slogan", + message: "HOME.FirstScreen.heroTitle", })}

-

{parseHighlightText(scriptText)}

-
- -
+

+ {translate({ + message: "HOME.FirstScreen.heroLead", + })} +

+

+ + {translate({ + message: "HOME.FirstScreen.heroAdvantage", + })} + + + {translate({ + message: "HOME.FirstScreen.heroAdvantageHighlight", + })} + +

-
- +
+
+ + {!isPlaying && ( + + )} + +
+
+ + + {translate({ + message: "HOME.FirstScreen.cta.secondary", + })} + +
diff --git a/src/components/HomepageFirstScreen/styles.module.scss b/src/components/HomepageFirstScreen/styles.module.scss index 3313944e..430c37da 100644 --- a/src/components/HomepageFirstScreen/styles.module.scss +++ b/src/components/HomepageFirstScreen/styles.module.scss @@ -3,7 +3,7 @@ .section { position: relative; overflow: clip; - padding: clamp(5.5rem, 9vw, 8rem) 0 clamp(3rem, 6vw, 5rem); + padding: clamp(4.75rem, 7.6vw, 6.6rem) 0 clamp(2.25rem, 4vw, 3.25rem); } .background { @@ -12,18 +12,18 @@ background: radial-gradient( circle at top left, - rgba(161, 191, 235, 0.22) 0%, - rgba(161, 191, 235, 0) 36% + rgba(161, 191, 235, 0.16) 0%, + rgba(161, 191, 235, 0) 34% ), radial-gradient( circle at 80% 18%, - rgba(127, 138, 231, 0.14) 0%, - rgba(127, 138, 231, 0) 28% + rgba(127, 138, 231, 0.08) 0%, + rgba(127, 138, 231, 0) 26% ), linear-gradient( 180deg, - rgba(251, 253, 255, 0.94) 0%, - rgba(244, 247, 251, 0.88) 100% + rgba(252, 253, 255, 0.96) 0%, + rgba(246, 248, 251, 0.9) 100% ); &::after { @@ -33,8 +33,9 @@ background: linear-gradient(rgba(92, 108, 141, 0.06) 1px, transparent 1px), linear-gradient(90deg, rgba(92, 108, 141, 0.06) 1px, transparent 1px); - background-size: 8.5rem 8.5rem; + background-size: 9.5rem 9.5rem; mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.75), transparent 90%); + opacity: 0.52; pointer-events: none; } } @@ -42,211 +43,335 @@ .container { position: relative; z-index: 1; - max-width: 1320px; + max-width: 1160px; margin: 0 auto; padding: 0 32px; display: grid; - grid-template-columns: minmax(0, 0.74fr) minmax(0, 1.06fr); - gap: clamp(1.75rem, 3.5vw, 3.75rem); - align-items: center; + gap: clamp(1.1rem, 2.2vw, 1.85rem); } -.header { +.titleGroup { display: grid; - gap: 1.25rem; - max-width: 35rem; - padding-top: clamp(0.4rem, 1vw, 1.2rem); -} - -.kicker { - display: inline-flex; - align-items: center; - width: fit-content; - gap: 0.75rem; - padding-left: 1rem; - font-size: 0.78rem; - font-weight: 700; - letter-spacing: 0.16em; - text-transform: uppercase; - color: var(--oomol-text-secondary); - border-left: 2px solid var(--oomol-primary); - position: relative; - - &::after { - content: ""; - width: 0.38rem; - height: 0.38rem; - border-radius: 999px; - background: color-mix(in srgb, var(--oomol-primary) 76%, white); - box-shadow: 0 0 0 5px - color-mix(in srgb, var(--oomol-primary-bg) 55%, transparent); - } + gap: 0.82rem; + max-width: 52rem; + margin: 0 auto; + justify-items: center; + text-align: center; } .slogan { margin: 0; - max-width: 11ch; + max-width: 22ch; font-family: var(--oomol-font-display); - font-size: clamp(3.4rem, 7vw, 6.4rem); - line-height: 0.96; + font-size: clamp(2.72rem, 4.7vw, 4.15rem); + line-height: 1; font-weight: 700; letter-spacing: -0.045em; - text-wrap: balance; + white-space: pre-line; + word-break: keep-all; + overflow-wrap: normal; color: var(--oomol-text-primary); } .overview { margin: 0; max-width: 40rem; - font-size: clamp(1.1rem, 1.4vw, 1.28rem); - line-height: 1.72; + font-size: clamp(1.12rem, 1.28vw, 1.24rem); + line-height: 1.64; color: var(--oomol-text-secondary); } -.highlight { +.ownershipNote { + margin: 0.18rem 0 0; + max-width: 48rem; + display: inline-flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.3rem; + padding: 0.7rem 1rem 0.76rem; + border-radius: 999px; + border: 1px solid color-mix(in srgb, var(--oomol-primary) 12%, white); + background: color-mix(in srgb, var(--oomol-primary-bg) 52%, white); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.72), + 0 10px 24px rgba(124, 138, 190, 0.08); + font-size: clamp(1rem, 1.08vw, 1.08rem); + line-height: 1.55; + color: color-mix(in srgb, var(--oomol-text-secondary) 88%, white 12%); +} + +.ownershipHighlight { + font-weight: 700; color: var(--oomol-primary-text); - font-weight: 650; } -.buttons { - margin-top: 0.65rem; +.mediaStack { + display: grid; + gap: clamp(0.78rem, 1.45vw, 1rem); + max-width: 1040px; + width: 100%; + margin: 0 auto; +} + +.actions { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 0.85rem; } -.screenshotFrame { - padding: 0.9rem; - border: 1px solid color-mix(in srgb, var(--oomol-border-default) 82%, white); - border-radius: 2rem; +.secondaryCta { + align-self: center; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.875rem; + padding: 0 1rem; + border-radius: 999px; + border: 1px solid color-mix(in srgb, var(--oomol-border-default) 86%, white); + background: color-mix( + in srgb, + var(--ifm-background-surface-color) 88%, + white + ); + color: var(--oomol-text-primary); + font-size: 0.98rem; + font-weight: 600; + letter-spacing: 0.01em; + text-decoration: none; + box-shadow: 0 10px 24px rgba(105, 120, 159, 0.08); + transition: + transform 0.2s ease, + box-shadow 0.2s ease, + border-color 0.2s ease; + + &:hover { + transform: translateY(-1px); + text-decoration: none; + border-color: color-mix(in srgb, var(--oomol-primary) 28%, white); + box-shadow: 0 14px 28px rgba(105, 120, 159, 0.12); + } +} + +.videoFrame { + width: 100%; + overflow: clip; + border: 1px solid color-mix(in srgb, var(--oomol-border-default) 76%, white); + border-radius: 1.35rem; + background: color-mix( + in srgb, + var(--ifm-background-surface-color) 90%, + white + ); + box-shadow: 0 14px 30px rgba(101, 118, 163, 0.09); + position: relative; +} + +.playOverlay { + position: absolute; + inset: 3.1rem 0 0; + z-index: 2; + display: grid; + place-items: center; + gap: 0.85rem; background: linear-gradient( 180deg, - rgba(252, 254, 255, 0.94) 0%, - rgba(244, 247, 252, 0.92) 100% + rgba(250, 251, 255, 0.14) 0%, + rgba(246, 248, 252, 0.52) 48%, + rgba(241, 244, 249, 0.72) 100% ); - box-shadow: var(--oomol-shadow-lg); - position: relative; - margin-top: clamp(-0.25rem, 2vw, 1rem); + border: 0; + padding: 0; + cursor: pointer; + transition: background 0.2s ease; - &::before { - content: ""; - position: absolute; - inset: -1px; - border-radius: inherit; - padding: 1px; + &:hover { background: linear-gradient( - 135deg, - rgba(255, 255, 255, 0.84) 0%, - rgba(173, 188, 233, 0.22) 52%, - rgba(255, 255, 255, 0.32) 100% + 180deg, + rgba(250, 251, 255, 0.1) 0%, + rgba(243, 246, 251, 0.46) 48%, + rgba(238, 242, 248, 0.66) 100% ); - -webkit-mask: - linear-gradient(#fff 0 0) content-box, - linear-gradient(#fff 0 0); - -webkit-mask-composite: xor; - mask-composite: exclude; - pointer-events: none; } } -.product-screenshot { +.playButton { + width: 4.8rem; + height: 4.8rem; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + background: color-mix(in srgb, var(--oomol-primary) 86%, white); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.3), + 0 16px 32px rgba(78, 68, 133, 0.18); +} + +.playTriangle { + width: 0; + height: 0; + margin-left: 0.22rem; + border-top: 0.72rem solid transparent; + border-bottom: 0.72rem solid transparent; + border-left: 1.1rem solid var(--oomol-white); +} + +.playLabel { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.55rem 0.9rem; + border-radius: 999px; + background: rgba(255, 255, 255, 0.88); + color: var(--oomol-text-primary); + font-size: 0.96rem; + font-weight: 600; + letter-spacing: 0.01em; + box-shadow: 0 10px 20px rgba(112, 126, 169, 0.12); +} + +.videoChrome { + display: flex; + align-items: center; + gap: 0.42rem; + padding: 0.72rem 0.92rem; + border-bottom: 1px solid + color-mix(in srgb, var(--oomol-border-default) 72%, white); + background: color-mix( + in srgb, + var(--ifm-background-surface-color) 92%, + white + ); + + span { + width: 0.56rem; + height: 0.56rem; + border-radius: 999px; + background: color-mix(in srgb, var(--oomol-text-secondary) 24%, white); + } +} + +.heroVideo { width: 100%; - height: auto; + aspect-ratio: 16 / 9; display: block; - border-radius: 1.15rem; - border: 1px solid color-mix(in srgb, var(--oomol-border-default) 72%, white); + object-fit: cover; background: var(--ifm-background-surface-color); } :global(html[lang="en"]) .container { - max-width: 1360px; - grid-template-columns: minmax(0, 0.88fr) minmax(0, 0.92fr); - gap: clamp(2.25rem, 4vw, 4.5rem); + max-width: 1200px; } -:global(html[lang="en"]) .header { - max-width: 38rem; - gap: 1.35rem; +:global(html[lang="en"]) .titleGroup { + gap: 0.82rem; + max-width: 56rem; } :global(html[lang="en"]) .slogan { - max-width: 15ch; - font-size: clamp(2.85rem, 5.4vw, 5.35rem); - line-height: 0.98; + max-width: 14ch; + font-size: clamp(2.55rem, 4.2vw, 3.95rem); + line-height: 1.02; letter-spacing: -0.038em; text-wrap: pretty; } :global(html[lang="en"]) .overview { - max-width: 43rem; - line-height: 1.78; + max-width: 35rem; + font-size: clamp(1.04rem, 1.16vw, 1.18rem); + line-height: 1.66; +} + +:global(html[lang="en"]) .ownershipNote { + max-width: 42rem; + font-size: clamp(0.96rem, 0.98vw, 1.02rem); } @media (max-width: 996px) { .container { - grid-template-columns: 1fr; + gap: clamp(1.35rem, 3vw, 1.9rem); } :global(html[lang="en"]) .container { - grid-template-columns: 1fr; - gap: clamp(1.75rem, 4vw, 2.5rem); + gap: clamp(1.35rem, 3vw, 1.9rem); } .section { - padding-top: 5rem; + padding-top: 4.5rem; } .container { padding: 0 24px; } - .header { + .slogan { max-width: 100%; - padding-top: 0; } - .slogan { + .overview { max-width: 100%; } - .screenshotFrame { - margin-top: 0; + .mediaStack { + max-width: 100%; } } @media (max-width: 768px) { .section { - padding: 4rem 0 2.6rem; + padding: 3.8rem 0 2.35rem; } .container { padding: 0 20px; } - :global(html[lang="en"]) .container { - grid-template-columns: 1fr; - } - .slogan { - font-size: clamp(2.8rem, 12vw, 4rem); - line-height: 1.04; + font-size: clamp(2.18rem, 8.5vw, 3rem); + line-height: 1.03; letter-spacing: -0.03em; - text-wrap: pretty; + max-width: 100%; } - .header { - gap: 1rem; + .titleGroup { + gap: 0.62rem; } .overview { font-size: 1rem; - line-height: 1.64; + line-height: 1.6; + } + + .ownershipNote { + max-width: 100%; + border-radius: 1rem; + padding: 0.78rem 0.95rem 0.82rem; + font-size: 0.95rem; + line-height: 1.58; } - .buttons { - margin-top: 0.3rem; + .videoFrame { + border-radius: 1.08rem; } - .screenshotFrame { - padding: 0.72rem; - border-radius: 1.2rem; + .playOverlay { + gap: 0.7rem; + } + + .playButton { + width: 4rem; + height: 4rem; + } + + .playLabel { + font-size: 0.9rem; + } + + .videoChrome { + padding: 0.64rem 0.8rem; } } @@ -259,12 +384,12 @@ background: radial-gradient( circle at top left, - rgba(155, 146, 208, 0.2) 0%, + rgba(155, 146, 208, 0.16) 0%, rgba(155, 146, 208, 0) 38% ), radial-gradient( circle at 80% 18%, - rgba(132, 138, 208, 0.16) 0%, + rgba(132, 138, 208, 0.1) 0%, rgba(132, 138, 208, 0) 26% ), linear-gradient( @@ -286,24 +411,36 @@ linear-gradient(90deg, rgba(204, 196, 223, 0.07) 1px, transparent 1px); } - .kicker { - color: color-mix(in srgb, var(--oomol-text-secondary) 88%, white 12%); - } - .overview { color: color-mix(in srgb, var(--oomol-text-secondary) 92%, white 8%); } - .screenshotFrame { - background: linear-gradient( - 180deg, - color-mix( - in srgb, - var(--oomol-bg-elevated) 72%, - var(--oomol-bg-container) 28% - ) - 0%, - color-mix(in srgb, var(--oomol-bg-container) 84%, black 16%) 100% + .ownershipNote { + border-color: color-mix( + in srgb, + var(--oomol-primary) 18%, + var(--oomol-border-default) + ); + background: color-mix( + in srgb, + var(--oomol-bg-elevated) 74%, + var(--oomol-primary-bg) 26% + ); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.06), + 0 12px 28px rgba(0, 0, 0, 0.12); + color: color-mix(in srgb, var(--oomol-text-secondary) 90%, white 10%); + } + + .ownershipHighlight { + color: color-mix(in srgb, var(--oomol-primary-text) 86%, white 14%); + } + + .videoFrame { + background: color-mix( + in srgb, + var(--oomol-bg-elevated) 80%, + var(--oomol-bg-container) 20% ); border-color: color-mix( in srgb, @@ -311,20 +448,48 @@ var(--oomol-divider) ); box-shadow: - 0 24px 56px rgba(0, 0, 0, 0.22), - 0 10px 24px rgba(0, 0, 0, 0.14); + 0 20px 42px rgba(0, 0, 0, 0.16), + 0 8px 18px rgba(0, 0, 0, 0.1); + } - &::before { + .playOverlay { + background: linear-gradient( + 180deg, + rgba(17, 18, 28, 0.08) 0%, + rgba(19, 21, 31, 0.34) 54%, + rgba(18, 20, 30, 0.48) 100% + ); + + &:hover { background: linear-gradient( - 135deg, - rgba(214, 205, 236, 0.2) 0%, - rgba(132, 138, 208, 0.28) 46%, - rgba(214, 205, 236, 0.1) 100% + 180deg, + rgba(17, 18, 28, 0.06) 0%, + rgba(19, 21, 31, 0.28) 54%, + rgba(18, 20, 30, 0.42) 100% ); } } - .product-screenshot { - border-color: color-mix(in srgb, var(--oomol-border-default) 78%, black); + .playLabel { + background: rgba(23, 26, 38, 0.84); + color: color-mix(in srgb, var(--oomol-text-primary) 90%, white 10%); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.18); + } + + .videoChrome { + border-bottom-color: color-mix( + in srgb, + var(--oomol-border-default) 72%, + black + ); + background: color-mix( + in srgb, + var(--oomol-bg-container) 82%, + var(--oomol-bg-elevated) 18% + ); + } + + .videoChrome span { + background: color-mix(in srgb, var(--oomol-text-secondary) 30%, white); } } diff --git a/src/components/HomepageLinearFlow/index.tsx b/src/components/HomepageLinearFlow/index.tsx new file mode 100644 index 00000000..f45a5cfe --- /dev/null +++ b/src/components/HomepageLinearFlow/index.tsx @@ -0,0 +1,452 @@ +import styles from "./styles.module.scss"; + +import type { DocusaurusContext } from "@docusaurus/types"; +import Link from "@docusaurus/Link"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import { DownloadButton } from "@site/src/components/DownloadButton"; +import ThemedImage from "@theme/ThemedImage"; +import { clsx } from "clsx"; +import React from "react"; + +type Copy = { + cli: { + eyebrow: string; + title: string; + description: string; + bullets: string[]; + commandsLabel: string; + commands: string[]; + guide: string; + github: string; + }; + studio: { + eyebrow: string; + title: string; + description: string; + points: Array<{ title: string; text: string }>; + primary: string; + secondary: string; + }; + cloud: { + eyebrow: string; + title: string; + description: string; + cards: Array<{ label: string; title: string; text: string }>; + primary: string; + secondary: string; + }; + agent: { + eyebrow: string; + title: string; + description: string; + cards: Array<{ title: string; text: string }>; + primary: string; + secondary: string; + }; + cta: { + title: string; + description: string; + primary: string; + secondary: string; + }; +}; + +const zhCopy: Copy = { + cli: { + eyebrow: "02 / oo-cli", + title: "先安装 oo-cli,三步就能把 Skill 用起来", + description: + "oo-cli 是最直接的消费入口。先搜索,再查看,再运行,不用先理解整套系统,也不用先接 API 或 MCP。", + bullets: [ + "安装一次,就能在终端和 Agent 工作流里直接使用 Skill。", + "搜索、查看、运行都在一个入口里完成,路径很短。", + "先把体验跑通,再决定是否要做自己的 Skill。", + ], + commandsLabel: "典型使用流程", + commands: [ + "bun install -g @oomol-lab/oo-cli", + "oo login", + 'oo search \"social media optimizer\"', + "oo package info foo/bar@latest", + "oo cloud-task run foo/bar@1.2.3 --block-id main", + ], + guide: "查看 oo-cli 指南", + github: "查看 GitHub", + }, + studio: { + eyebrow: "03 / OOMOL Studio", + title: "想做自己的 Skill,就装 OOMOL Studio", + description: + "直接告诉 Agent 你要生成什么,Studio 帮你把 Skill 生成出来,然后在本地完成验证。不会写平台 DSL,也能零门槛开始。", + points: [ + { + title: "Describe", + text: "告诉 Agent 你想做什么,不必先画完整流程。", + }, + { + title: "Generate", + text: "让 Studio 生成 Skill 的实现、参数和基本结构。", + }, + { + title: "Validate", + text: "在本地把依赖、输入输出和运行结果先跑通。", + }, + ], + primary: "安装 OOMOL Studio", + secondary: "了解 Studio", + }, + cloud: { + eyebrow: "04 / Cloud", + title: "发布之后,Cloud 负责运行、订阅和管理", + description: + "Skill 做好以后,Cloud 在后台承接运行,并提供订阅方式、配置入口和数据面板。开发者不必再围着同一份实现重做一层产品外壳。", + cards: [ + { + label: "订阅", + title: "把 Skill 交付给自己、团队或客户", + text: "Cloud 在后台承接订阅关系,让一个 Skill 可以持续交付,而不是只停留在本地脚本。", + }, + { + label: "配置", + title: "把权限、参数和运行环境放在后台配置", + text: "运行参数、访问控制、Secrets 和发布配置都留在 Cloud 里统一管理。", + }, + { + label: "数据", + title: "查看调用情况、运行状态和使用趋势", + text: "你可以看到 Skill 的使用和运行数据,而不只是单次调用结果。", + }, + ], + primary: "了解 Cloud", + secondary: "打开 Cloud 控制台", + }, + agent: { + eyebrow: "05 / OOMOL AI", + title: "不想用 CLI,就直接用 OOMOL AI 官方 Agent", + description: + "它可以理解成 oo-cli 的 GUI 版本。同一套 Skill,不同的消费入口。终端适合工作流,GUI 更适合直观使用。", + cards: [ + { + title: "对话入口", + text: "当用户意图还不够明确时,通过对话选择并调用 Skill。", + }, + { + title: "参数入口", + text: "当输入明确时,用结构化界面直接运行同一个 Skill。", + }, + ], + primary: "体验 OOMOL AI", + secondary: "了解 OOMOL AI", + }, + cta: { + title: "先用一个 Skill,再决定要不要自己做", + description: + "先通过 oo-cli 把使用路径跑通。需要自己的 Skill 时,再安装 Studio 生成、验证并发布。", + primary: "安装 OOMOL Studio", + secondary: "先用 oo-cli", + }, +}; + +const enCopy: Copy = { + cli: { + eyebrow: "02 / oo-cli", + title: "Install oo-cli first and get a skill running in three steps", + description: + "oo-cli is the simplest entry point. Search, inspect, and run without learning the whole system first or wiring API and MCP on day one.", + bullets: [ + "Install once and use skills directly from terminal and agent workflows.", + "Search, inspect, and run all happen in one short path.", + "Start with the experience first, then decide whether to build your own skill.", + ], + commandsLabel: "Typical flow", + commands: [ + "bun install -g @oomol-lab/oo-cli", + "oo login", + 'oo search \"social media optimizer\"', + "oo package info foo/bar@latest", + "oo cloud-task run foo/bar@1.2.3 --block-id main", + ], + guide: "Open oo-cli Guide", + github: "View GitHub", + }, + studio: { + eyebrow: "03 / OOMOL Studio", + title: "When you need your own skill, install OOMOL Studio", + description: + "Tell the agent what you want to build, let Studio generate the skill, then validate it locally. No platform DSL or steep setup before you begin.", + points: [ + { + title: "Describe", + text: "Tell the agent what you want instead of designing the whole flow first.", + }, + { + title: "Generate", + text: "Let Studio generate the implementation, parameters, and structure.", + }, + { + title: "Validate", + text: "Run dependencies, inputs, outputs, and results locally before release.", + }, + ], + primary: "Install OOMOL Studio", + secondary: "Explore Studio", + }, + cloud: { + eyebrow: "04 / Cloud", + title: "After release, Cloud handles runtime, subscriptions, and management", + description: + "Once a skill is ready, Cloud takes over the runtime and gives you subscription paths, configuration controls, and usage data without rebuilding another product shell around the same implementation.", + cards: [ + { + label: "Subscriptions", + title: "Deliver the skill to yourself, your team, or customers", + text: "Cloud carries the subscription relationship so a skill can be operated continuously instead of staying as a local script.", + }, + { + label: "Configuration", + title: "Keep access, parameters, and runtime setup in the backend", + text: "Runtime settings, access control, secrets, and release configuration stay managed in one place.", + }, + { + label: "Data", + title: "See runs, status, and usage trends", + text: "You get operational visibility into the skill instead of only seeing one-off invocation results.", + }, + ], + primary: "Explore Cloud", + secondary: "Open Cloud Console", + }, + agent: { + eyebrow: "05 / OOMOL AI", + title: "If you do not want CLI, use the official OOMOL AI agent", + description: + "Think of it as the GUI version of oo-cli. The same skill, a different consumption surface. Terminal is for workflows; GUI is for direct use.", + cards: [ + { + title: "Chat Surface", + text: "Use conversation when intent is still fuzzy and the skill should be selected dynamically.", + }, + { + title: "Structured Surface", + text: "Use a parameterized interface when inputs are clear and execution should be direct.", + }, + ], + primary: "Try OOMOL AI", + secondary: "Explore OOMOL AI", + }, + cta: { + title: "Use one skill first, then decide whether to build your own", + description: + "Start by getting the usage path working in oo-cli. When you need your own skill, install Studio to generate, validate, and publish it.", + primary: "Install OOMOL Studio", + secondary: "Start with oo-cli", + }, +}; + +export default function HomepageLinearFlow() { + const { i18n } = useDocusaurusContext() as unknown as DocusaurusContext & { + i18n: { currentLocale: string }; + }; + const copy = i18n.currentLocale === "zh-CN" ? zhCopy : enCopy; + const studioLight = useBaseUrl("/img/pages/studio/studio-light.png"); + const studioDark = useBaseUrl("/img/pages/studio/studio-dark.png"); + const cloudLight = useBaseUrl("/img/pages/cloud/publish-light.png"); + const cloudDark = useBaseUrl("/img/pages/cloud/publish-dark.png"); + const chatLight = useBaseUrl("/img/pages/app/chat-light.png"); + const chatDark = useBaseUrl("/img/pages/app/chat-dark.png"); + const appletLight = useBaseUrl("/img/pages/app/applet-light.png"); + const appletDark = useBaseUrl("/img/pages/app/applet-dark.png"); + + return ( +
+
+
+
+ {copy.cli.eyebrow} +

{copy.cli.title}

+

{copy.cli.description}

+
+ {copy.cli.bullets.map(item => ( +

+ {item} +

+ ))} +
+
+ + {copy.cli.guide} + + + {copy.cli.github} + +
+
+ +
+
+ + + +
+
+
{copy.cli.commandsLabel}
+
+                
+                  {copy.cli.commands.map(command => (
+                    
+                      $ {command}
+                    
+                  ))}
+                
+              
+
+
+
+
+ +
+
+
+ +
+ +
+ {copy.studio.eyebrow} +

{copy.studio.title}

+

+ {copy.studio.description} +

+
+ {copy.studio.points.map(point => ( +
+
{point.title}
+

{point.text}

+
+ ))} +
+
+ + {copy.studio.primary} + + + {copy.studio.secondary} + +
+
+
+
+ +
+
+
+ {copy.cloud.eyebrow} +

{copy.cloud.title}

+

{copy.cloud.description}

+
+ {copy.cloud.cards.map(card => ( +
+
{card.label}
+

{card.title}

+

{card.text}

+
+ ))} +
+
+ + {copy.cloud.primary} + + + {copy.cloud.secondary} + +
+
+ +
+ +
+
+
+ +
+
+
+ {copy.agent.eyebrow} +

{copy.agent.title}

+

{copy.agent.description}

+
+ {copy.agent.cards.map(card => ( +
+
{card.title}
+

{card.text}

+
+ ))} +
+
+ + {copy.agent.primary} + + + {copy.agent.secondary} + +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ 06 / CTA +

{copy.cta.title}

+

{copy.cta.description}

+
+ + + {copy.cta.secondary} + +
+
+
+
+ ); +} diff --git a/src/components/HomepageLinearFlow/styles.module.scss b/src/components/HomepageLinearFlow/styles.module.scss new file mode 100644 index 00000000..8f659633 --- /dev/null +++ b/src/components/HomepageLinearFlow/styles.module.scss @@ -0,0 +1,436 @@ +@use "../../css/custom.scss" as *; + +.flow { + display: grid; +} + +.section { + padding: clamp(3.5rem, 7vw, 5.5rem) 0; +} + +.sectionTint { + background: + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-base) 92%, #d7c8af 8%) 0%, + color-mix(in srgb, var(--oomol-bg-base) 96%, white 4%) 100% + ); +} + +.agentSection { + background: + radial-gradient( + circle at top right, + rgba(188, 167, 122, 0.12) 0%, + rgba(188, 167, 122, 0) 28% + ), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-base) 96%, white 4%) 0%, + var(--oomol-bg-base) 100% + ); +} + +.container, +.ctaInner { + width: min(1260px, calc(100% - 48px)); + margin: 0 auto; +} + +.container { + display: grid; + grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr); + gap: clamp(1.6rem, 4vw, 3.2rem); + align-items: center; +} + +.copyPanel { + display: grid; + gap: 1rem; + align-content: start; +} + +.eyebrow { + display: inline-flex; + width: fit-content; + align-items: center; + gap: 0.75rem; + font-size: 0.76rem; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--oomol-text-secondary); + + &::before { + content: ""; + width: 0.8rem; + height: 1px; + background: var(--oomol-primary); + } +} + +.sectionTitle, +.ctaTitle { + margin: 0; + font-family: var(--oomol-font-display); + font-size: clamp(2.4rem, 4.8vw, 4.2rem); + line-height: 0.98; + letter-spacing: -0.045em; + color: var(--oomol-text-primary); +} + +.sectionDescription, +.ctaDescription { + margin: 0; + max-width: 42rem; + font-size: 1.02rem; + line-height: 1.76; + color: var(--oomol-text-secondary); +} + +.bulletList { + display: grid; + gap: 0.72rem; + padding-top: 0.25rem; +} + +.bullet { + margin: 0; + display: grid; + grid-template-columns: auto 1fr; + gap: 0.78rem; + align-items: start; + font-size: 0.98rem; + line-height: 1.72; + color: var(--oomol-text-secondary); + + &::before { + content: "—"; + color: var(--oomol-primary-text); + } +} + +.inlineActions, +.ctaActions { + display: flex; + flex-wrap: wrap; + gap: 0.85rem; + padding-top: 0.4rem; +} + +.primaryLink, +.secondaryLink, +.ctaGhost { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 2.95rem; + padding: 0 1rem; + border-radius: 999px; + font-size: 0.95rem; + font-weight: 650; + text-decoration: none; + transition: + transform 0.18s ease, + background-color 0.18s ease, + border-color 0.18s ease, + color 0.18s ease; + + &:hover { + transform: translateY(-1px); + text-decoration: none; + } +} + +.primaryLink { + color: var(--oomol-white); + border: 1px solid color-mix(in srgb, var(--oomol-primary-active) 64%, black 12%); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-primary) 80%, white 12%) 0%, + color-mix(in srgb, var(--oomol-primary-active) 88%, black 12%) 100% + ); +} + +.secondaryLink, +.ctaGhost { + color: var(--oomol-text-primary); + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); +} + +.terminalPanel, +.mediaPanel, +.agentMediaCard { + border-radius: 1.8rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%); + box-shadow: var(--oomol-shadow-lg); + overflow: hidden; +} + +.terminalPanel { + display: grid; +} + +.terminalChrome { + display: flex; + align-items: center; + gap: 0.45rem; + padding: 0.82rem 1rem; + border-bottom: 1px solid var(--oomol-divider); + + span { + width: 0.58rem; + height: 0.58rem; + border-radius: 999px; + background: color-mix(in srgb, var(--oomol-text-secondary) 26%, white); + } +} + +.terminalBody { + display: grid; + gap: 1rem; + padding: 1.2rem 1.3rem 1.35rem; +} + +.terminalLabel { + font-size: 0.82rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-text-tertiary); +} + +.commandBlock { + margin: 0; + padding: 0; + white-space: pre-wrap; + font-family: + ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Monaco, Consolas, + "Liberation Mono", monospace; + font-size: 0.92rem; + line-height: 1.8; + color: var(--oomol-text-primary); +} + +.commandLine { + display: block; +} + +.prompt { + color: var(--oomol-primary-text); +} + +.heroImage { + display: block; + width: 100%; + height: auto; +} + +.stepGrid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.9rem; +} + +.stepCard, +.cloudCard { + border-radius: 1.25rem; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%); +} + +.stepCard { + padding: 1rem 1rem 1.05rem; +} + +.stepTitle { + font-size: 0.86rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-primary-text); +} + +.stepText { + margin: 0.65rem 0 0; + font-size: 0.95rem; + line-height: 1.68; + color: var(--oomol-text-secondary); +} + +.cloudCardStack { + display: grid; + gap: 0.95rem; +} + +.cloudCard { + padding: 1rem 1rem 1.1rem; +} + +.cloudLabel { + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-text-tertiary); +} + +.cloudTitle { + margin: 0.45rem 0 0; + font-size: 1.08rem; + line-height: 1.35; + color: var(--oomol-text-primary); +} + +.cloudText { + margin: 0.55rem 0 0; + font-size: 0.95rem; + line-height: 1.7; + color: var(--oomol-text-secondary); +} + +.dualMedia { + display: grid; + gap: 1rem; +} + +.ctaSection { + padding: clamp(4rem, 8vw, 5.8rem) 0 clamp(3rem, 6vw, 4.4rem); +} + +.ctaInner { + display: grid; + gap: 1rem; + padding: clamp(1.9rem, 4vw, 2.8rem); + border-radius: 2rem; + border: 1px solid rgba(214, 221, 236, 0.12); + background: + radial-gradient( + circle at top left, + rgba(132, 138, 208, 0.18) 0%, + rgba(132, 138, 208, 0) 32% + ), + linear-gradient(180deg, #1a1b28 0%, #12131d 100%); + box-shadow: var(--oomol-shadow-lg); +} + +.ctaTitle { + max-width: 14ch; + color: rgba(243, 239, 248, 0.98); +} + +.ctaDescription { + max-width: 42rem; + color: rgba(221, 214, 231, 0.8); +} + +.ctaGhost { + color: rgba(243, 239, 248, 0.94); + border-color: rgba(243, 239, 248, 0.14); + background: rgba(243, 239, 248, 0.08); +} + +:global(html[lang="en"]) .sectionTitle, +:global(html[lang="en"]) .ctaTitle { + max-width: 16ch; + font-size: clamp(2.1rem, 4vw, 3.45rem); + line-height: 1.02; +} + +@media (max-width: 996px) { + .container { + grid-template-columns: 1fr; + } + + .stepGrid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 768px) { + .container, + .ctaInner { + width: min(100%, calc(100% - 40px)); + } + + .section { + padding: 3rem 0; + } + + .sectionTitle, + .ctaTitle { + max-width: 100%; + text-wrap: pretty; + } + + .sectionDescription, + .ctaDescription { + font-size: 0.98rem; + line-height: 1.7; + } +} + +[data-theme="dark"] { + .sectionTint { + background: + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-base) 90%, #41372d 10%) 0%, + color-mix(in srgb, var(--oomol-bg-base) 96%, black 4%) 100% + ); + } + + .agentSection { + background: + radial-gradient( + circle at top right, + rgba(188, 167, 122, 0.08) 0%, + rgba(188, 167, 122, 0) 28% + ), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-base) 96%, black 4%) 0%, + var(--oomol-bg-base) 100% + ); + } + + .secondaryLink, + .ctaGhost, + .stepCard, + .cloudCard, + .terminalPanel, + .mediaPanel, + .agentMediaCard { + background: color-mix( + in srgb, + var(--oomol-bg-elevated) 86%, + var(--oomol-bg-container) 14% + ); + } + + .ctaInner { + border-color: color-mix( + in srgb, + var(--oomol-primary-border) 44%, + var(--oomol-divider) + ); + background: + radial-gradient( + circle at top left, + rgba(132, 138, 208, 0.16) 0%, + rgba(132, 138, 208, 0) 34% + ), + linear-gradient( + 180deg, + color-mix( + in srgb, + var(--oomol-bg-container) 82%, + var(--oomol-bg-spotlight) 18% + ) + 0%, + color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 100% + ); + } +} diff --git a/src/pages/app/index.tsx b/src/pages/app/index.tsx index 90d7e3ae..f29f2f6b 100644 --- a/src/pages/app/index.tsx +++ b/src/pages/app/index.tsx @@ -14,19 +14,22 @@ export default function AppPage() { {/* Hero Section */}

- {translate({ id: "APP.new.hero.title", message: "OOMOL App" })} + {translate({ + id: "APP.new.hero.title", + message: "OOMOL App Surfaces", + })}

{translate({ id: "APP.new.hero.subtitle", - message: "Direct Product Surfaces for Your Functions", + message: "Product surfaces for cloud skills", })}

{translate({ id: "APP.new.hero.description", message: - "Turn function capabilities directly into Chat skills or Applet entry points, without building separate UI from scratch.", + "A single cloud skill can be delivered through chat or structured applets, without building separate product surfaces from scratch.", })}

@@ -57,14 +60,14 @@ export default function AppPage() {

{translate({ id: "APP.new.concept.title", - message: "Code is Product", + message: "One skill, different surfaces", })}

{translate({ id: "APP.new.concept.description", message: - "OOMOL wraps function capabilities into usable product surfaces. You focus on the function; we connect it to the user.", + "OOMOL turns the same cloud skill into usable entry points. You focus on the implementation; we connect it to the user.", })}

@@ -77,7 +80,7 @@ export default function AppPage() { {translate({ id: "APP.new.chat.pill", - message: "Chat · Workflow Copilot", + message: "Chat Surface · Skill", })} @@ -97,7 +100,7 @@ export default function AppPage() { {translate({ id: "APP.new.chat.description", message: - "When user intent is still vague, let AI choose and call your function capabilities through conversation.", + "When user intent is still vague, let AI choose and run the right cloud skill through conversation.", })}

@@ -112,7 +115,7 @@ export default function AppPage() { {translate({ id: "APP.new.chat.meta1.value", message: - "Best when capabilities need to be exposed through conversation and intent needs clarification first", + "Best when a cloud skill should be used through conversation and intent needs clarification first", })}
@@ -127,7 +130,7 @@ export default function AppPage() { {translate({ id: "APP.new.chat.meta2.value", message: - "Understand intent first, then call the right service with less user setup", + "Understand intent first, then call the right cloud skill with less setup", })}
@@ -136,7 +139,7 @@ export default function AppPage() { {translate({ id: "APP.new.chat.devValue", message: - "Functions as Skills: your functions become AI-callable capabilities.", + "Cloud skill as agent tool: the same implementation becomes an AI-callable surface.", })}

@@ -161,7 +164,7 @@ export default function AppPage() { {translate({ id: "APP.new.applet.pill", - message: "Parameterized Surface · Applet", + message: "Structured Surface · Applet", })} @@ -181,7 +184,7 @@ export default function AppPage() { {translate({ id: "APP.new.applet.description", message: - "When inputs are clear, call the function directly through structured parameters for more reliable delivery.", + "When inputs are clear, run the same cloud skill through structured parameters for more reliable delivery.", })}

@@ -196,7 +199,7 @@ export default function AppPage() { {translate({ id: "APP.new.applet.meta1.value", message: - "Best for teams delivering fixed-input function capabilities to internal or external users", + "Best for teams delivering fixed-input cloud skills to internal or external users", })}
@@ -211,7 +214,7 @@ export default function AppPage() { {translate({ id: "APP.new.applet.meta2.value", message: - "Wrap a function as a fillable, executable, and reusable product entry point", + "Wrap the same cloud skill as a fillable, executable, and reusable entry point", })} @@ -220,7 +223,7 @@ export default function AppPage() { {translate({ id: "APP.new.applet.devValue", message: - "Function as App: auto-generated parameter UI with less frontend boilerplate.", + "Cloud skill as app: auto-generated parameter UI with less frontend boilerplate.", })}

diff --git a/src/pages/cloud/index.tsx b/src/pages/cloud/index.tsx index 24c39118..12159cb9 100644 --- a/src/pages/cloud/index.tsx +++ b/src/pages/cloud/index.tsx @@ -73,6 +73,9 @@ export default function CloudPage() {

{translate({ message: "CLOUD.hero.description" })}

+

+ {translate({ message: "CLOUD.hero.note" })} +

@@ -138,6 +141,25 @@ export default function CloudPage() {
+
+
+
+
+ {translate({ message: "CLOUD.pricing.kicker" })} +
+

+ {translate({ message: "CLOUD.pricing.title" })} +

+

+ {translate({ message: "CLOUD.pricing.description" })} +

+ + {translate({ message: "CLOUD.pricing.cta" })} + +
+
+
+
@@ -168,25 +190,6 @@ export default function CloudPage() {
-
-
-
-
- {translate({ message: "CLOUD.pricing.kicker" })} -
-

- {translate({ message: "CLOUD.pricing.title" })} -

-

- {translate({ message: "CLOUD.pricing.description" })} -

- - {translate({ message: "CLOUD.pricing.cta" })} - -
-
-
-
diff --git a/src/pages/cloud/styles.module.scss b/src/pages/cloud/styles.module.scss index 99a585d6..b0bd6808 100644 --- a/src/pages/cloud/styles.module.scss +++ b/src/pages/cloud/styles.module.scss @@ -86,6 +86,18 @@ font-size: 1.08rem; } +.heroNote { + margin: -0.2rem 0 0; + max-width: 38rem; + padding: 0.95rem 1rem; + border-radius: 1rem; + border: 1px solid color-mix(in srgb, var(--oomol-primary) 16%, white); + background: color-mix(in srgb, var(--oomol-primary-bg) 54%, white); + font-size: 0.98rem; + line-height: 1.68; + color: color-mix(in srgb, var(--oomol-text-secondary) 90%, white 10%); +} + .stats { display: flex; flex-wrap: wrap; @@ -354,3 +366,19 @@ text-wrap: pretty; } } + +[data-theme="dark"] { + .heroNote { + border-color: color-mix( + in srgb, + var(--oomol-primary) 22%, + var(--oomol-divider) + ); + background: color-mix( + in srgb, + var(--oomol-bg-elevated) 78%, + var(--oomol-primary-bg) 22% + ); + color: color-mix(in srgb, var(--oomol-text-secondary) 92%, white 8%); + } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index bdcadd1c..d062bdf2 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,13 +1,9 @@ import Head from "@docusaurus/Head"; import { translate } from "@docusaurus/Translate"; -import HomepageCliEntry from "@site/src/components/HomepageCliEntry"; -import HomepageCodexBlocks from "@site/src/components/HomepageCodexBlocks"; import HomepageFirstScreen from "@site/src/components/HomepageFirstScreen"; -import HomepageProductComparison from "@site/src/components/HomepageProductComparison"; -import StudioDetailContent from "@site/src/components/StudioDetailContent"; +import HomepageLinearFlow from "@site/src/components/HomepageLinearFlow"; import React from "react"; -import { GetStartedPrompt } from "../components/GetStartedPrompt"; import Layout from "../theme/Layout"; export default function Home() { @@ -22,11 +18,7 @@ export default function Home() {
- - - - - +
); From 57e6372c3a0706859a31bcdfd6dac273d99aea6a Mon Sep 17 00:00:00 2001 From: shaun Date: Sat, 28 Mar 2026 17:20:36 +0800 Subject: [PATCH 03/15] update --- i18n/en/code.json | 6 +- src/components/DownloadButton/index.tsx | 38 +-- src/components/HomepageLinearFlow/index.tsx | 249 +++++++++++------- .../HomepageLinearFlow/styles.module.scss | 136 +++++++--- 4 files changed, 276 insertions(+), 153 deletions(-) diff --git a/i18n/en/code.json b/i18n/en/code.json index fa882558..638c8362 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -39,19 +39,19 @@ "message": "Start with ready-made capabilities in oo-cli, create your own blocks in OOMOL Studio, then deploy and deliver them privately through Cloud." }, "HOME.FirstScreen.heroTitle": { - "message": "Let agents use your skill while you keep full control of the code" + "message": "Let agents use your skill while you stay in control of the code" }, "HOME.FirstScreen.heroSubtitle": { "message": "We call this a cloud skill: a capability that runs in the cloud and can be used directly from terminals and agent workflows." }, "HOME.FirstScreen.heroLead": { - "message": "A cloud skill is a capability that runs in the cloud, stays reusable, and can be used directly from terminals and agent workflows." + "message": "A cloud skill runs in the cloud, stays reusable, and can be used directly from terminals and agent workflows." }, "HOME.FirstScreen.heroAdvantage": { "message": "Open source or closed source," }, "HOME.FirstScreen.heroAdvantageHighlight": { - "message": "the decision stays yours." + "message": "it is your call." }, "HOME.FirstScreen.pill1": { "message": "No new DSL" diff --git a/src/components/DownloadButton/index.tsx b/src/components/DownloadButton/index.tsx index 21aa33f0..7d53fad6 100644 --- a/src/components/DownloadButton/index.tsx +++ b/src/components/DownloadButton/index.tsx @@ -28,11 +28,13 @@ function detectOSAndArchitecture(): OS { export interface DownloadButtonProps { stableTag?: boolean; centered?: boolean; + showNote?: boolean; } export const DownloadButton = ({ stableTag, centered, + showNote = true, }: DownloadButtonProps) => { const downloadIcon = (
} > @@ -87,11 +91,13 @@ export const DownloadButton = ({ })} - - {translate({ - message: "HOME.FirstScreen.download-macos-chip-note", - })} - + {showNote ? ( + + {translate({ + message: "HOME.FirstScreen.download-macos-chip-note", + })} + + ) : null}
) : (
@@ -111,11 +117,13 @@ export const DownloadButton = ({ })} - - {translate({ - message: "HOME.FirstScreen.download-windows-subtitle", - })} - + {showNote ? ( + + {translate({ + message: "HOME.FirstScreen.download-windows-subtitle", + })} + + ) : null}
)}
diff --git a/src/components/HomepageLinearFlow/index.tsx b/src/components/HomepageLinearFlow/index.tsx index f45a5cfe..b219fb28 100644 --- a/src/components/HomepageLinearFlow/index.tsx +++ b/src/components/HomepageLinearFlow/index.tsx @@ -3,9 +3,7 @@ import styles from "./styles.module.scss"; import type { DocusaurusContext } from "@docusaurus/types"; import Link from "@docusaurus/Link"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import useBaseUrl from "@docusaurus/useBaseUrl"; import { DownloadButton } from "@site/src/components/DownloadButton"; -import ThemedImage from "@theme/ThemedImage"; import { clsx } from "clsx"; import React from "react"; @@ -13,10 +11,9 @@ type Copy = { cli: { eyebrow: string; title: string; - description: string; - bullets: string[]; commandsLabel: string; - commands: string[]; + commands: Array<{ comment: string; command: string }>; + media: { label: string; title: string; note: string }; guide: string; github: string; }; @@ -25,6 +22,7 @@ type Copy = { title: string; description: string; points: Array<{ title: string; text: string }>; + media: { label: string; title: string; note: string }; primary: string; secondary: string; }; @@ -33,6 +31,7 @@ type Copy = { title: string; description: string; cards: Array<{ label: string; title: string; text: string }>; + media: { label: string; title: string; note: string }; primary: string; secondary: string; }; @@ -41,6 +40,7 @@ type Copy = { title: string; description: string; cards: Array<{ title: string; text: string }>; + media: { label: string; title: string; note: string }; primary: string; secondary: string; }; @@ -55,28 +55,41 @@ type Copy = { const zhCopy: Copy = { cli: { eyebrow: "02 / oo-cli", - title: "先安装 oo-cli,三步就能把 Skill 用起来", - description: - "oo-cli 是最直接的消费入口。先搜索,再查看,再运行,不用先理解整套系统,也不用先接 API 或 MCP。", - bullets: [ - "安装一次,就能在终端和 Agent 工作流里直接使用 Skill。", - "搜索、查看、运行都在一个入口里完成,路径很短。", - "先把体验跑通,再决定是否要做自己的 Skill。", - ], - commandsLabel: "典型使用流程", + title: "先在 Codex 里装 oo-cli,直接开始用 Skill", + commandsLabel: "以 Codex 为例", commands: [ - "bun install -g @oomol-lab/oo-cli", - "oo login", - 'oo search \"social media optimizer\"', - "oo package info foo/bar@latest", - "oo cloud-task run foo/bar@1.2.3 --block-id main", + { + comment: "先在 Codex 里装好 oo-cli", + command: "bun install -g @oomol-lab/oo-cli", + }, + { + comment: "登录之后,就能直接搜索和运行 Skill", + command: "oo login", + }, + { + comment: "先用自然语言搜索一个 Skill", + command: 'oo search "social media optimizer"', + }, + { + comment: "查看它做什么、需要什么输入", + command: "oo package info foo/bar@latest", + }, + { + comment: "最后直接运行", + command: "oo cloud-task run foo/bar@1.2.3 --block-id main", + }, ], + media: { + label: "演示占位", + title: "这里放 Codex 演示视频", + note: "建议后续替换成一段在 Codex 中安装、搜索、查看并运行 Skill 的短视频。", + }, guide: "查看 oo-cli 指南", github: "查看 GitHub", }, studio: { eyebrow: "03 / OOMOL Studio", - title: "想做自己的 Skill,就装 OOMOL Studio", + title: "想做自己的 Skill,就用 OOMOL Studio", description: "直接告诉 Agent 你要生成什么,Studio 帮你把 Skill 生成出来,然后在本地完成验证。不会写平台 DSL,也能零门槛开始。", points: [ @@ -93,12 +106,17 @@ const zhCopy: Copy = { text: "在本地把依赖、输入输出和运行结果先跑通。", }, ], + media: { + label: "演示占位", + title: "这里放 Studio + Agent Vibe 生成 Skill 的视频", + note: "建议后续替换成一段从提需求到本地验证跑通的短视频。", + }, primary: "安装 OOMOL Studio", secondary: "了解 Studio", }, cloud: { eyebrow: "04 / Cloud", - title: "发布之后,Cloud 负责运行、订阅和管理", + title: "发布之后,Cloud 负责运行和管理", description: "Skill 做好以后,Cloud 在后台承接运行,并提供订阅方式、配置入口和数据面板。开发者不必再围着同一份实现重做一层产品外壳。", cards: [ @@ -118,12 +136,17 @@ const zhCopy: Copy = { text: "你可以看到 Skill 的使用和运行数据,而不只是单次调用结果。", }, ], + media: { + label: "演示占位", + title: "这里放 Cloud 后台订阅、配置和数据面板的视频", + note: "建议后续替换成一段发布后如何查看订阅、配置和运行数据的短视频。", + }, primary: "了解 Cloud", secondary: "打开 Cloud 控制台", }, agent: { eyebrow: "05 / OOMOL AI", - title: "不想用 CLI,就直接用 OOMOL AI 官方 Agent", + title: "不想用 CLI,就直接用 OOMOL AI", description: "它可以理解成 oo-cli 的 GUI 版本。同一套 Skill,不同的消费入口。终端适合工作流,GUI 更适合直观使用。", cards: [ @@ -136,6 +159,11 @@ const zhCopy: Copy = { text: "当输入明确时,用结构化界面直接运行同一个 Skill。", }, ], + media: { + label: "演示占位", + title: "这里放 OOMOL AI 官方 Agent 的演示视频", + note: "建议后续替换成一段同时体现对话入口和参数入口体验的短视频。", + }, primary: "体验 OOMOL AI", secondary: "了解 OOMOL AI", }, @@ -151,30 +179,43 @@ const zhCopy: Copy = { const enCopy: Copy = { cli: { eyebrow: "02 / oo-cli", - title: "Install oo-cli first and get a skill running in three steps", - description: - "oo-cli is the simplest entry point. Search, inspect, and run without learning the whole system first or wiring API and MCP on day one.", - bullets: [ - "Install once and use skills directly from terminal and agent workflows.", - "Search, inspect, and run all happen in one short path.", - "Start with the experience first, then decide whether to build your own skill.", - ], - commandsLabel: "Typical flow", + title: "Install oo-cli in Codex and start using skills", + commandsLabel: "Using Codex as the demo", commands: [ - "bun install -g @oomol-lab/oo-cli", - "oo login", - 'oo search \"social media optimizer\"', - "oo package info foo/bar@latest", - "oo cloud-task run foo/bar@1.2.3 --block-id main", + { + comment: "Install oo-cli in Codex first", + command: "bun install -g @oomol-lab/oo-cli", + }, + { + comment: "Log in so you can search and run skills", + command: "oo login", + }, + { + comment: "Start with a natural-language search", + command: 'oo search "social media optimizer"', + }, + { + comment: "Inspect what the skill does and what it needs", + command: "oo package info foo/bar@latest", + }, + { + comment: "Run it directly", + command: "oo cloud-task run foo/bar@1.2.3 --block-id main", + }, ], + media: { + label: "Video Slot", + title: "Use this slot for the Codex demo", + note: "Replace later with a short video that shows installing, searching, inspecting, and running a skill inside Codex.", + }, guide: "Open oo-cli Guide", github: "View GitHub", }, studio: { eyebrow: "03 / OOMOL Studio", - title: "When you need your own skill, install OOMOL Studio", + title: "When you need your own skill, use OOMOL Studio", description: - "Tell the agent what you want to build, let Studio generate the skill, then validate it locally. No platform DSL or steep setup before you begin.", + "Tell the agent what skill you want, let Studio generate the first version, then validate it locally. You do not need to learn a platform DSL before you begin.", points: [ { title: "Describe", @@ -189,14 +230,19 @@ const enCopy: Copy = { text: "Run dependencies, inputs, outputs, and results locally before release.", }, ], + media: { + label: "Video Slot", + title: "Use this slot for a Studio + Agent Vibe skill-generation demo", + note: "Replace later with a short video that goes from prompting to local validation.", + }, primary: "Install OOMOL Studio", secondary: "Explore Studio", }, cloud: { eyebrow: "04 / Cloud", - title: "After release, Cloud handles runtime, subscriptions, and management", + title: "After release, Cloud runs and manages the skill", description: - "Once a skill is ready, Cloud takes over the runtime and gives you subscription paths, configuration controls, and usage data without rebuilding another product shell around the same implementation.", + "Once a skill is ready, Cloud runs it in the background and gives you subscriptions, configuration, and usage data. You do not need to rebuild another product layer around the same implementation.", cards: [ { label: "Subscriptions", @@ -214,14 +260,19 @@ const enCopy: Copy = { text: "You get operational visibility into the skill instead of only seeing one-off invocation results.", }, ], + media: { + label: "Video Slot", + title: "Use this slot for a Cloud subscriptions, config, and metrics demo", + note: "Replace later with a backend walkthrough that shows publishing, settings, and operational data.", + }, primary: "Explore Cloud", secondary: "Open Cloud Console", }, agent: { eyebrow: "05 / OOMOL AI", - title: "If you do not want CLI, use the official OOMOL AI agent", + title: "If you do not want CLI, use OOMOL AI", description: - "Think of it as the GUI version of oo-cli. The same skill, a different consumption surface. Terminal is for workflows; GUI is for direct use.", + "Think of it as the GUI version of oo-cli. It uses the same skills through a more direct interface. CLI is better for workflows; GUI is better for straightforward use.", cards: [ { title: "Chat Surface", @@ -232,11 +283,16 @@ const enCopy: Copy = { text: "Use a parameterized interface when inputs are clear and execution should be direct.", }, ], + media: { + label: "Video Slot", + title: "Use this slot for the OOMOL AI agent demo", + note: "Replace later with a short video that shows both the chat surface and the structured surface.", + }, primary: "Try OOMOL AI", secondary: "Explore OOMOL AI", }, cta: { - title: "Use one skill first, then decide whether to build your own", + title: "Use a skill first, then decide whether to build your own", description: "Start by getting the usage path working in oo-cli. When you need your own skill, install Studio to generate, validate, and publish it.", primary: "Install OOMOL Studio", @@ -249,14 +305,6 @@ export default function HomepageLinearFlow() { i18n: { currentLocale: string }; }; const copy = i18n.currentLocale === "zh-CN" ? zhCopy : enCopy; - const studioLight = useBaseUrl("/img/pages/studio/studio-light.png"); - const studioDark = useBaseUrl("/img/pages/studio/studio-dark.png"); - const cloudLight = useBaseUrl("/img/pages/cloud/publish-light.png"); - const cloudDark = useBaseUrl("/img/pages/cloud/publish-dark.png"); - const chatLight = useBaseUrl("/img/pages/app/chat-light.png"); - const chatDark = useBaseUrl("/img/pages/app/chat-dark.png"); - const appletLight = useBaseUrl("/img/pages/app/applet-light.png"); - const appletDark = useBaseUrl("/img/pages/app/applet-dark.png"); return (
@@ -265,13 +313,27 @@ export default function HomepageLinearFlow() {
{copy.cli.eyebrow}

{copy.cli.title}

-

{copy.cli.description}

-
- {copy.cli.bullets.map(item => ( -

- {item} -

- ))} +
+
+ + + +
+
+
{copy.cli.commandsLabel}
+
+                  
+                    {copy.cli.commands.map(item => (
+                      
+                        # {item.comment}
+                        
+                          $ {item.command}
+                        
+                      
+                    ))}
+                  
+                
+
@@ -288,23 +350,13 @@ export default function HomepageLinearFlow() {
-
-
- - - -
-
-
{copy.cli.commandsLabel}
-
-                
-                  {copy.cli.commands.map(command => (
-                    
-                      $ {command}
-                    
-                  ))}
-                
-              
+
+
+
+ {copy.cli.media.label} +
+

{copy.cli.media.title}

+

{copy.cli.media.note}

@@ -313,11 +365,13 @@ export default function HomepageLinearFlow() {
- +
+
+ {copy.studio.media.label} +
+

{copy.studio.media.title}

+

{copy.studio.media.note}

+
@@ -377,11 +431,13 @@ export default function HomepageLinearFlow() {
- +
+
+ {copy.cloud.media.label} +
+

{copy.cloud.media.title}

+

{copy.cloud.media.note}

+
@@ -415,20 +471,13 @@ export default function HomepageLinearFlow() {
-
-
- -
-
- +
+
+
+ {copy.agent.media.label} +
+

{copy.agent.media.title}

+

{copy.agent.media.note}

@@ -440,7 +489,7 @@ export default function HomepageLinearFlow() {

{copy.cta.title}

{copy.cta.description}

- + {copy.cta.secondary} diff --git a/src/components/HomepageLinearFlow/styles.module.scss b/src/components/HomepageLinearFlow/styles.module.scss index 8f659633..a6fa3a86 100644 --- a/src/components/HomepageLinearFlow/styles.module.scss +++ b/src/components/HomepageLinearFlow/styles.module.scss @@ -48,6 +48,7 @@ display: grid; gap: 1rem; align-content: start; + max-width: 38rem; } .eyebrow { @@ -72,9 +73,10 @@ .sectionTitle, .ctaTitle { margin: 0; + max-width: 11ch; font-family: var(--oomol-font-display); - font-size: clamp(2.4rem, 4.8vw, 4.2rem); - line-height: 0.98; + font-size: clamp(2.15rem, 4vw, 3.55rem); + line-height: 1; letter-spacing: -0.045em; color: var(--oomol-text-primary); } @@ -88,32 +90,11 @@ color: var(--oomol-text-secondary); } -.bulletList { - display: grid; - gap: 0.72rem; - padding-top: 0.25rem; -} - -.bullet { - margin: 0; - display: grid; - grid-template-columns: auto 1fr; - gap: 0.78rem; - align-items: start; - font-size: 0.98rem; - line-height: 1.72; - color: var(--oomol-text-secondary); - - &::before { - content: "—"; - color: var(--oomol-primary-text); - } -} - .inlineActions, .ctaActions { display: flex; flex-wrap: wrap; + align-items: center; gap: 0.85rem; padding-top: 0.4rem; } @@ -169,6 +150,11 @@ overflow: hidden; } +.mediaPanel, +.agentMediaCard { + min-height: clamp(20rem, 34vw, 28rem); +} + .terminalPanel { display: grid; } @@ -218,14 +204,67 @@ display: block; } +.commentLine { + display: block; + margin: 0 0 0.28rem; + color: var(--oomol-text-tertiary); +} + .prompt { color: var(--oomol-primary-text); } -.heroImage { - display: block; - width: 100%; - height: auto; +.placeholderCard { + height: 100%; + min-height: inherit; + display: grid; + align-content: center; + gap: 0.95rem; + padding: clamp(1.4rem, 3vw, 2.2rem); + background: + linear-gradient(rgba(97, 113, 145, 0.08) 1px, transparent 1px), + linear-gradient(90deg, rgba(97, 113, 145, 0.08) 1px, transparent 1px), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-elevated) 90%, white 10%) 0%, + color-mix(in srgb, var(--oomol-bg-container) 82%, white 18%) 100% + ); + background-size: 3.25rem 3.25rem, 3.25rem 3.25rem, auto; +} + +.placeholderBadge { + display: inline-flex; + width: fit-content; + align-items: center; + justify-content: center; + min-height: 2rem; + padding: 0 0.7rem; + border-radius: 999px; + border: 1px solid var(--oomol-divider); + background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%); + font-size: 0.74rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--oomol-text-tertiary); +} + +.placeholderTitle { + margin: 0; + max-width: 18ch; + font-family: var(--oomol-font-display); + font-size: clamp(1.6rem, 2.4vw, 2.3rem); + line-height: 1.04; + letter-spacing: -0.03em; + color: var(--oomol-text-primary); +} + +.placeholderNote { + margin: 0; + max-width: 34rem; + font-size: 0.98rem; + line-height: 1.74; + color: var(--oomol-text-secondary); } .stepGrid { @@ -291,11 +330,6 @@ color: var(--oomol-text-secondary); } -.dualMedia { - display: grid; - gap: 1rem; -} - .ctaSection { padding: clamp(4rem, 8vw, 5.8rem) 0 clamp(3rem, 6vw, 4.4rem); } @@ -327,6 +361,12 @@ } .ctaGhost { + min-width: 12rem; + min-height: 54px; + padding: 0 1.35rem; + border-radius: 999px; + font-size: 1rem; + font-weight: 700; color: rgba(243, 239, 248, 0.94); border-color: rgba(243, 239, 248, 0.14); background: rgba(243, 239, 248, 0.08); @@ -334,8 +374,8 @@ :global(html[lang="en"]) .sectionTitle, :global(html[lang="en"]) .ctaTitle { - max-width: 16ch; - font-size: clamp(2.1rem, 4vw, 3.45rem); + max-width: 14ch; + font-size: clamp(1.95rem, 3.6vw, 3.1rem); line-height: 1.02; } @@ -410,6 +450,32 @@ ); } + .inlineNote { + border-color: color-mix( + in srgb, + var(--oomol-primary) 22%, + var(--oomol-divider) + ); + background: color-mix( + in srgb, + var(--oomol-bg-elevated) 78%, + var(--oomol-primary-bg) 22% + ); + color: color-mix(in srgb, var(--oomol-text-secondary) 92%, white 8%); + } + + .placeholderCard { + background: + linear-gradient(rgba(188, 194, 224, 0.07) 1px, transparent 1px), + linear-gradient(90deg, rgba(188, 194, 224, 0.07) 1px, transparent 1px), + linear-gradient( + 180deg, + color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 0%, + color-mix(in srgb, var(--oomol-bg-container) 82%, black 18%) 100% + ); + background-size: 3.25rem 3.25rem, 3.25rem 3.25rem, auto; + } + .ctaInner { border-color: color-mix( in srgb, From 0b19742bc1009ed2a0ba0921180377ea4f9a5bd4 Mon Sep 17 00:00:00 2001 From: shaun Date: Sat, 28 Mar 2026 22:43:49 +0800 Subject: [PATCH 04/15] update --- docusaurus.config.js | 10 + i18n/en/code.json | 47 +-- i18n/zh-CN/code.json | 129 +----- src/components/DownloadButton/index.tsx | 16 +- .../DownloadButton/styles.module.scss | 14 +- src/components/HomepageDeliveryGap/index.tsx | 59 --- .../HomepageDeliveryGap/styles.module.scss | 262 ------------ src/components/HomepageFirstScreen/index.tsx | 10 +- .../HomepageFirstScreen/styles.module.scss | 59 +-- src/components/HomepageLinearFlow/index.tsx | 310 ++++---------- .../HomepageLinearFlow/styles.module.scss | 387 +++++++++++++----- src/pages/studio/index.tsx | 9 +- src/pages/studio/styles.module.scss | 23 ++ src/theme/Navbar/index.tsx | 47 ++- src/theme/Navbar/styles.module.scss | 48 ++- 15 files changed, 599 insertions(+), 831 deletions(-) delete mode 100644 src/components/HomepageDeliveryGap/index.tsx delete mode 100644 src/components/HomepageDeliveryGap/styles.module.scss diff --git a/docusaurus.config.js b/docusaurus.config.js index 4cf1b0d6..106a6582 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -181,6 +181,11 @@ const config = { position: "left", className: "productDropdown", items: [ + { + to: "/docs/cloud-services/cli", + label: "navbar.oo-cli", + className: "productDropdownItem productDropdownItemCli", + }, { to: "/studio", label: "navbar.oomol-studio", @@ -191,6 +196,11 @@ const config = { label: "navbar.oomol-cloud", className: "productDropdownItem productDropdownItemCloud", }, + { + to: "/app", + label: "navbar.oomol-ai", + className: "productDropdownItem productDropdownItemAi", + }, ], }, { to: "/downloads", label: "navbar.download", position: "left" }, diff --git a/i18n/en/code.json b/i18n/en/code.json index 638c8362..14ea80f8 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -39,13 +39,13 @@ "message": "Start with ready-made capabilities in oo-cli, create your own blocks in OOMOL Studio, then deploy and deliver them privately through Cloud." }, "HOME.FirstScreen.heroTitle": { - "message": "Let agents use your skill while you stay in control of the code" + "message": "Let agents use your skill.\nYou stay in control of the code." }, "HOME.FirstScreen.heroSubtitle": { "message": "We call this a cloud skill: a capability that runs in the cloud and can be used directly from terminals and agent workflows." }, "HOME.FirstScreen.heroLead": { - "message": "A cloud skill runs in the cloud, stays reusable, and can be used directly from terminals and agent workflows." + "message": "A skill generated with OOMOL runs its underlying tool functions reliably in the cloud;\nonce users install oo-cli, they can use it directly in Codex and Claude Code." }, "HOME.FirstScreen.heroAdvantage": { "message": "Open source or closed source," @@ -53,6 +53,12 @@ "HOME.FirstScreen.heroAdvantageHighlight": { "message": "it is your call." }, + "HOME.FirstScreen.video.playAriaLabel": { + "message": "Play demo video" + }, + "HOME.FirstScreen.video.playLabel": { + "message": "Play demo" + }, "HOME.FirstScreen.pill1": { "message": "No new DSL" }, @@ -71,33 +77,6 @@ "HOME.FirstScreen.offer2": { "message": "200 free Cloud Task minutes each month" }, - "HOME.DeliveryGap.badge": { - "message": "Why Delivery Breaks" - }, - "HOME.DeliveryGap.title": { - "message": "The real cost starts after the function works." - }, - "HOME.DeliveryGap.subtitle": { - "message": "Once you want a capability to be called reliably by AI, APIs, and automations, the work that grows is usually wrapping interfaces, aligning environments, shipping to production, and keeping the whole path stable." - }, - "HOME.DeliveryGap.problem1.title": { - "message": "Function Done. Backend Work Begins." - }, - "HOME.DeliveryGap.problem1.description": { - "message": "The implementation already exists, but publishing it as an API or task still means rebuilding interfaces, deployment steps, and runtime wrappers." - }, - "HOME.DeliveryGap.problem2.title": { - "message": "Local Runs Do Not Guarantee Delivery" - }, - "HOME.DeliveryGap.problem2.description": { - "message": "Development, dependency, and deployment environments drift apart. The problem is often not the code itself, but whether it still holds once it leaves your machine." - }, - "HOME.DeliveryGap.problem3.title": { - "message": "One Capability Gets Wrapped Repeatedly" - }, - "HOME.DeliveryGap.problem3.description": { - "message": "Teams often wrap the same implementation separately for APIs, MCP tools, and automation tasks, multiplying delivery cost without adding capability." - }, "HOME.ProofLayer.badge": { "message": "Real Use Cases" }, @@ -3082,10 +3061,16 @@ "message": "Explore Cloud" }, "Theme.Navbar.product.studio.description": { - "message": "Build, debug, and validate your blocks" + "message": "Generate and validate your own cloud skills" + }, + "Theme.Navbar.product.cli.description": { + "message": "Install in Codex or Claude Code and use skills directly" }, "Theme.Navbar.product.cloud.description": { - "message": "Publish and deliver cloud skills privately" + "message": "Run, subscribe, and manage cloud skills in the cloud" + }, + "Theme.Navbar.product.ai.description": { + "message": "Use the official GUI agent for the same skills" }, "Theme.Navbar.product.label": { "message": "Product" diff --git a/i18n/zh-CN/code.json b/i18n/zh-CN/code.json index cc2e7c3a..a6acd6da 100644 --- a/i18n/zh-CN/code.json +++ b/i18n/zh-CN/code.json @@ -45,7 +45,7 @@ "message": "我们把这种运行在云端、可被终端和 agent 工作流直接使用的能力,叫做 cloud skill。" }, "HOME.FirstScreen.heroLead": { - "message": "cloud skill 是一种运行在云端、可复用,并且能被终端和 agent 工作流直接使用的能力。" + "message": "用 OOMOL 生成的 Skill,背后的工具函数在云端稳定执行;\n用户安装 oo-cli 后即可直接在 Codex 和 Claude Code 中使用。" }, "HOME.FirstScreen.heroAdvantage": { "message": "开源还是闭源," @@ -53,6 +53,12 @@ "HOME.FirstScreen.heroAdvantageHighlight": { "message": "都由你自己决定。" }, + "HOME.FirstScreen.video.playAriaLabel": { + "message": "播放演示视频" + }, + "HOME.FirstScreen.video.playLabel": { + "message": "点击播放演示" + }, "HOME.FirstScreen.pill1": { "message": "不学新 DSL" }, @@ -71,117 +77,6 @@ "HOME.FirstScreen.offer2": { "message": "每月赠送 200 分钟 Cloud Task" }, - "HOME.DeliveryGap.badge": { - "message": "为什么交付会卡住" - }, - "HOME.DeliveryGap.title": { - "message": "真正费时间的,不是把函数写出来" - }, - "HOME.DeliveryGap.subtitle": { - "message": "一旦你希望能力能被 AI、API 和自动化任务稳定调用,真正开始膨胀的往往是接口封装、环境对齐、部署上线和后续维护。" - }, - "HOME.DeliveryGap.problem1.title": { - "message": "写完业务,还要再搭一套后端" - }, - "HOME.DeliveryGap.problem1.description": { - "message": "实现已经有了,但为了对外提供 API 或任务能力,还要重新封装接口、部署流程和运行方式。" - }, - "HOME.DeliveryGap.problem2.title": { - "message": "本地能跑,不等于交付能跑" - }, - "HOME.DeliveryGap.problem2.description": { - "message": "开发环境、依赖环境和发布环境脱节,问题往往不是代码本身,而是它换了地方就不成立。" - }, - "HOME.DeliveryGap.problem3.title": { - "message": "同一份能力,被重复包装" - }, - "HOME.DeliveryGap.problem3.description": { - "message": "为了 API、MCP 工具和自动化任务,团队经常围着同一份实现反复改造,交付成本被重复放大。" - }, - "Suggested Media Slot": { - "message": "建议素材位" - }, - "Use motion here to explain why delivery work expands after the function already works. This slot should show process change, not UI detail alone.": { - "message": "这里更适合用动态素材解释函数已经跑通之后,为什么交付工作还会继续膨胀。这一位要讲“流程变化”,而不是单纯展示界面细节。" - }, - "GIF OR SHORT VIDEO": { - "message": "GIF 或短视频" - }, - "Delivery Gap": { - "message": "交付断层" - }, - "Flow Demo": { - "message": "流程演示" - }, - "6-10s loop. 16:9. Show delivery work multiplying.": { - "message": "建议 6-10 秒循环,16:9 横向,重点展示交付工作如何不断叠加。" - }, - "Loop": { - "message": "循环" - }, - "Function works": { - "message": "函数已跑通" - }, - "Start from a validated local run.": { - "message": "从本地已经验证成功的运行开始。" - }, - "Delivery work appears": { - "message": "交付工作开始出现" - }, - "Show wrappers, deploy, env, scheduling.": { - "message": "展示接口包装、部署、环境与调度配置。" - }, - "Outputs split": { - "message": "交付出口分叉" - }, - "End at API, MCP, and Task branches.": { - "message": "最后落到 API、MCP 和任务三个分支。" - }, - "Replace with real capture: code-to-delivery-gap.mp4": { - "message": "后续替换真实素材:code-to-delivery-gap.mp4" - }, - "Primary Demo Slot": { - "message": "主演示位" - }, - "This should become the homepage's main product demo. Show one validated capability being published to multiple delivery targets in a single flow.": { - "message": "这里应该成为首页的主演示。建议用一段完整流程,展示同一个已验证能力如何被发布到多个交付出口。" - }, - "VIDEO PREFERRED": { - "message": "视频优先" - }, - "One Function": { - "message": "一份函数" - }, - "Multiple Outputs": { - "message": "多个出口" - }, - "10-15s loop. 16:10. Publish to API, MCP, and Tasks.": { - "message": "建议 10-15 秒循环,16:10,展示如何发布成 API、MCP 和自动化任务。" - }, - "Video": { - "message": "视频" - }, - "Select validated flow": { - "message": "选中已验证流程" - }, - "Begin from something already proven locally.": { - "message": "从已经在本地验证过的能力开始。" - }, - "Switch delivery target": { - "message": "切换交付目标" - }, - "Move between API, MCP, and automation output.": { - "message": "在 API、MCP 与自动化任务之间切换。" - }, - "Show live result": { - "message": "看到线上结果" - }, - "End with endpoint, tool entry, or task status.": { - "message": "结尾落到接口地址、工具入口或任务状态。" - }, - "Replace with real capture: publish-to-api-mcp-task.mp4": { - "message": "后续替换真实素材:publish-to-api-mcp-task.mp4" - }, "HOME.ProofLayer.badge": { "message": "真实案例" }, @@ -3163,10 +3058,16 @@ "message": "了解 Cloud" }, "Theme.Navbar.product.studio.description": { - "message": "编写、调试并验证你的 block" + "message": "生成并验证你自己的 cloud skill" + }, + "Theme.Navbar.product.cli.description": { + "message": "装进 Codex 或 Claude Code,直接使用 Skill" }, "Theme.Navbar.product.cloud.description": { - "message": "私有发布并交付你的 cloud skill" + "message": "在云端运行、订阅和管理 cloud skill" + }, + "Theme.Navbar.product.ai.description": { + "message": "用官方 GUI Agent 直接使用同一套 Skill" }, "Theme.Navbar.product.label": { "message": "产品" diff --git a/src/components/DownloadButton/index.tsx b/src/components/DownloadButton/index.tsx index 7d53fad6..286b112b 100644 --- a/src/components/DownloadButton/index.tsx +++ b/src/components/DownloadButton/index.tsx @@ -29,12 +29,14 @@ export interface DownloadButtonProps { stableTag?: boolean; centered?: boolean; showNote?: boolean; + noteTone?: "default" | "inverse"; } export const DownloadButton = ({ stableTag, centered, showNote = true, + noteTone = "default", }: DownloadButtonProps) => { const downloadIcon = (