Skip to content

Lampio Landing — 项目指南

嵌套 CLAUDE.md,工作在 landing/ 下时自动加载。 2026-07-19 从 admin/ 拆出为独立子项目(landing-split-plan.md 方案 C)。


1. 定位

Lampio 的公开产品落地页/)——对外发版后真实外部用户访问的介绍 + 下载页。

  • 物理位置:landing/,与 admin/ 并列的独立 pnpm 项目(自己的 package.json / lockfile / node_modules,非 workspace 成员)。
  • 纯静态:无 Supabase、无 Auth、无 service_role、无任何数据库调用。这是拆分的核心目的 ——公开站与持密钥的 admin 部署解耦(可用性 + 密钥爆炸半径)。

2. 技术栈

Next.js 16.2.3(App Router)· TypeScript strict · Tailwind CSS 4 + shadcn/ui(base-nova)· lucide-react · 动态 OG 图用 next/og · @vercel/analytics(访问统计,见 §3.2)。与 admin 同栈, 但依赖树是裁剪过的子集(无 supabase-js / recharts)。

3. 结构

landing/
├── proxy.ts                 ← i18n 路由代理(Next 16 取代 middleware.ts;无前缀请求按 Accept-Language 重定向 /zh|/en,默认 zh,手写解析零依赖)
├── app/
│   ├── [lang]/              ← 无库 i18n 段(lang ∈ {zh,en});[lang]/layout.tsx = 根 layout
│   │   ├── layout.tsx       ← <html lang> 动态 + generateStaticParams + generateMetadata(per-locale title/OG)
│   │   ├── page.tsx         ← 落地页;getDictionary(lang) 后传 dict slice 给各 section
│   │   └── opengraph-image.tsx  ← 动态社交预览图(next/og,1200×630,per-locale 文案)
│   ├── robots.ts            ← /robots.txt(force-static,全站可抓 + 指向 sitemap)
│   ├── sitemap.ts           ← /sitemap.xml(localizedPaths × locales,每条自带全组 hreflang + x-default)
│   ├── globals.css          ← Tailwind v4 + shadcn 主题
│   └── favicon.ico
├── components/
│   ├── landing/{hero,features,download,footer,lang-switcher}.tsx  ← 组件收 dict slice;lang-switcher 中英切换(hero 右上)
│   └── ui/{button,card,separator}.tsx   ← 从 admin 复制的副本(独立演进)
└── lib/
    ├── dictionaries.ts      ← 无库 i18n 字典(zh/en 对象 + getDictionary;zh 为类型基准 Dictionary=typeof zh)+ `bcp47`(<html lang> 与 hreflang 共用)
    ├── legal.ts             ← 隐私政策 / 服务条款中英长文 + `LAST_UPDATED`(也当法务页的 sitemap lastmod)
    ├── site.ts              ← 站点级 SEO 单一真相源:siteUrl / localizedPaths / alternatesFor()
    └── utils.ts             ← cn()(copy)

3.1 SEO(2026-08-13)

  • 加页面 = 往 lib/site.tslocalizedPaths 加一行,sitemap 自动铺满两种 locale; 再在该页 generateMetadataalternates: alternatesFor(lang, path)
  • 🔒 canonical/hreflang 只放页面级,禁止上提到 [lang]/layout.tsx——layout 的 metadata 会被 privacy/terms 原样继承,canonical 全指向 /zh 首页(比没有 canonical 更糟)。
  • x-default 指向不带 locale 前缀的 URL(//privacy),由 proxy.ts 按 Accept-Language 跳转——正是 Google 说的「自动跳转的通用页」;这类重定向 URL 不进 sitemap 条目本身。
  • hreflang 码取 dictionaries.ts::bcp47,与 <html lang> 同一份:两处不一致时 Google 会整组忽略 hreflang。
  • lastModified:首页读 site.ts::CONTENT_LAST_MODIFIED(改 dictionaries.ts 营销文案时手动更新), 法务页读 legal.ts::LAST_UPDATED刻意不用构建时间——每次部署都变会让爬虫直接无视该字段。

3.2 访问统计(2026-08-13)

@vercel/analytics<Analytics /> 挂在 [lang]/layout.tsx<body> 末尾。选它而非 Plausible/Cloudflare 的理由:脚本从本站域名下发(/_vercel/insights/*)→ 无 cookie、无跨站标识、 大陆可达性与站点本身同命;且 Vercel 本就是托管方 = 隐私政策不新增第三方点名对象。

  • 🔒 它不读任何密钥,与「landing 无 Supabase / 无 service_role」隔离无关,别把它当破口。
  • 与客户端 opt-in 遥测(usage_events,Supabase)不同源、不合流——那是应用内学习行为,这里只有网页流量。
  • 数据要真正开始进:需在 Vercel 项目 → Analytics 面板点一次 Enable(代码侧已就绪,未 enable 时脚本 no-op)。
  • 隐私政策已如实披露(lib/legal.ts 中英各三处:适用范围 / 收集清单 / 第三方处理方 + 摘要); 再动统计口径就要同步改那几段并 bump LAST_UPDATED

i18n(2026-07-24):中英双语走 Next.js 官方「无库 i18n」范式——app/[lang]/ 段 + lib/dictionaries.ts 字典 + proxy.ts Accept-Language 重定向 + lang-switcher/zh /en 真实 URL(利于 SEO/分享/per-locale OG)。零新依赖; proxy 只做 locale 重定向、不触任何密钥,不破坏「无 Supabase/service_role」隔离("纯静态"约束是安全面,非字面零 edge)。 加语言 = 在 locales 加码 + 字典补一份;改文案 = 只动 lib/dictionaries.ts(组件不含硬编码文案)。

components/ui/* + lib/utils.ts 是 admin 的副本(全独立子项目的代价)。landing 极少改这些,与 admin 漂移可接受;真要改共享 UI 时两处各改一次。

4. 环境变量(Vercel)

变量说明
NEXT_PUBLIC_SITE_URL正式域名,修正 OG/metadataBase 基址(域名 = lampio.app,已注册 2026-07-28;代码 fallback 同为 https://lampio.app
NEXT_PUBLIC_DOWNLOAD_URL下载按钮目标(公开 Release 渠道,fallback 占位)

🔒 绝不设 SUPABASE_SERVICE_ROLE_KEY(landing 不需要,设了就毁了拆分的意义)。

5. 开发 / 验证

  • 本地:pnpm dev(默认 3000,可 -p 换端口避让 admin);/ 会按浏览器语言重定向到 /zh/en
  • 验证:pnpm exec tsc --noEmit + pnpm build(无 RB dev-flow skill,非 Tauri)。build 后确认路由树含 /zh /en 两份 + /zh|en/opengraph-image + Proxy (Middleware)
  • ⚠️ 改路由/i18n 后若 tsc 报 .next/types/validator.ts 引用旧文件,先 rm -rf .next && pnpm build 再生成类型再 tsc(Next 类型是 build 产物)

6. 发布

  • Vercel 独立 project,Root Directory=landing
  • 下载渠道 + 拆分收尾详见 docs/plans/archive/landing-split-plan.md