frontend-playbook

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Frontend Playbook

前端操作手册

What You Probably Got Wrong

你可能搞错的几件事

"I'll use
yarn chain
."
Wrong.
yarn chain
gives you an empty local chain with no protocols, no tokens, no state.
yarn fork --network base
gives you a copy of real Base with Uniswap, Aave, USDC, real whale balances — everything. Always fork.
"I deployed to IPFS and it works." Did the CID change? If not, you deployed stale output. Did routes work? Without
trailingSlash: true
, every route except
/
returns 404. Did you check the OG image? Without
NEXT_PUBLIC_PRODUCTION_URL
, it points to
localhost:3000
.
"I'll set up the project manually." Don't.
npx create-eth@latest
handles everything — Foundry, Next.js, RainbowKit, scaffold hooks. Never run
forge init
or create Next.js projects from scratch.

“我要用
yarn chain
。”
错了。
yarn chain
会给你一个空的本地链,没有协议、没有代币、没有状态。
yarn fork --network base
会给你一个真实Base链的副本,包含Uniswap、Aave、USDC、真实的巨鲸余额——所有内容。始终使用fork模式。
“我部署到IPFS了,能正常运行。” CID有没有变化?如果没有,你部署的是旧的输出内容。路由能正常工作吗?如果没有设置
trailingSlash: true
,除了
/
之外的所有路由都会返回404。你检查OG图片了吗?如果没有设置
NEXT_PUBLIC_PRODUCTION_URL
,它会指向
localhost:3000
“我要手动搭建项目。” 别这么做。
npx create-eth@latest
会处理所有事情——Foundry、Next.js、RainbowKit、scaffold钩子函数。永远不要手动运行
forge init
或从零创建Next.js项目。

Fork Mode Setup

Fork模式设置

Why Fork, Not Chain

为什么用Fork而不是Chain

yarn chain (WRONG)              yarn fork --network base (CORRECT)
└─ Empty local chain            └─ Fork of real Base mainnet
└─ No protocols                 └─ Uniswap, Aave, etc. available
└─ No tokens                    └─ Real USDC, WETH exist
└─ Testing in isolation         └─ Test against REAL state
yarn chain (错误)              yarn fork --network base (正确)
└─ 空的本地链            └─ 真实Base主网的副本
└─ 无任何协议                 └─ 可使用Uniswap、Aave等协议
└─ 无代币                    └─ 存在真实的USDC、WETH
└─ 孤立环境测试         └─ 针对真实状态进行测试

Setup

搭建步骤

bash
npx create-eth@latest          # Select: foundry, target chain, name
cd <project-name>
yarn install
yarn fork --network base       # Terminal 1: fork of real Base
yarn deploy                    # Terminal 2: deploy contracts to fork
yarn start                     # Terminal 3: Next.js frontend
bash
npx create-eth@latest          # 选择:foundry、目标链、项目名称
cd <project-name>
yarn install
yarn fork --network base       # 终端1:启动真实Base链的fork副本
yarn deploy                    # 终端2:将合约部署到fork链
yarn start                     # 终端3:启动Next.js前端

Critical: Chain ID Gotcha

关键注意点:Chain ID陷阱

When using fork mode, the frontend target network MUST be
chains.foundry
(chain ID 31337), NOT the chain you're forking.
The fork runs locally on Anvil with chain ID 31337. Even if you're forking Base:
typescript
// scaffold.config.ts during development
targetNetworks: [chains.foundry],  // ✅ NOT chains.base!
Only switch to
chains.base
when deploying contracts to the REAL network.
使用fork模式时,前端的目标网络必须是
chains.foundry
(Chain ID 31337),而不是你要fork的链。
Fork链在本地Anvil上运行,Chain ID为31337。即使你fork的是Base链:
typescript
// 开发环境下的scaffold.config.ts
targetNetworks: [chains.foundry],  // ✅ 不要用chains.base!
只有在将合约部署到真实网络时,才切换为
chains.base

Enable Block Mining

启用区块挖矿

bash
undefined
bash
undefined

In a new terminal — REQUIRED for time-dependent logic

在新终端中执行——对于依赖时间的逻辑是必需的

cast rpc anvil_setIntervalMining 1

Without this, `block.timestamp` stays FROZEN. Any contract logic using timestamps (deadlines, expiry, vesting) will break silently.

**Make it permanent** by editing `packages/foundry/package.json` to add `--block-time 1` to the fork script.

---
cast rpc anvil_setIntervalMining 1

如果不这么做,`block.timestamp`会保持冻结状态。任何使用时间戳的合约逻辑(截止时间、过期、归属)都会静默失效。

**永久设置**:编辑`packages/foundry/package.json`,在fork脚本中添加`--block-time 1`。

---

Deploying to IPFS (Recommended)

部署到IPFS(推荐)

IPFS is the recommended deploy path for SE2. Avoids Vercel's memory limits entirely. Produces a fully decentralized static site.
IPFS是SE2推荐的部署路径,完全避免Vercel的内存限制,生成完全去中心化的静态站点。

Full Build Command

完整构建命令

bash
cd packages/nextjs
rm -rf .next out  # ALWAYS clean first

NEXT_PUBLIC_PRODUCTION_URL="https://yourapp.yourname.eth.link" \
  NODE_OPTIONS="--require ./polyfill-localstorage.cjs" \
  NEXT_PUBLIC_IPFS_BUILD=true \
  NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \
  yarn build
bash
cd packages/nextjs
rm -rf .next out  # 始终先清理旧文件

NEXT_PUBLIC_PRODUCTION_URL="https://yourapp.yourname.eth.link" \
  NODE_OPTIONS="--require ./polyfill-localstorage.cjs" \
  NEXT_PUBLIC_IPFS_BUILD=true \
  NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \
  yarn build

Upload to BuidlGuidl IPFS

上传到BuidlGuidl IPFS

yarn bgipfs upload out
yarn bgipfs upload out

Save the CID!

保存生成的CID!

undefined
undefined

Node 25+ localStorage Polyfill (REQUIRED)

Node 25+ localStorage 兼容补丁(必需)

Node.js 25+ ships a built-in
localStorage
object that's MISSING standard WebStorage API methods (
getItem
,
setItem
). This breaks
next-themes
, RainbowKit, and any library that calls
localStorage.getItem()
during static page generation.
Error you'll see:
TypeError: localStorage.getItem is not a function
Error occurred prerendering page "/_not-found"
The fix: Create
polyfill-localstorage.cjs
in
packages/nextjs/
:
javascript
if (typeof globalThis.localStorage !== "undefined" &&
    typeof globalThis.localStorage.getItem !== "function") {
  const store = new Map();
  globalThis.localStorage = {
    getItem: (key) => store.get(key) ?? null,
    setItem: (key, value) => store.set(key, String(value)),
    removeItem: (key) => store.delete(key),
    clear: () => store.clear(),
    key: (index) => [...store.keys()][index] ?? null,
    get length() { return store.size; },
  };
}
Why
--require
and not
instrumentation.ts
?
Next.js spawns a separate build worker process for prerendering.
--require
injects into EVERY Node process (including workers).
next.config.ts
polyfill only runs in the main process.
instrumentation.ts
doesn't run in the build worker. Only
--require
works.
Node.js 25+内置的
localStorage
对象缺少标准WebStorage API的方法(
getItem
setItem
)。这会导致
next-themes
、RainbowKit以及任何在静态页面生成期间调用
localStorage.getItem()
的库失效。
你会遇到的错误:
TypeError: localStorage.getItem is not a function
Error occurred prerendering page "/_not-found"
修复方法:
packages/nextjs/
目录下创建
polyfill-localstorage.cjs
文件:
javascript
if (typeof globalThis.localStorage !== "undefined" &&
    typeof globalThis.localStorage.getItem !== "function") {
  const store = new Map();
  globalThis.localStorage = {
    getItem: (key) => store.get(key) ?? null,
    setItem: (key, value) => store.set(key, String(value)),
    removeItem: (key) => store.delete(key),
    clear: () => store.clear(),
    key: (index) => [...store.keys()][index] ?? null,
    get length() { return store.size; },
  };
}
为什么用
--require
而不是
instrumentation.ts
Next.js会为预渲染启动单独的构建工作进程。
--require
会注入到所有Node进程(包括工作进程)中。
next.config.ts
中的补丁仅在主进程中运行,
instrumentation.ts
不会在构建工作进程中运行。只有
--require
能生效。

IPFS Routing — Why Routes Break

IPFS路由——路由失效的原因

IPFS gateways serve static files. No server handles routing. Three things MUST be true:
1.
output: "export"
in next.config.ts
— generates static HTML files.
2.
trailingSlash: true
(CRITICAL)
— This is the #1 reason routes break:
  • trailingSlash: false
    (default) → generates
    debug.html
  • trailingSlash: true
    → generates
    debug/index.html
  • IPFS gateways resolve directories to
    index.html
    automatically, but NOT bare filenames
  • Without trailing slash:
    /debug
    → 404 ❌
  • With trailing slash:
    /debug
    debug/
    debug/index.html
3. Pages must survive static prerendering — any page that crashes during
yarn build
(browser APIs at import time, localStorage) gets skipped silently → 404 on IPFS.
The complete IPFS-safe next.config.ts pattern:
typescript
const isIpfs = process.env.NEXT_PUBLIC_IPFS_BUILD === "true";
if (isIpfs) {
  nextConfig.output = "export";
  nextConfig.trailingSlash = true;
  nextConfig.images = { unoptimized: true };
}
SE2's block explorer pages use
localStorage
at import time and crash during static export. Rename
app/blockexplorer
to
app/_blockexplorer-disabled
if not needed.
IPFS网关仅提供静态文件服务,没有服务器处理路由。必须满足三个条件:
1. next.config.ts中设置
output: "export"
—— 生成静态HTML文件。
2. 设置
trailingSlash: true
(至关重要)
—— 这是路由失效的头号原因:
  • trailingSlash: false
    (默认)→ 生成
    debug.html
  • trailingSlash: true
    → 生成
    debug/index.html
  • IPFS网关会自动将目录解析为
    index.html
    ,但不会解析裸文件名
  • 没有尾部斜杠:
    /debug
    → 404 ❌
  • 有尾部斜杠:
    /debug
    debug/
    debug/index.html
3. 页面必须能通过静态预渲染 —— 任何在
yarn build
期间崩溃的页面(导入时调用浏览器API、localStorage)会被静默跳过→在IPFS上返回404。
完整的IPFS兼容next.config.ts模板:
typescript
const isIpfs = process.env.NEXT_PUBLIC_IPFS_BUILD === "true";
if (isIpfs) {
  nextConfig.output = "export";
  nextConfig.trailingSlash = true;
  nextConfig.images = { unoptimized: true };
}
SE2的区块浏览器页面在导入时使用
localStorage
,会在静态导出时崩溃。如果不需要,将
app/blockexplorer
重命名为
app/_blockexplorer-disabled

Stale Build Detection

陈旧构建检测

The #1 IPFS footgun: You edit code, then deploy the OLD build.
bash
undefined
IPFS的头号陷阱: 你修改了代码,但部署的是旧构建。
bash
undefined

MANDATORY after ANY code change:

任何代码变更后必须执行:

rm -rf .next out # 1. Delete old artifacts
rm -rf .next out # 1. 删除旧构建产物

... run full build command ... # 2. Rebuild from scratch

... 执行完整构建命令 ... # 2. 从头重新构建

grep -l "YOUR_STRING" out/_next/static/chunks/app/*.js # 3. Verify changes present
grep -l "YOUR_STRING" out/_next/static/chunks/app/*.js # 3. 验证变更已包含在内

Timestamp check:

时间戳检查:

stat -f '%Sm' app/page.tsx # Source modified time stat -f '%Sm' out/ # Build output time
stat -f '%Sm' app/page.tsx # 源码修改时间 stat -f '%Sm' out/ # 构建输出时间

Source NEWER than out/ = STALE BUILD. Rebuild first!

源码时间晚于out/ = 陈旧构建。先重新构建!


**The CID is proof:** If the IPFS CID didn't change after a deploy, you deployed the same content. A real code change ALWAYS produces a new CID.

**CID是证明:** 如果部署后IPFS的CID没有变化,说明你部署的是相同内容。真正的代码变更必然会生成新的CID。

Verify Routes After Deploy

部署后验证路由

bash
ls out/*/index.html                  # Each route has a directory + index.html
curl -s -o /dev/null -w "%{http_code}" -L "https://GATEWAY/ipfs/CID/debug/"
bash
ls out/*/index.html                  # 每个路由都有对应的目录+index.html
curl -s -o /dev/null -w "%{http_code}" -L "https://GATEWAY/ipfs/CID/debug/"

Should return 200, not 404

应返回200,而非404


---

---

Deploying to Vercel (Alternative)

部署到Vercel(替代方案)

SE2 is a monorepo — Vercel needs special configuration.
SE2是一个单仓多包项目——Vercel需要特殊配置。

Configuration

配置步骤

  1. Root Directory:
    packages/nextjs
  2. Install Command:
    cd ../.. && yarn install
  3. Build Command: leave default (
    next build
    )
  4. Output Directory: leave default (
    .next
    )
bash
undefined
  1. 根目录:
    packages/nextjs
  2. 安装命令:
    cd ../.. && yarn install
  3. 构建命令: 保留默认值(
    next build
  4. 输出目录: 保留默认值(
    .next
bash
undefined

Via API:

通过API配置:

curl -X PATCH "https://api.vercel.com/v9/projects/PROJECT_ID"
-H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
-d '{"rootDirectory": "packages/nextjs", "installCommand": "cd ../.. && yarn install"}'
undefined
curl -X PATCH "https://api.vercel.com/v9/projects/PROJECT_ID"
-H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
-d '{"rootDirectory": "packages/nextjs", "installCommand": "cd ../.. && yarn install"}'
undefined

Common Failures

常见失败情况

ErrorCauseFix
"No Next.js version detected"Root Directory not setSet to
packages/nextjs
"cd packages/nextjs: No such file"Build command has
cd
Clear it — root dir handles this
OOM / exit code 129SE2 monorepo exceeds 8GBUse IPFS instead, or
vercel --prebuilt
错误原因修复方法
"No Next.js version detected"未设置根目录设置为
packages/nextjs
"cd packages/nextjs: No such file"构建命令包含
cd
清空构建命令——根目录会处理路径
OOM / exit code 129SE2单仓多包项目超过8GB内存限制改用IPFS部署,或使用
vercel --prebuilt

Decision Tree

决策树

Want to deploy SE2?
├─ IPFS (recommended) → yarn ipfs / manual build + upload
│   └─ Fully decentralized, no memory limits, works with ENS
├─ Vercel → Set rootDirectory + installCommand
│   └─ Fast CDN, but centralized. May OOM on large projects
└─ vercel --prebuilt → Build locally, push artifacts to Vercel
    └─ Best of both: local build power + Vercel CDN

想要部署SE2?
├─ IPFS(推荐)→ yarn ipfs / 手动构建+上传
│   └─ 完全去中心化,无内存限制,兼容ENS
├─ Vercel → 设置rootDirectory + installCommand
│   └─ CDN速度快,但中心化。大型项目可能出现内存不足
└─ vercel --prebuilt → 本地构建,将产物推送到Vercel
    └─ 兼顾两者优势:本地构建能力 + Vercel CDN

ENS Subdomain Setup

ENS子域名设置

Two mainnet transactions to point an ENS subdomain at your IPFS deployment.
需要两笔主网交易,将ENS子域名指向你的IPFS部署。

Transaction 1: Create Subdomain (new apps only)

交易1:创建子域名(仅适用于新应用)

  1. Open
    https://app.ens.domains/yourname.eth
  2. Go to "Subnames" tab → "New subname"
  3. Enter the label (e.g.
    myapp
    ) → Next → Skip profile → Open Wallet → Confirm
  4. If gas is stuck: switch MetaMask to Ethereum → Activity tab → "Speed up"
  1. 打开
    https://app.ens.domains/yourname.eth
  2. 进入“Subnames”标签页 → “New subname”
  3. 输入标签(例如
    myapp
    )→ 下一步 → 跳过资料设置 → 打开钱包 → 确认交易
  4. 如果gas卡住:将MetaMask切换到以太坊主网 → 活动标签页 → “加速”

Transaction 2: Set IPFS Content Hash

交易2:设置IPFS内容哈希

  1. Navigate to
    https://app.ens.domains/myapp.yourname.eth
  2. "Records" tab → "Edit Records" → "Other" tab
  3. Paste in Content Hash field:
    ipfs://<CID>
  4. Save → Open Wallet → Confirm in MetaMask
For updates to an existing app: skip Tx 1, only do Tx 2.
  1. 导航到
    https://app.ens.domains/myapp.yourname.eth
  2. “Records”标签页 → “Edit Records” → “Other”标签页
  3. 在Content Hash字段中粘贴:
    ipfs://<CID>
  4. 保存 → 打开钱包 → 在MetaMask中确认交易
对于现有应用的更新:跳过交易1,仅执行交易2。

Verify

验证

bash
undefined
bash
undefined

1. Onchain content hash matches

1. 链上内容哈希匹配

RESOLVER=$(cast call 0x00000000000C2e074eC69A0dFb2997BA6C7d2e1e
"resolver(bytes32)(address)" $(cast namehash myapp.yourname.eth)
--rpc-url https://eth.llamarpc.com) cast call $RESOLVER "contenthash(bytes32)(bytes)"
$(cast namehash myapp.yourname.eth) --rpc-url https://eth.llamarpc.com
RESOLVER=$(cast call 0x00000000000C2e074eC69A0dFb2997BA6C7d2e1e
"resolver(bytes32)(address)" $(cast namehash myapp.yourname.eth)
--rpc-url https://eth.llamarpc.com) cast call $RESOLVER "contenthash(bytes32)(bytes)"
$(cast namehash myapp.yourname.eth) --rpc-url https://eth.llamarpc.com

2. Gateway responds (may take 5-15 min for cache)

2. 网关响应(缓存可能需要5-15分钟)

curl -s -o /dev/null -w "%{http_code}" -L "https://myapp.yourname.eth.link"
curl -s -o /dev/null -w "%{http_code}" -L "https://myapp.yourname.eth.link"

3. OG metadata correct (not localhost)

3. OG元数据正确(不是localhost)

curl -s -L "https://myapp.yourname.eth.link" | grep 'og:image'

**Use `.eth.link` NOT `.eth.limo`** — `.eth.link` works better on mobile.

---
curl -s -L "https://myapp.yourname.eth.link" | grep 'og:image'

**使用`.eth.link`而不是`.eth.limo`** —— `.eth.link`在移动端的兼容性更好。

---

Go to Production — Complete Checklist

上线生产环境——完整检查清单

When the user says "ship it", follow this EXACT sequence.
当用户说“发布”时,严格按照以下步骤执行。

Step 1: Final Code Review 🤖

步骤1:最终代码审查 🤖

  • All feedback incorporated
  • No duplicate h1, no raw addresses, no shared isLoading
  • scaffold.config.ts
    has
    rpcOverrides
    and
    pollingInterval: 3000
  • 所有反馈已处理
  • 无重复h1标签、无裸地址、无共享的isLoading状态
  • scaffold.config.ts
    中配置了
    rpcOverrides
    pollingInterval: 3000

Step 2: Choose Domain 👤

步骤2:选择域名 👤

Ask: "What subdomain do you want? e.g.
myapp.yourname.eth
myapp.yourname.eth.link
"
询问:“你想要什么子域名?例如
myapp.yourname.eth
myapp.yourname.eth.link

Step 3: Generate OG Image + Fix Metadata 🤖

步骤3:生成OG图片 + 修复元数据 🤖

  • Create 1200×630 PNG (
    public/thumbnail.png
    ) — NOT the stock SE2 thumbnail
  • Set
    NEXT_PUBLIC_PRODUCTION_URL
    to the live domain
  • Verify
    og:image
    will resolve to an absolute production URL
  • 创建1200×630的PNG图片(
    public/thumbnail.png
    )——不要使用SE2的默认缩略图
  • NEXT_PUBLIC_PRODUCTION_URL
    设置为正式域名
  • 验证
    og:image
    会解析为绝对的生产环境URL

Step 4: Clean Build + IPFS Deploy 🤖

步骤4:清理构建 + IPFS部署 🤖

bash
cd packages/nextjs && rm -rf .next out
NEXT_PUBLIC_PRODUCTION_URL="https://myapp.yourname.eth.link" \
  NODE_OPTIONS="--require ./polyfill-localstorage.cjs" \
  NEXT_PUBLIC_IPFS_BUILD=true NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \
  yarn build
bash
cd packages/nextjs && rm -rf .next out
NEXT_PUBLIC_PRODUCTION_URL="https://myapp.yourname.eth.link" \
  NODE_OPTIONS="--require ./polyfill-localstorage.cjs" \
  NEXT_PUBLIC_IPFS_BUILD=true NEXT_PUBLIC_IGNORE_BUILD_ERROR=true \
  yarn build

Verify before uploading:

上传前验证:

ls out/*/index.html # Routes exist grep 'og:image' out/index.html # Not localhost stat -f '%Sm' app/page.tsx # Source older than out/ stat -f '%Sm' out/
yarn bgipfs upload out # Save the CID
undefined
ls out/*/index.html # 路由存在 grep 'og:image' out/index.html # 不是localhost stat -f '%Sm' app/page.tsx # 源码时间早于out/ stat -f '%Sm' out/
yarn bgipfs upload out # 保存CID
undefined

Step 5: Share for Approval 👤

步骤5:分享以获得批准 👤

Send: "Build ready for review:
https://community.bgipfs.com/ipfs/<CID>
"
Wait for approval before touching ENS.
发送:“构建已准备好审查:
https://community.bgipfs.com/ipfs/<CID>
在触碰ENS之前等待批准。

Step 6: Set ENS 🤖

步骤6:设置ENS 🤖

Create subdomain (if new) + set IPFS content hash. Two mainnet transactions.
创建子域名(如果是新应用)+ 设置IPFS内容哈希。两笔主网交易。

Step 7: Verify 🤖

步骤7:验证 🤖

  • Content hash matches onchain
  • .eth.link
    gateway responds with 200
  • OG image loads correctly
  • Routes work (
    /debug/
    , etc.)
  • 链上内容哈希匹配
  • .eth.link
    网关返回200状态码
  • OG图片加载正常
  • 路由可正常访问(
    /debug/
    等)

Step 8: Report 👤

步骤8:汇报 👤

"Live at
https://myapp.yourname.eth.link
— ENS content hash confirmed onchain, unfurl metadata set."

“已上线:
https://myapp.yourname.eth.link
——ENS内容哈希已在链上确认,分享元数据已设置完成。”

Build Verification Process

构建验证流程

A build is NOT done when the code compiles. It's done when you've tested it like a real user.
构建完成的标志不是代码编译通过,而是你像真实用户一样完成了测试。

Phase 1: Code QA (Automated)

阶段1:代码QA(自动化)

  • Scan
    .tsx
    files for raw address strings (should use
    <Address/>
    )
  • Scan for shared
    isLoading
    state across multiple buttons
  • Scan for missing
    disabled
    props on transaction buttons
  • Verify RPC config and polling interval
  • Verify OG metadata with absolute URLs
  • Verify no public RPCs in any file
  • 扫描
    .tsx
    文件中的裸地址字符串(应使用
    <Address/>
    组件)
  • 扫描多个按钮之间共享的
    isLoading
    状态
  • 扫描交易按钮上缺失的
    disabled
    属性
  • 验证RPC配置和轮询间隔
  • 验证OG元数据使用绝对URL
  • 验证所有文件中没有使用公共RPC

Phase 2: Smart Contract Testing

阶段2:智能合约测试

bash
forge test                    # All tests pass
forge test --fuzz-runs 10000  # Fuzz testing
Test edge cases: zero amounts, max amounts, unauthorized callers, reentrancy attempts.
bash
forge test                    # 所有测试通过
forge test --fuzz-runs 10000  # 模糊测试
测试边缘情况:零金额、最大金额、未授权调用者、重入攻击尝试。

Phase 3: Browser Testing (THE REAL TEST)

阶段3:浏览器测试(真实测试)

Open the app and do a FULL walkthrough:
  1. Load the app — does it render correctly?
  2. Check page title — is it correct, not "Scaffold-ETH 2"?
  3. Connect wallet — does the connect flow work?
  4. Wrong network — connect on wrong chain, verify "Switch to Base" appears
  5. Switch network — click the switch button, verify it works
  6. Approve flow — verify approve button shows, click it, wait for tx, verify action button appears
  7. Main action — click primary action, verify loader, wait for tx, verify state updates
  8. Error handling — reject a transaction in wallet, verify UI recovers
  9. Address displays — all addresses showing ENS/blockies, not raw hex?
  10. Share URL — check OG unfurl (image, title, description)
打开应用并完成完整的流程测试:
  1. 加载应用 —— 渲染是否正常?
  2. 检查页面标题 —— 是否正确,不是“Scaffold-ETH 2”?
  3. 连接钱包 —— 连接流程是否正常?
  4. 错误网络 —— 连接到错误的链,验证是否显示“切换到Base链”提示
  5. 切换网络 —— 点击切换按钮,验证是否能正常切换
  6. 授权流程 —— 验证授权按钮显示,点击后等待交易完成,验证操作按钮出现
  7. 主操作 —— 点击主要操作按钮,验证加载状态,等待交易完成,验证状态更新
  8. 错误处理 —— 在钱包中拒绝交易,验证UI是否能恢复
  9. 地址显示 —— 所有地址是否显示ENS/区块头像,而不是原始十六进制字符串?
  10. 分享URL —— 检查OG预览(图片、标题、描述)

Phase 4: QA Sub-Agent (Complex Builds)

阶段4:QA子代理(复杂构建)

For bigger projects, spawn a sub-agent with fresh context. Give it the repo path and deployed URL. It reads all code against the UX rules, opens a browser, clicks through independently, and reports issues.

对于大型项目,启动一个带有全新上下文的子代理。提供仓库路径和部署URL。它会根据UX规则检查所有代码,打开浏览器独立完成流程测试,并报告问题。

Don't Do These

禁止操作

  • yarn chain
    — use
    yarn fork --network <chain>
  • forge init
    — use
    npx create-eth@latest
  • ❌ Manual Next.js setup — SE2 handles it
  • ❌ Manual wallet connection — SE2 has RainbowKit pre-configured
  • ❌ Edit
    deployedContracts.ts
    — it's auto-generated by
    yarn deploy
  • ❌ Hardcode API keys in
    scaffold.config.ts
    — use
    .env.local
  • ❌ Use
    mainnet.base.org
    in production — use Alchemy or similar

  • yarn chain
    —— 使用
    yarn fork --network <chain>
  • forge init
    —— 使用
    npx create-eth@latest
  • ❌ 手动搭建Next.js项目 —— SE2会处理所有配置
  • ❌ 手动实现钱包连接 —— SE2已预配置RainbowKit
  • ❌ 编辑
    deployedContracts.ts
    —— 它由
    yarn deploy
    自动生成
  • ❌ 在
    scaffold.config.ts
    中硬编码API密钥 —— 使用
    .env.local
  • ❌ 生产环境使用
    mainnet.base.org
    —— 使用Alchemy或类似服务

Resources

资源