ICP用户中心模板
用于Internet计算机(ICP)应用程序的入门模板,具有基于角色的访问控制(RBAC)、Internet身份验证和用户配置文件管理。
特性
- 摩托车后端 具有RBAC(管理员/用户/访客角色)和用户配置文件
- React+TypeScript前端 使用Tailwind CSS和shadcn/ui组件
- 互联网身份 身份验证(使用dev旁路进行本地测试)
- Docker开发容器 使用官方dfinity/icp-dev-env映像
- 第一个用户成为管理员 自动;后续用户获得常规角色
- 管理员仪表板 具有用户管理功能(查看所有用户,分配角色)
快速开始
选项A:VS代码开发容器(推荐)
- 在VS Code中打开此文件夹
- 出现提示时,单击“在容器中重新打开”
- 集装箱码头内部:
dfx start --background
dfx deps pull && dfx deps deploy # Internet Identity canister
dfx deploy # Backend + frontend canisters
npm run dev # Vite dev server on port 5173选项B:本地(需要dfx CLI+Node.js)
npm install
dfx start --background
dfx deps pull && dfx deps deploy
dfx deploy
cd src/frontend && npx vite打开http://localhost:5173在您的浏览器中。
开发人员绕过(跳过Internet身份登录)
对于本地开发,set DEV_BYPASS_II=1 在你的 .env 文件(或作为env-var传递给Vite)以使用确定性身份自动登录:
# Append to .env after dfx deploy generates it
echo "DEV_BYPASS_II=1" >> .env多用户测试
使用 dev_seed URL参数,用于在并行浏览器选项卡中创建不同的测试标识:
| URL | 身份 | 角色 |
|---|---|---|
http://localhost:5173 | 种子0(默认) | 管理员(第一个用户) |
http://localhost:5173?dev_seed=1 | 种子1 | 用户 |
http://localhost:5173?dev_seed=2 | 种子2 | 用户 |
每个种子产生一个唯一的主体。第一个调用后端的用户变为admin。
项目结构
.devcontainer/devcontainer.json # Docker dev container config
dfx.json # ICP canister definitions
package.json # Root workspace config
spec.md # Application specification
port-forward.py # WSL-to-Docker port forwarding utility
src/
backend/
main.mo # Motoko actor: RBAC + user profiles
migration.mo # Schema migration utilities
authorization/
access-control.mo # Role-based permission system
frontend/
index.html # HTML entry point
vite.config.ts # Vite bundler config (import.meta.env)
package.json # Frontend dependencies
tsconfig.json # TypeScript config
tailwind.config.js # Tailwind CSS config
src/
main.tsx # React bootstrap + providers
App.tsx # Auth flow + routing
backend.ts # Candid type converters
hooks/
useInternetIdentity.tsx # II auth + dev bypass
useActor.ts # Backend canister actor (singleton)
useQueries.ts # React Query hooks for all backend calls
pages/
Dashboard.tsx # Admin/user dashboard with tabs
components/
Header.tsx, Footer.tsx # Layout
ProfileTab.tsx # Profile view/edit
ProfileSetupModal.tsx # First-time profile creation
UsersTab.tsx # Admin user management
LoadingScreen.tsx # Loading state
ui/ # shadcn/ui component library定制
- 添加后端功能:编辑
src/backend/main.mo并在中添加相应的钩子src/frontend/src/hooks/useQueries.ts - 添加页面/组件:创建于
src/frontend/src/pages/或src/frontend/src/components/ - 修改角色:编辑
src/backend/authorization/access-control.mo更改权限级别 - 环境变量:Vite暴露前缀为vars的变量
CANISTER_,DFX_,或DEV_通过import.meta.env
用于自动化测试和开发的剧作家MCP
设置
将Playwright MCP服务器添加到Claude代码中:
claude mcp add playwright npx playwright-mcp@latest这将Playwright注册为MCP工具。然后,Claude Code可以使用 init-browser, get-screenshot, execute-code,以及直接使用其他剧作家工具。
端口转发(Docker/WSL设置)
在WSL上运行Docker中的开发容器时,Vite开发服务器(端口5173)和dfx副本(端口4943)位于容器内,不能直接从Playwright运行的WSL主机访问。使用附带的端口转发器:
# Find your container IP
docker inspect | grep IPAddress
# Update CONTAINER_IP in port-forward.py if needed, then run:
python3 port-forward.py &这向前 localhost:5173 和 localhost:4943 从WSL主机到Docker容器,允许Playwright访问应用程序 http://localhost:5173.
如果使用带有自动端口转发的VS代码开发容器,或者在本地运行dfx(不在Docker中),则可以跳过此步骤。
运作原理
在运行开发服务器并配置Playwright MCP的情况下,Claude Code可以:
导航并截图:
# Claude Code uses these MCP tools automatically:
init-browser → open http://localhost:5173
get-screenshot → capture current page state与应用程序交互:
// Claude Code runs Playwright code via execute-code tool:
async function run(page) {
await page.fill('input[placeholder="Enter your name"]', 'Test User');
await page.click('button:has-text("Create Profile")');
await page.waitForTimeout(3000);
}捕获错误和控制台输出:
async function run(page) {
const errors = [];
const logs = [];
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
page.on('pageerror', err => errors.push(err.message));
await page.goto('http://localhost:5173');
await page.waitForTimeout(5000);
return { errors, logs };
}使用并行浏览器上下文进行多用户测试:
async function run(page) {
// Admin user (seed 0) is already on the current page
const adminText = await page.textContent('body');
// Create a second browser context for a different user
const browser = page.context().browser();
const newContext = await browser.newContext();
const page2 = await newContext.newPage();
// Navigate as a different user (seed 1 = non-admin)
await page2.goto('http://localhost:5173?dev_seed=1');
await page2.waitForTimeout(5000);
const userText = await page2.textContent('body');
return {
adminHasUsersTab: adminText.includes('All Users'),
userHasUsersTab: userText.includes('All Users'), // should be false
};
}开发工作流程
典型的Claude Code+Playwright工作流程:
- 进行代码更改 --Claude Code编辑源文件
- 复制到容器 —
docker cp将更新的文件放入正在运行的容器中(Vite HMR会自动获取更改) - 与剧作家一起测试 --导航到应用程序,截图,验证UI状态,检查控制台错误
- 迭代 --如果发现错误,请修复并重新测试,无需人工干预
- 验证源转换 --获取服务源以确认Vite正在正确处理文件:
async function run(page) {
const source = await page.evaluate(async () => {
const r = await fetch('/src/hooks/useInternetIdentity.tsx');
return await r.text();
});
return source.substring(0, 500);
}容器管理
Claude Code也可以直接管理Docker容器:
# Check container status
docker ps --filter name=icp
# Execute commands inside the container
docker exec dfx deploy backend
docker exec dfx canister install backend --mode reinstall # reset state
# Restart Vite after config changes
docker exec bash -c 'kill $(pgrep -f vite)'
docker exec -d bash -c 'cd /workspaces/*/src/frontend && DEV_BYPASS_II=1 npx vite --host 0.0.0.0 --port 5173 > /tmp/vite.log 2>&1'
# Check Vite logs
docker exec cat /tmp/vite.log关键技术细节
- 坦率编码汽车:
?Text映射到TypeScript[] | [string](不是string | undefined).使用toCandidProfile()/fromCandidProfile()在backend.ts为了转换。 - 快速env:用途
envPrefix+envDir(不是process.env).所有源代码使用import.meta.env.X. - 单身演员:
ActorProvider在useActor.ts通过React上下文创建一个共享的HttpAgent/Actor实例。 - 初始化流程:
useInitializeAccessControl()在任何查询触发之前,在RBAC系统中注册用户。
