Initial Paprika Next.js implementation

This commit is contained in:
2026-07-06 12:12:36 -04:00
commit 7d585484a6
38 changed files with 14824 additions and 0 deletions

View File

@@ -0,0 +1,670 @@
# 02-项目程序开发详细步骤
## 1. 开发原则
1. 先完整对标 `doc/index.html`,再做工程化拆分。
2. 每一轮开发只领取 `04-任务矩阵.md` 中明确编号的任务,避免重复做。
3. 每一轮必须同步更新:
- `03-推进台账.md`
- `04-任务矩阵.md`
- `05-验收证据.md`
- 必要时更新 `06-决策记录.md`
4. 涉及移民、法律、隐私、退款、attorney referral、表单收集的内容必须留有验收证据和确认记录。
5. 不把明文服务器密码写入长期文档;部署凭据用 SSH key、环境变量或受控密钥库。
## 2. 当前基线复现
目标:确认 `doc/index.html` 当前 mockup 可回溯、可打开、可作为工程化基准。
步骤:
1. 进入项目目录:
```bash
cd /home/mes123456/MeetPaprika
```
2. 确认文件存在:
```bash
test -f doc/index.html && wc -l doc/index.html
```
3. 检查当前页面路由和脚本入口:
```bash
rg -n "pageData|URLSearchParams|data-page|page=start|page=ask|page=terms|page=privacy|page=disclaimer" doc/index.html
```
4. 浏览器打开以下页面并记录截图:
- `doc/index.html?page=home`
- `doc/index.html?page=press`
- `doc/index.html?page=judging`
- `doc/index.html?page=scholarly`
- `doc/index.html?page=services`
- `doc/index.html?page=why`
- `doc/index.html?page=resources`
- `doc/index.html?page=faq`
- `doc/index.html?page=start`
- `doc/index.html?page=ask`
- `doc/index.html?page=terms`
- `doc/index.html?page=privacy`
- `doc/index.html?page=disclaimer`
验收标准:
- 所有公开路由能渲染。
- 未识别 `?page=unknown` 回退 `home`。
- 顶部导航 active 状态正确。
- Resources 下拉可见且链接正确。
- 证据记录写入 `05-验收证据.md`。
## 3. 阶段 A静态 mockup 修复
目标:不引入构建系统,先修复当前单文件中影响体验和转化的明确问题。
任务:
1. 修复 Services 页面 04/05/06 卡片 CTA。
- 已由 `contact` 改为 `start`。
2. 明确 `blog` 和 `about` 是否保留。
- 若保留,加入导航或 footer。
- 若不保留,记录为隐藏路由。
3. 检查 legal 页面日期。
- 已由 `July 10, 2026` 改为 `July 6, 2026`。
- 当前工作日期为 `2026-07-06`。
4. 检查首页、Press、Judging、Services、FAQ、Legal 移动端布局。
5. 补充基础 SEO
- description
- canonical
- Open Graph
- favicon 占位或正式资源
6. 将 mockup 表单明确标注为占位,或进入阶段 B 改为真实表单。
验收标准:
- 无明显死链。
- 所有 CTA 指向存在页面。
- 法务日期有明确确认。
- 桌面和移动端核心页面无明显重叠。
- 变更写入台账和证据。
## 4. 阶段 B真实表单与线索收集
目标Start Here 和 Ask a Question 从视觉 mockup 变成真实可提交入口。
### 推荐字段
Start Here
- name required
- email required
- linkedin
- company_website
- current_role_company
- field_or_industry
- resume_cv optional upload
- reason required
- existing_recognition
- timeline
- consent/disclaimer acknowledgement
Ask a Question
- name required
- email required
- linkedin optional
- resume_cv optional upload
- question required
- consent/disclaimer acknowledgement
### 实现路径选项
| 方案 | 适用 | 优点 | 风险 |
| --- | --- | --- | --- |
| 第三方表单服务 | 快速上线 | 开发少,有后台记录 | 文件上传和隐私策略受限 |
| 自建轻量 API | 需要控制数据 | 可控、可扩展 | 需要安全、日志、备份 |
| CRM 直连 | 销售流程明确 | 直接进入业务系统 | 依赖第三方 API 和权限 |
建议优先级:
1. 若目标是快速 HTTPS 上线:先接第三方表单或 webhook。
2. 若会收 CV/敏感信息:优先自建 API加上传限制和访问控制。
3. 若已有 CRM按 CRM 字段建映射并保留 submission id。
### 表单验收标准
- 必填字段缺失时不能提交。
- email 格式错误时提示。
- 文件上传明确限制类型和大小。
- 成功后有 submission id 或后台记录 id。
- 失败时显示错误状态,不静默跳转。
- disclaimer 可见:提交不创建 attorney-client relationship。
- 验收证据包含页面截图、提交记录、job_id/report_id/submission id。
## 5. 阶段 CNext.js + React + PostgreSQL 工程化
目标:把单文件 mockup 迁移为 Next.js + React 应用,并接入 PostgreSQL形成可维护、可部署、可验收的正式工程。
### 5.1 技术架构
- 前端和服务端框架Next.js + React
- 语言TypeScript
- 样式:先使用全局 CSS / CSS Modules 迁移 `doc/index.html` 视觉;不强行引入 UI 框架
- 数据库PostgreSQL
- ORMPrisma
- 表单校验Zod 或等价 schema 校验
- 部署Node.js 进程监听 `8082`Nginx/Caddy 提供 HTTPS 反向代理
- 验收Playwright 页面截图 + API/数据库写入验证
### 5.2 初始化工程
当前已完成初始化。保留建议命令供复建参考:
```bash
npx create-next-app@latest paprika-site --ts --eslint --app --src-dir=false
cd paprika-site
npm install prisma @prisma/client zod
npx prisma init
```
本项目已直接在当前根目录工程化,并保留 `doc/index.html` 为对标基线。
### 5.3 页面迁移
从 `doc/index.html` 迁移为真实路由:
| 旧路由 | Next.js 路由 |
| --- | --- |
| `?page=home` | `/` |
| `?page=press` | `/press` |
| `?page=judging` | `/judging` |
| `?page=scholarly` | `/scholarly` |
| `?page=services` | `/services` |
| `?page=why` | `/why` |
| `?page=resources` | `/resources` |
| `?page=faq` | `/faq` |
| `?page=start` | `/start` |
| `?page=ask` | `/ask` |
| `?page=thanks` | `/thanks` |
| `?page=terms` | `/terms` |
| `?page=privacy` | `/privacy` |
| `?page=disclaimer` | `/disclaimer` |
隐藏路由 `blog`、`about` 先不要公开,除非产品确认。
### 5.4 PostgreSQL 数据模型初稿
建议最小表:
```prisma
model Submission {
id String @id @default(cuid())
type String
name String
email String
linkedin String?
companyWebsite String?
currentRoleCompany String?
fieldOrIndustry String?
reason String?
existingRecognition String?
timeline String?
question String?
consentAccepted Boolean @default(false)
sourcePath String?
status String @default("new")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
files SubmissionFile[]
}
model SubmissionFile {
id String @id @default(cuid())
submissionId String
fileName String
mimeType String
byteSize Int
storageKey String
createdAt DateTime @default(now())
submission Submission @relation(fields: [submissionId], references: [id])
}
```
字段说明:
- `type``start` 或 `ask`
- `sourcePath`:提交来源,如 `/start`、`/ask`
- `status``new`、`reviewed`、`spam`、`archived`
- 文件上传未落地前,可以先不创建 `SubmissionFile` 或禁用上传。
### 5.5 表单 API
建议 API
```text
POST /api/submissions
```
请求类型:
- `type=start`
- `type=ask`
验收:
- 必填字段缺失返回 400。
- 邮箱格式错误返回 400。
- 成功写入 PostgreSQL 并返回 `submission_id`。
- 前端成功后跳转 `/thanks?submission_id=...` 或展示成功状态。
- 失败时显示明确错误。
### 5.6 环境变量
`.env` 至少包含:
```bash
DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/paprika"
NEXT_PUBLIC_SITE_URL="https://paprikalaw.com"
```
规则:
- `.env` 不提交。
- 服务器凭据和数据库密码不写入 `working` 文档。
- 生产数据库用户只授予应用所需权限。
### 5.7 服务器 PostgreSQL 验证
用户已确认 PostgreSQL 在服务器 `170.106.192.152` 安装完成。正式接入前需要在服务器上验证:
```bash
ssh ubuntu@170.106.192.152
systemctl status postgresql --no-pager
psql --version
sudo -u postgres psql -c '\l'
```
建议创建应用数据库和受限应用用户:
```sql
CREATE DATABASE paprika;
CREATE USER paprika_app WITH ENCRYPTED PASSWORD 'REPLACE_WITH_SECURE_PASSWORD';
GRANT CONNECT ON DATABASE paprika TO paprika_app;
```
进入数据库后授予 schema 权限:
```sql
\c paprika
GRANT USAGE, CREATE ON SCHEMA public TO paprika_app;
```
生产 `DATABASE_URL` 示例:
```bash
DATABASE_URL="postgresql://paprika_app:REPLACE_WITH_SECURE_PASSWORD@127.0.0.1:5432/paprika"
```
注意:
- 不使用 SSH 登录密码作为数据库密码。
- 不把数据库密码写入仓库、`working` 文档或聊天后的可复制文档。
- 如果 PostgreSQL 仅供本机 Next.js 使用,优先监听 `127.0.0.1`,不要对公网开放 5432。
### 5.8 构建和本地验证
```bash
npm install
npm run generate:legacy
npm run prisma:generate
npm run lint
npx tsc --noEmit
npm run build
npm run start -- -p 8082
```
本地生产服务冒烟:
```bash
for p in / /press /judging /scholarly /services /why /resources /faq /start /ask /thanks /terms /privacy /disclaimer /robots.txt /sitemap.xml; do
code=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8082$p)
printf '%s %s\n' "$code" "$p"
done
```
生产数据库迁移:
```bash
npx prisma migrate deploy
```
验收标准:
- `npm run dev` 可本地启动。
- `npm run build` 通过。
- `npm run start -- -p 8082` 可在 8082 启动。
- `npx prisma migrate deploy` 可在生产环境执行。
- 核心页面内容、视觉和 CTA 与 `doc/index.html` 对标。
- Start/Ask 提交能写入 PostgreSQL。当前本地未配置 `DATABASE_URL` 时只能验证 400 校验路径和 500 失败路径,不能关闭入库验收。
## 6. 阶段 D部署到云服务器
目标:让 `https://paprikalaw.com/` 访问目标站点,内部服务端口使用 `8082`。
### 服务器信息
- Host`170.106.192.152`
- User`ubuntu`
- 端口范围:`8080-8099` 已开放
- 本项目端口:`8082`
- 密码:不写入文档;使用用户交接的临时凭据登录后立即配置 SSH key
### 建议部署结构
```text
/opt/paprika/
current/
releases/
shared/
.env
logs/
```
### 基础命令模板
```bash
ssh ubuntu@170.106.192.152
sudo mkdir -p /opt/paprika/releases /opt/paprika/shared/logs
sudo chown -R ubuntu:ubuntu /opt/paprika
```
### Next.js 服务示例
构建并启动:
```bash
npm ci
npm run build
npm run start -- -p 8082
```
生产建议用 systemd
```ini
[Unit]
Description=Paprika static site
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/paprika/current
Environment=NODE_ENV=production
EnvironmentFile=/opt/paprika/shared/.env
ExecStart=/usr/bin/npm run start -- -p 8082
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
### Nginx 反向代理示例
```nginx
server {
listen 80;
server_name paprikalaw.com www.paprikalaw.com;
location / {
proxy_pass http://127.0.0.1:8082;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
HTTPS
```bash
sudo certbot --nginx -d paprikalaw.com -d www.paprikalaw.com
```
验收标准:
- `curl -I http://127.0.0.1:8082` 在服务器上返回 200。
- `curl -I https://paprikalaw.com/` 返回 200。
- `https://paprikalaw.com/`、`/start`、`/faq` 可访问。
- `POST /api/submissions` 能写入 PostgreSQL 并返回 `submission_id`。
- systemd 服务 `active (running)`。
- Nginx 配置通过 `sudo nginx -t`。
- HTTPS 证书有效。
## 7. 阶段 E回归验收
目标:上线前后能证明页面、表单、合规、部署都可用。
### 页面回归
必测页面:
- home
- press
- judging
- scholarly
- services
- why
- resources
- faq
- start
- ask
- thanks
- terms
- privacy
- disclaimer
### 设备尺寸
- Desktop1440x900
- Tablet768x1024
- Mobile390x844
### 验收内容
- 页面可访问。
- 首屏品牌和 CTA 可见。
- Header 不遮挡内容。
- 文本无明显重叠。
- CTA 链接可达。
- 表单可提交或明确是 mockup。
- Footer legal 链接可达。
- Legal disclaimer 可见。
### 证据格式
每次验收写入 `05-验收证据.md`
```text
EV-YYYYMMDD-序号
时间:
任务:
命令/页面:
结果:
证据文件:
job_id/report_id/submission_id
结论:
```
## 8. 阶段 F后续产品增强
可选任务:
- 增加真实 Contact 页面。
- 增加 Blog/Resources 内容系统。
- 增加案例或证据包示例,但必须避免误导和隐私泄露。
- 增加 analytics并同步 Privacy Policy。
- 增加 sitemap、robots、structured data。
- 增加 Playwright screenshot regression。
- 增加后台 leads 管理或 CRM 同步。
## 9. 阶段 G邮箱系统配置与验证
目标:确认 `mail.paprikalaw.com` 邮件系统可用,管理员和普通公司邮箱能登录、收发和承接网站通知。
### 9.1 邮箱入口
- 普通用户网页登录:`https://mail.paprikalaw.com/webmail/`
- 管理员网页登录:`https://mail.paprikalaw.com/admin/`
- 管理员邮箱:`admin@paprikalaw.com`
### 9.2 需要创建或确认的普通邮箱
```text
info@paprikalaw.com
contact@paprikalaw.com
support@paprikalaw.com
sales@paprikalaw.com
marketing@paprikalaw.com
hr@paprikalaw.com
finance@paprikalaw.com
billing@paprikalaw.com
legal@paprikalaw.com
service@paprikalaw.com
```
凭据规则:
- 用户已提供统一初始密码,但不写入长期文档。
- 建议创建后立即为每个邮箱设置独立强密码。
- 如果邮件系统支持启用首次登录改密、2FA、登录审计和反垃圾策略。
### 9.3 DNS 和投递验证
需要确认:
- `mail.paprikalaw.com` A/AAAA 记录正确。
- `paprikalaw.com` MX 记录指向邮件服务器。
- SPF 记录包含授权发件源。
- DKIM 已生成并加入 DNS。
- DMARC 已配置,至少先从 `p=none` 观察。
- 反向 DNS/PTR 与邮件服务器发信域名匹配。
建议验证:
```bash
dig MX paprikalaw.com
dig TXT paprikalaw.com
dig TXT default._domainkey.paprikalaw.com
dig TXT _dmarc.paprikalaw.com
```
### 9.4 网站表单通知接入
Next.js 表单写入 PostgreSQL 后,可选邮件通知:
- 发件邮箱:建议 `support@paprikalaw.com` 或专用 `no-reply@paprikalaw.com`
- 收件邮箱:建议 `support@paprikalaw.com`、`contact@paprikalaw.com`
- 表单类型:
- `/start` 提交通知
- `/ask` 提交通知
- 邮件内容不得包含完整敏感 CV 文件,只发送 submission id 和后台查看提示。
环境变量示例:
```bash
SMTP_HOST="mail.paprikalaw.com"
SMTP_PORT="587"
SMTP_USER="support@paprikalaw.com"
SMTP_PASSWORD="REPLACE_WITH_SECURE_PASSWORD"
LEADS_NOTIFY_TO="support@paprikalaw.com,contact@paprikalaw.com"
```
验收标准:
- 管理员能登录 admin。
- 10 个普通邮箱能登录 webmail。
- 至少完成一封内部互发、一封外部收信、一封外部发信测试。
- SPF/DKIM/DMARC 检查通过或有明确待处理项。
- 表单邮件通知如启用,必须记录 message id 或测试截图。
## 10. 每轮工作固定流程
1. 查看 `04-任务矩阵.md`,领取一个或一组任务。
2. 查看相关决策:`06-决策记录.md`。
3. 修改代码或文档。
4. 执行对应验证。
5. 将证据写入 `05-验收证据.md`。
6. 更新任务状态。
7. 在 `03-推进台账.md` 记录:
- 本轮做了什么
- 改了哪些文件
- 验证了什么
- 下一步是什么
## 11. 完全对标核验清单
每次声称“已完全对标 `doc/index.html`”时,至少执行以下核验。
### 10.1 源文件结构核验
```bash
wc -l doc/index.html
rg -n 'function [A-Za-z0-9_]+\(|const [A-Za-z0-9_]+ =|href="\?page=|Last updated|Packages start|@media|--[a-z-]+:' doc/index.html
```
验收:
- 记录 `doc/index.html` 行数。
- 记录 CSS token、断点、路由、CTA、函数、法务日期、价格文案。
### 10.2 页面和函数映射核验
```bash
rg -n 'pageData|home:|press:|judging:|scholarly:|services:|why:|resources:|faq:|blog:|start:|ask:|thanks:|about:|terms:|privacy:|disclaimer:' doc/index.html
rg -n 'function (hero|heroWithKicker|servicesCta|card|pressPage|judgingPage|scholarlyPage|o1CriteriaPage|faqPage|legalTermsPage|legalPrivacyPage|legalDisclaimerPage)' doc/index.html
```
验收:
- `01-项目功能内容.md` 中的路由清单与 `pageData` 保持一致。
- 使用中函数、未调用函数都有记录。
- 隐藏路由 `blog`、`about` 不被误删。
### 10.3 链接和 CTA 核验
```bash
rg -n 'href="\?page=|card\("' doc/index.html
```
验收:
- Header、footer、hero、services CTA、form mockup、thanks、service card 链接全部登记。
- 不存在的 `contact` 路由历史缺陷必须保留在风险和任务矩阵中;修复后记录验收证据。
### 10.4 Legal 和 FAQ 核验
```bash
sed -n '2870,3035p' doc/index.html
sed -n '3070,3228p' doc/index.html
```
验收:
- FAQ 4 组 20 个问题记录完整。
- Terms、Privacy、Disclaimer section 数量和标题记录完整。
- Terms 缺少 17、legal 日期晚于当前日期、原文语法风险均进入任务矩阵。
### 10.5 视觉样式核验
```bash
rg -n '^\\s*\\.[A-Za-z0-9_-]+|@media|grid-template-columns|width: min|border-radius|background:' doc/index.html
```
验收:
- CSS token、布局宽度、卡片、表单、Press、Judging、FAQ、Legal、响应式断点在文档中有对应说明。
- 后续工程化拆分不能只迁移内容,必须迁移视觉规则。