从零构建网站和 Web 应用,使用结构化的计划驱动工作流。触发条件:用户要求创建/构建/搭建网站、Web应用、落地页、管理后台、Dashboard
Web Builder Skill是一项面向实际任务的技能,主要用于通过结构化的计划驱动工作流构建 Web 项目:先搞清楚需求,再选对架构,然后逐页实现;开始前必读 :;
开始任何工作之前,先检查计划文件是否已存在。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
通过结构化的计划驱动工作流构建 Web 项目:先搞清楚需求,再选对架构,然后逐页实现。
开始前必读:
开始任何工作之前,先检查计划文件是否已存在:
查找:当前工作目录下的 .web_builder/plan.md
文件已存在:读取内容,告诉用户上次做到哪了,从当前阶段继续。不要重新开始。
文件不存在:从下面的 Phase 0 开始。
用 plan-template.md 中的模板创建 .web_builder/plan.md。
分轮提问,不要一次性丢一堆问题:
用户回答后立刻更新 plan.md。
| 信号 | 追问 |
|---|---|
| 展示/营销类 | 几个页面?什么设计风格?有品牌色吗? |
| 工具/后台类 | 核心功能?数据从哪来?需要登录吗? |
| 内容/博客类 | 谁来发内容?要评论吗?内容怎么分类? |
| 电商类 | 多少商品?需要支付吗?库存管理? |
第一轮必问,不可跳过。第二轮、第三轮时,若能从用户回答中推断出答案,则无需追问。
推荐方案时直接给出具体技术栈供用户确认,不要问"你想用什么框架?"。参考下表:
| 用户说 | 推断 | 推荐方案 |
|---|---|---|
| "做个博客" | 全栈,需要内容管理 | Next.js + MDX 或 Prisma |
| "做个产品介绍页" | 静态,纯展示 | Vite + Tailwind |
| "做个管理后台" | SPA,复杂交互 | React + shadcn/ui + Zustand |
| "做个xxx,后端用 Python" | 前后端分离 | Vite + FastAPI |
| "做个公司官网" | 静态或简单 SSR | Vite + React 或 Astro |
根据采集结果匹配以下原型之一,更新 plan.md 中的原型、技术栈和目录结构。
static(静态站)匹配条件:纯展示、内容固定、不需要登录、不需要数据库。
技术栈:Vite + React + Tailwind CSS(多页面可选 Astro)
目录结构:
/ ├── src/ │ ├── components/ │ ├── pages/ # 多页面场景 │ ├── assets/ │ ├── App.tsx │ └── main.tsx ├── public/ ├── index.html ├── package.json ├── vite.config.ts ├── tailwind.config.ts └── tsconfig.json
spa(单页应用)匹配条件:复杂交互、管理后台、Dashboard、不需要 SEO。
技术栈:React 18 + Vite + Tailwind + shadcn/ui + Zustand + React Router v7
目录结构:
/ ├── src/ │ ├── components/ │ │ ├── ui/ # shadcn 组件 │ │ └── layout/ # Header, Sidebar, Footer │ ├── pages/ │ ├── hooks/ │ ├── stores/ # Zustand 状态管理 │ ├── services/ # API 调用 │ ├── types/ │ ├── utils/ │ ├── App.tsx │ └── main.tsx ├── public/ ├── package.json ├── vite.config.ts └── tailwind.config.ts
fullstack(全栈一体)匹配条件:需要登录、需要存数据、需要 SEO、动态内容管理。
技术栈:Next.js 15 (App Router) + Tailwind + shadcn/ui + Prisma
目录结构:
/ ├── src/ │ ├── app/ │ │ ├── (public)/ # 公开页面 │ │ ├── (auth)/ # 需要登录的页面 │ │ ├── api/ # API 路由 │ │ ├── layout.tsx │ │ └── page.tsx │ ├── components/ │ ├── lib/ # 数据库、认证等 │ └── types/ ├── prisma/ │ └── schema.prisma ├── public/ └── package.json
separated(前后端分离)匹配条件:明确要求分离、Python 后端、多端共享 API、团队分工。
技术栈: 前端:React + Vite + Tailwind 后端:Express/Fastify (Node) 或 FastAPI (Python)
目录结构:
/ ├── frontend/ │ ├── src/ │ ├── package.json │ └── vite.config.ts # 代理到后端 ├── backend/ │ ├── src/ │ │ ├── routes/ │ │ ├── services/ │ │ ├── models/ │ │ └── index.ts │ └── package.json # Node 后端 │ # 或 app/main.py # Python 后端(依赖在 README 中说明,默认不生成 requirements.txt) └── README.md
拆解所有页面和共享组件,更新 plan.md:
编码注意:
使用 file(brief=..., action=write, path=..., content=...) 工具将内容写入文件:
禁止使用 Python 脚本写入代码文件(会有转义问题)
第1步:项目结构 → 创建目录、配置文件,在依赖管理文件中记录所需依赖(不执行安装) 第2步:全局样式 → Tailwind 配置、CSS 变量/Design Tokens、基础样式 第3步:布局骨架 → Header + Footer + 主内容区(共享布局) 第4步:路由占位 → 所有路由指向占位页面("即将上线") 第5步:逐页实现 → 按路由表顺序,一次一个页面 第6步:数据对接 → 接入真实 API / 数据库(如有)
1. 创建页面文件 + 注册路由 2. 搭页面骨架(用注释划分区域) 3. 从上到下实现各区域 4. 填充模拟数据 5. 响应式检查(手机 → 平板 → 桌面) 6. 接入真实数据(如有) 7. 添加交互和过渡动效 8. 在 plan.md 中标记该页面为 ✅
全部代码写完后,统一安装依赖并验证项目能否正常运行:
1. 安装依赖(前后端分离项目需分别安装;Python 后端用 pip install 一次性安装所需包) 2. 执行构建,确保编译无报错(注意检查导入路径、类型定义、未使用的变量等常见问题) 3. 启动开发服务器,逐一访问各路由确认正常渲染 4. 检查浏览器控制台无红色错误 5. 如有后端:确认 API 接口可正常返回数据
执行 npm 命令时,使用 Python subprocess 并设置正确的编码:
import subprocess
env = dict(subprocess.os.environ)
env["NODE_OPTIONS"] = ""
subprocess.run("npm run build", shell=True, cwd="项目路径",
encoding="utf-8", errors="replace", env=env)
发现问题则修复后重新验证,直到项目能完整跑通。
- [ ] 响应式适配(手机/平板/桌面,手机端无水平滚动) - [ ] 所有可点击元素有 hover/active/focus 状态 - [ ] 加载状态(骨架屏或转圈,不能白屏) - [ ] 错误状态(友好提示,不是报错堆栈) - [ ] 空状态(没有数据时给有用的提示) - [ ] 表单验证 + 行内错误提示 - [ ] favicon 已设置 - [ ] README.md 包含:项目简介、本地启动步骤、目录说明 - [ ] plan.md 所有项目标记为 ✅
最终的 README.md 必须包含:
# 项目名称 一句话描述。 ## 快速开始 ### 环境要求 (根据项目实际情况列出,如 Node.js、Python 等) ### 安装与运行 (本地安装依赖和启动的完整步骤,Python 项目需列出所需的包) ## 目录结构 (简要目录说明) ## 技术栈 (使用的关键技术列表)
build 通过后,启动开发服务器并输出访问地址。
⚠️ 重要:启动和读取地址必须在同一段代码中完成,禁止拆成多段代码。
import subprocess, time, os, re, socket, random
def get_free_port():
"""获取一个可用的随机端口"""
for _ in range(10): # 最多尝试10次
port = random.randint(10000, 65535)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
if s.connect_ex(("127.0.0.1", port)) != 0:
return port
return 5173 # 降级到默认端口
port = get_free_port()
env = dict(os.environ)
env["NODE_OPTIONS"] = ""
process = subprocess.Popen(
f"npx vite --port {port} --host",
shell=True,
cwd="项目路径",
env=env,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
time.sleep(6)
output = process.stdout.read1(65536).decode("utf-8", errors="replace")
print(output)
local_url = network_url = None
for line in output.splitlines():
m = re.search(r"https?://[^s]+", line)
if m:
if "localhost" in line or "127.0.0.1" in line or "Local" in line:
local_url = m.group()
elif "Network" in line:
network_url = m.group()
if local_url:
print(f"本地访问: {local_url}")
if network_url:
print(f"局域网访问: {network_url}")
关键点:
stdin=subprocess.DEVNULL:必须加,防止任何交互式提示阻塞进程npx vite:指定端口和 --host 参数,不依赖 package.json 配置输出访问链接(使用 Markdown 超链接格式 [文本](URL)):
[本地访问 http://localhost:端口](http://localhost:端口)[局域网访问 http://本机IP:端口](http://本机IP:端口)更新 plan.md 标记项目已完成并交付。
UI/UX:
代码:
anyloading="lazy"(或框架等效方案)工程:
package.json 的 scripts 至少有 dev 和 buildrequirements.txt,在 README 的"安装与运行"中列出所需的 pip install 命令| 原则 | 含义 |
|---|---|
| 先规划再动手 | 先写 plan.md,确认后再写代码 |
| 先写后验 | 先写完所有代码,最后统一安装依赖、启动验证 |
| 推断优先 | 能推断就不问,给方案让用户确认/否决 |
| 逐步交付 | 一个页面一个页面做,每步可验证 |
| 计划即真相 | 所有进度记在 plan.md 里,不在聊天记录里 |
相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134.1万人学习
共49课时 | 82.6万人学习
最新文章