Files
Arcrun/.agents/specs/arcrun/frontend-redesign/design.md
T
uncle6me-web 922a57fe34 arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。

此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在
richblack/arcrun 與本地 backup 分支)。含:
- acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe)
- recipe push 把關(資料外流提醒 + 打通檢查)
- 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1)
- CLI / cypher-executor / registry / 完整 SDD

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 15:52:38 +08:00

13 KiB
Raw Blame History

Frontend Redesign — Design

讀此檔前請先讀 requirements.mddesign-source/index.html。 視覺 spec 的 single source of truth 是 design-source/Claude Design 匯出的 HTML/JSX prototype)。


1. 架構總覽

landing/ (Next.js 15 App Router)
├── app/
│   ├── layout.tsx             ← 全站 layoutnext/font + design tokens + 全域 CSS 匯入
│   ├── globals.css            ← 匯入 design-tokens.cssTailwind @import
│   ├── design-tokens.css      ← 新增:從 design-source 抽出的 CSS variables:root {...}
│   ├── page.tsx               ← LandingRSC
│   ├── auth/
│   │   └── page.tsx           ← Auth"use client"
│   ├── dashboard/
│   │   └── page.tsx           ← Dashboard"use client",仍靠 middleware 保護)
│   ├── keys/
│   │   └── page.tsx           ← API Keys"use client"
│   ├── workflows/
│   │   ├── page.tsx           ← Workflows 清單(redirect 到 dashboard 的 table,本身極簡)
│   │   └── [name]/page.tsx    ← Workflow Viewer"use client"
│   ├── integrations/page.tsx  ← 保留現有
│   ├── api-docs/page.tsx      ← 保留現有
│   └── login/page.tsx         ← 保留現有(redirect /auth 同義;見 §9 遷移策略)
├── components/
│   ├── shell/
│   │   ├── Logo.tsx
│   │   ├── Icon.tsx
│   │   ├── TopNav.tsx
│   │   ├── Footer.tsx
│   │   └── Sidebar.tsx
│   ├── primitives/
│   │   ├── Button.tsx         ← btn / btn-primary / btn-secondary / btn-ghost 對應 class
│   │   ├── Pill.tsx
│   │   ├── Toggle.tsx
│   │   ├── Terminal.tsx       ← landing hero 右卡用
│   │   └── ChatPreview.tsx    ← landing hero 右卡用
│   └── workflow/
│       ├── Canvas.tsx         ← wf-viewer 本體(節點 + SVG edges
│       ├── NodeCard.tsx
│       ├── DetailPanel.tsx
│       ├── Minimap.tsx
│       └── ZoomControls.tsx
├── lib/
│   ├── api.ts                 ← typed fetch wrapperfetch ${API_BASE}${path}, credentials: 'include'
│   ├── workflows.ts           ← listWorkflows / getWorkflow / getWorkflowYaml
│   ├── apiKeys.ts             ← listKeys / createKey / patchKey / deleteKey
│   └── me.ts                  ← 已存在邏輯,集中到此
├── middleware.ts              ← 擴展 matcher(加 /keys, /workflows/*
└── ...(既有 package.json / wrangler.toml 不變)

路由對照設計稿的 5 screen

Screen Route
Landing /
Auth /auth(新增;/login 保留並內部 redirect('/auth')
Dashboard /dashboard
API Keys /keys
Workflow Viewer /workflows/[name]

2. Design tokens 對應

設計稿所有 CSS 變數抄進 app/design-tokens.css不解析、不改名

:root {
  --bg: #0F0F0F;
  --bg-1: #141414;
  --card: #1A1A1A;
  --card-2: #222222;
  --line: #262626;
  --line-2: #303030;
  --text: #EDEDED;
  --text-dim: #A0A0A0;
  --text-mute: #6B6B6B;
  --primary: #6366F1;
  --primary-2: #8B5CF6;
  --primary-soft: rgba(99, 102, 241, 0.12);
  --primary-ring: rgba(99, 102, 241, 0.32);
  --success: #22C55E;
  --warn: #F59E0B;
  --danger: #EF4444;
  --gradient: linear-gradient(135deg, #6366F1 0%, #8B5CF6 100%);
  --gradient-soft: linear-gradient(135deg, rgba(99,102,241,0.16) 0%, rgba(139,92,246,0.16) 100%);
}

並在 Tailwind v4 的 @theme inline block 內對應出:

@theme inline {
  --color-bg: var(--bg);
  --color-card: var(--card);
  --color-card-2: var(--card-2);
  --color-line: var(--line);
  --color-line-2: var(--line-2);
  --color-text: var(--text);
  --color-text-dim: var(--text-dim);
  --color-text-mute: var(--text-mute);
  --color-primary: var(--primary);
  --color-primary-2: var(--primary-2);
}

這樣 JSX 裡可用 bg-bg / text-text-dim / border-line,又保留 CSS 變數語義。

現有的 --background: #0a0a0a 要換成 #0F0F0F(視覺 breaking change;受影響:所有沿用 bg-[#0a0a0a] 的 inline 值)。


3. 字型

// app/layout.tsx
import { Inter, JetBrains_Mono } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  weight: ['300', '400', '500', '600', '700', '800'],
});
const mono = JetBrains_Mono({
  subsets: ['latin'],
  variable: '--font-mono',
  weight: ['400', '500', '600'],
});

// body class = `${inter.variable} ${mono.variable}`

globals.css 中的 body { font-family: var(--font-inter), -apple-system, sans-serif; }.mono class 用 font-family: var(--font-mono)

移除

  • design-source/index.html 第 7-9 行的 <link rel="preconnect"> / <link href="fonts.googleapis.com">(不寫入 production)。
  • React / Babel standalone script 標籤(prototype 專用,不進 production)。

4. 元件 porting 規則

Claude Design 用了 window.Icon / window.Logo / window.AppIcon / window.TopNav ... 的 globals 風格 — 那是 prototype 專用。Port 到 Next.js 時:

  1. 每個元件拆單檔、具名 export。
  2. 用 Tailwind + className 模板字串;共用 variant(如 btn)用 cva-style helper 即可(自己寫 5 行的 clsx-alike 函式),不引入 class-variance-authority / clsx 套件(避免新依賴)。
  3. Icon 的 paths 直接搬,但每個 icon 拆成自己的 functional component 或集中在一個 <Icon name="..." />(沿用 design source 的 pattern)。
  4. SVG arc wordmark 的 logo 直接 port。

5. 各 screen 實作細節

5.1 Landing — app/page.tsx

  • 結構:<TopNav /> + <Hero /> + <Paths /> + <Strip /> + <Footer />
  • Heroheading、eyebrow、CTA、radial grid bg(純 CSS)。
  • Paths 左卡(Developer):install tabs (npm / pip / bun) + 兩個 terminal blockcode 範例用 dogfooding 範例acr CLI),不留 Arcrun SDK 假 API。
  • Paths 右卡(Everyone):chat preview 結構保留;assistant 對話中的 tool call 用「arcrun · digest/weekly」不動。
  • Strip4 cell。
  • LandingClientTabs 因為有 tabs state,需標 "use client";外層保持 RSC。

5.2 Auth — app/auth/page.tsx

  • "use client"。statemode: 'signin' | 'signup', email, pw, remember
  • Submitfetch(${API_BASE}/auth/password-login, { method: 'POST', credentials: 'include' })若 cypher-executor 尚未支援 password auth,先顯示「Password 登入尚未開放,請用 OAuth」警示,不偽造成功流程)。
  • OAuth 按鈕:直接 <a href={API_BASE}/auth/google/start?redirect=/dashboard>,和現行 /login 同樣機制。
  • 下標提示「By signing up, you agree to our Terms ...」保留 static 字串。
  • 保留 /login 路由向後相容(RSC 裡 redirect('/auth'))。

5.3 Dashboard — app/dashboard/page.tsx

  • "use client" 或 split(外層 RSC 抓 /me,內層 Client)。
  • <Sidebar current="dashboard" /> + main。
  • 主要區塊:
    • Main headbreadcrumb「{email 的 domain} Dashboard」、heading「Welcome back, {display_name}」、subtitle 顯示 app/workflow 總數(從 /apps + /workflows 計算;若 endpoint 404 → 顯示 )。
    • Apps Grid/apps 的結果渲染;每列永遠有一個 app-empty 卡(新建 CTA)。
    • Workflows Table/workflows 的結果渲染;空時改為全寬「No workflows yet. Run acr push to add one.」內嵌指令框。
  • 「Open app」「View」按鈕導向 /workflows/[name]
  • 「Edit in Claude」按鈕本次不做動作,僅保 UIdisabled + tooltip「Coming soon」)。

5.4 API Keys — app/keys/page.tsx

  • "use client"
  • Fetch /api-keys:若回傳為空陣列但 /me 有 api_keyfallback 顯示 /me.api_key 為唯一一列(單 key 相容模式)。
  • 頂部 new-key-box:只在「剛剛建立新 key」的一次性狀態顯示(useState + sessionStorage flagreload 後消失)。
  • 表格、toggle、trash:對應 PATCH / DELETE。
  • 「Create new key」按鈕:呼叫 POST /api-keys,拿到後打 highlight box。
  • Revoke 警告文字維持設計稿「within 60 seconds」。

5.5 Workflow Viewer — app/workflows/[name]/page.tsx

  • "use client"param name 來自動態路由。
  • Mount 後呼叫 GET /workflows/:name:後端回傳 { name, nodes: Node[], edges: Edge[], yaml, last_run: {...} }(若 endpoint 未實作 → 顯示「Workflow viewer 尚未啟用」empty state,不用假資料)。
  • <Canvas> 內:
    • SVG 的 <marker>, <path> 定義抄設計稿。
    • Node 用絕對定位(x/y 直接用 API 資料;資料沒有 coord 時做自動 layout — 階段性做簡單 dagre-free 的「column by depth」排版,避免新依賴)。
    • 點選節點 → 右側 detail panel 顯示 input/output schema;若 type 含 ai.*,顯示 triplet 編輯器(model / temp / prompt)— 編輯本次 read-onlydisabled input + 「Edit via acr CLI」提示)。
  • 「Export YAML」按 GET /workflows/:name/yamldownload blob。
  • 「Edit in Claude」:本次只開新 tab 到 https://claude.ai/new?q=...(文案「coming soon」按鈕),避免偽裝已整合。
  • Zoom controls、minimap:純 UIzoom state 實際不套 transform(或簡單 style={{ transform: scale(zoom/100) }} 套在 .wf-nodes + svg)。

6. API wrapperlib/api.ts

export const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? 'https://cypher.arcrun.dev';

export async function arcrunFetch<T>(path: string, init: RequestInit = {}): Promise<T> {
  const res = await fetch(`${API_BASE}${path}`, {
    credentials: 'include',
    headers: { 'Accept': 'application/json', ...(init.headers ?? {}) },
    ...init,
  });
  if (res.status === 401 && typeof window !== 'undefined') {
    window.location.href = `/auth?redirect=${encodeURIComponent(location.pathname)}`;
    throw new Error('unauthenticated');
  }
  if (!res.ok) throw new Error(`arcrun ${path}: ${res.status}`);
  return res.json() as Promise<T>;
}

所有頁面透過這個 wrapper。禁止在 page.tsx 裡 hard-code fetch('https://...')(測試可以 grep)。


7. Middleware

export const config = {
  matcher: ['/dashboard/:path*', '/keys/:path*', '/workflows/:path*'],
};

現有邏輯(讀 arcrun_session cookie,沒有就 redirect /login?redirect=...)保留,/login 改為內部 redirect /auth


8. 不做的設計稿功能

設計元素 取捨
底部的 proto-switch5 個 screen 切換 pill 。那是 prototype 用的 demo 切換器,不進 production。
Sidebar 的 count badge 先保留;數字從 /workflows / /apps 的長度派生;無資料時藏起來。
Sidebar bottom 的 avatar + "Maya Rivera / maya@northwind.co" 換成 {display_name} / {email}(真資料)。
Workflow Viewer 的 triplet 可編輯 本次 disabled,僅顯示。
「Edit in Claude」整合 按鈕保留,點擊開新 tab 到 claude.ai,不串 MCP/API。
多 workspace breadcrumb 固定顯示用戶 email domain 或「Personal」。

9. 既有頁面遷移

既有 處理
/page.tsx rewrite:沿用設計稿結構,code demo 字串改為 acr 實際指令(現有的 auth.bind(...) 寫法可保留在 Python tab
/login 改為 redirect('/auth')Next.js RSC redirect),保留舊連結相容
/dashboard rewrite:舊 dashboard 變成 API Keys 獨立頁 + 新 Dashboard 總覽。原本 dashboard 裡的 Key 卡片搬到 /keys
/api-docs 不動
/integrations 不動;在 Dashboard Apps Grid 旁提供 link

10. 開發順序(高度相依)

tasks.md。總則:

  1. 先做 design tokens + shellLogo / Icon / Button / Sidebar / TopNav / Footer — 其他頁面都吃這些。
  2. 然後 Landing(可直接驗證視覺基準)。
  3. 然後 Auth(獨立)。
  4. 然後 API Keys(後端依賴少)。
  5. 然後 Dashboard(依賴 /workflows + /apps,若未實作先 empty state)。
  6. 最後 Workflow Viewer(依賴最重,多 endpoint)。

11. 風險與未解

風險 緩解
cypher-executor 尚未有 /workflows, /apps, /api-keys CRUD 前端先做,統一走 404 → empty state;另開 task 去 cypher-executor SDD 增補。本次 SDD 不負責後端實作。
Password auth 沒實作 Auth 頁 email/password form 在 submit 時顯示「OAuth only」提示
acr push 未記錄 node 座標 Canvas 自動排版(by topological depth),不強制 YAML 載入 layout
next-on-pages"use client" 大量頁面的 edge runtime 支援 本來就用 next-on-pages,問題不大;必要時 per-page export const runtime = 'edge'
/dashboard 的 bookmark 使用者 現行 /dashboard 的 Key 管理被搬走;保留 Key 區塊 + 顯示提示「New page: /keys」引導

12. 與封測的關係

此 SDD 的實作不解除封測阻擋(封測阻擋在 Credential Primitives WASM)。此重設計與 Phase 0.6 / 0.7 / 1-3 是並行軌道。richblack 可決定先後順序,但本 SDD 獨立可 ship。