Files
dalcode-website/docs/superpowers/plans/2026-05-23-website-redesign.md
2026-05-30 14:00:38 +08:00

2471 lines
81 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DAL Website Redesign Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Transform dalcode-website from a single-product Webflow-template site into a product-matrix platform site for DAL Code, DAL CLI, DAL Office, and DeepAILab API Platform.
**Architecture:** Replace webflow.css (11K lines) with Tailwind utility classes. Keep GSAP for scroll animations, remove Lottie. Remove next-themes (dark-only). Retain next-intl for zh-CN/en bilingual support. All new content goes through i18n message files.
**Tech Stack:** Next.js 16.2.4, React 19, Tailwind CSS 4, GSAP 3, next-intl 4, React Hook Form + Zod
**Key constraint:** All copy must be smart, polished, and sophisticated — not generic/cheap-sounding. The user explicitly said "文案一定要智能灵活,不要太 low".
**AGENTS.md warning:** Next.js 16 may have breaking API changes. Before writing any code, check `node_modules/next/dist/docs/` for current conventions. Key findings from review: `page.tsx`, `layout.tsx`, `not-found.tsx` conventions unchanged. `middleware` is deprecated in favor of `proxy`.
---
## File Structure
### New files
```
app/
├── globals.css (REWRITE — pure Tailwind, no webflow refs)
├── code/page.tsx (DAL Code product page)
├── cli/page.tsx (DAL CLI product page)
├── office/page.tsx (DAL Office page)
├── platform/page.tsx (API Platform page)
├── pricing/page.tsx (Unified pricing page)
components/
├── Header.tsx (REWRITE — new nav with Products dropdown)
├── Footer.tsx (REWRITE — 4-column layout)
├── GsapAnimations.tsx (MODIFY — update selectors for new sections)
├── ScrollReveal.tsx (NEW — reusable scroll-reveal wrapper)
├── home/
│ ├── HeroSection.tsx (REWRITE)
│ ├── ProductEcosystem.tsx (NEW — 2×2 product cards)
│ ├── WorkflowSteps.tsx (NEW — 3-step Intent/Build/Ship)
│ ├── FeatureGrid.tsx (NEW — 8-feature grid)
│ ├── EcosystemSection.tsx (NEW — DeepAILab platform)
│ ├── BottomCta.tsx (NEW — bottom CTA)
│ ├── FaqSection.tsx (NEW — accordion FAQ)
│ └── index.ts (REWRITE — export new components)
lib/
├── site-content.ts (REWRITE — new data structures)
```
### Files to delete
```
app/webflow.css (11K lines, replaced by Tailwind)
components/ThemeToggle.tsx (no more theme switching)
components/LottiePlayer.tsx (removing Lottie)
components/home/IntegrationsSection.tsx (replaced by ProductEcosystem)
components/home/PrinciplesSection.tsx (replaced by WorkflowSteps)
components/home/BlogPreviewSection.tsx (removed from homepage)
components/home/CtaSection.tsx (replaced by BottomCta)
```
### Message files to rewrite
```
messages/zh-CN.json (full rewrite with new content)
messages/en.json (full rewrite with new content)
```
---
## Task 1: Foundation — Remove webflow.css, set up dark Tailwind base
**Files:**
- Delete: `app/webflow.css`
- Rewrite: `app/globals.css`
- Modify: `app/layout.tsx`
- Delete: `components/ThemeToggle.tsx`
- Delete: `components/LottiePlayer.tsx`
- [ ] **Step 1: Create the new globals.css**
Replace the entire `app/globals.css` with a Tailwind-first dark theme foundation:
```css
@import "tailwindcss";
@theme {
--color-bg-primary: #0a0a0a;
--color-bg-secondary: #111111;
--color-bg-card: #161616;
--color-bg-card-hover: #1a1a1a;
--color-border: #222222;
--color-border-hover: #333333;
--color-text-primary: #f0f0f0;
--color-text-secondary: #a0a0a0;
--color-text-muted: #666666;
--color-accent: #6366f1;
--color-accent-hover: #818cf8;
--color-accent-glow: rgba(99, 102, 241, 0.15);
--font-sans: var(--font-inter), ui-sans-serif, system-ui, sans-serif;
--font-display: var(--font-inter-tight), var(--font-sans);
}
html {
scroll-behavior: smooth;
}
body {
@apply bg-bg-primary text-text-primary antialiased;
font-family: var(--font-sans);
}
::selection {
@apply bg-accent/30 text-text-primary;
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--color-border-hover); }
/* Shared animation classes used by GSAP */
.reveal-up {
opacity: 0;
transform: translateY(40px);
}
.reveal-visible {
opacity: 1;
transform: translateY(0);
transition: opacity 0.6s ease, transform 0.6s ease;
}
/* Glow effect for cards */
.card-glow {
position: relative;
}
.card-glow::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1px;
background: linear-gradient(135deg, transparent, var(--color-accent-glow), transparent);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
opacity: 0;
transition: opacity 0.3s ease;
}
.card-glow:hover::before {
opacity: 1;
}
/* Stagger children animation delay */
.stagger-children > * {
opacity: 0;
transform: translateY(20px);
}
```
- [ ] **Step 2: Update layout.tsx — remove webflow.css, ThemeProvider, Lottie**
Replace `app/layout.tsx`:
```tsx
import type { Metadata } from "next"
import { Inter, Inter_Tight } from "next/font/google"
import { NextIntlClientProvider } from "next-intl"
import { getLocale, getMessages } from "next-intl/server"
import Header from "@/components/Header"
import Footer from "@/components/Footer"
import GsapAnimations from "@/components/GsapAnimations"
import { SITE_BRAND, SITE_DESCRIPTION, SITE_NAME } from "@/lib/site-content"
import "./globals.css"
const inter = Inter({
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
variable: "--font-inter",
display: "swap",
})
const interTight = Inter_Tight({
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
variable: "--font-inter-tight",
display: "swap",
})
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000"
export const metadata: Metadata = {
metadataBase: new URL(SITE_URL),
title: {
default: SITE_BRAND,
template: `%s | ${SITE_NAME}`,
},
description: SITE_DESCRIPTION,
icons: {
icon: "/favicon.ico",
apple: "/assets/dalcode-app-icon-192.png",
},
openGraph: {
type: "website",
siteName: SITE_BRAND,
title: SITE_BRAND,
description: SITE_DESCRIPTION,
},
}
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const locale = await getLocale()
const messages = await getMessages()
return (
<NextIntlClientProvider locale={locale} messages={messages}>
<html
lang={locale}
className={`${inter.variable} ${interTight.variable}`}
>
<body className={inter.className}>
<Header />
<main>{children}</main>
<Footer />
<GsapAnimations />
</body>
</html>
</NextIntlClientProvider>
)
}
```
- [ ] **Step 3: Delete obsolete files**
```bash
rm app/webflow.css
rm components/ThemeToggle.tsx
rm components/LottiePlayer.tsx
rm components/RevealObserver.tsx
rm components/PageTransition.tsx
```
- [ ] **Step 4: Verify build compiles**
```bash
cd /Users/leon/本地开发项目/claude-code/dalcode-website && npx next build 2>&1 | tail -20
```
Expected: Build may fail due to import references in other files. That's OK — we'll fix them in subsequent tasks. The goal here is that `globals.css` and `layout.tsx` are correct.
- [ ] **Step 5: Commit**
```bash
git add -A
git commit -m "chore: remove webflow.css and theme toggle, set up dark Tailwind foundation"
```
---
## Task 2: i18n Content — Rewrite all message files
**Files:**
- Rewrite: `messages/zh-CN.json`
- Rewrite: `messages/en.json`
The copy below is the heart of the redesign. Every string must be polished — no filler, no "lorem ipsum energy".
- [ ] **Step 1: Write zh-CN.json**
```json
{
"site": {
"name": "DAL",
"brand": "DAL by DeepAILab",
"tagline": "The Open AI Development Platform",
"description": "从想法到产品的完整 AI 开发平台。自由选模型,全链路覆盖,一个账号搞定一切。"
},
"nav": {
"products": "产品",
"docs": "文档",
"pricing": "定价",
"blog": "博客",
"community": "社区",
"downloads": "下载",
"signIn": "登录",
"toggleMenu": "切换菜单",
"productItems": {
"code": { "name": "DAL Code", "tagline": "AI 原生开发环境" },
"cli": { "name": "DAL CLI", "tagline": "终端里的 AI 搭档" },
"office": { "name": "DAL Office", "tagline": "AI 文档工作台" },
"platform": { "name": "API Platform", "tagline": "统一 AI 开发者平台" }
}
},
"hero": {
"badge": "by DeepAILab",
"headline": "开放的 AI 开发平台",
"subheadline": "从想法到产品,自由选模型,从代码到文档全覆盖。一个账号,完整生态。",
"ctaPrimary": "下载 DAL Code",
"ctaSecondary": "安装 CLI",
"cliCommand": "curl -fsSL https://cli.deepailab.ai/install | bash"
},
"ecosystem": {
"label": "PRODUCT ECOSYSTEM",
"title": "一个平台,覆盖 AI 开发全场景",
"products": {
"code": {
"name": "DAL Code",
"tagline": "AI 原生开发环境",
"description": "不只是写代码的编辑器,而是从需求澄清到工程交付的完整工作台。",
"features": ["Intent Capture", "Mission Mode", "多模型路由"],
"cta": "了解 DAL Code"
},
"cli": {
"name": "DAL CLI",
"tagline": "终端里的 AI 开发搭档",
"description": "轻量、快速、管道友好。在终端里完成从 Agent 任务到代码交付的全流程。",
"features": ["Agent 执行", "管道集成", "轻量高速"],
"cta": "了解 DAL CLI"
},
"office": {
"name": "DAL Office",
"tagline": "AI 驱动的文档工作台",
"description": "用 AI 生成和编辑文档、表格、演示文稿——开发者的工作不只有代码。",
"features": ["Word", "Excel", "PPT"],
"cta": "了解 DAL Office"
},
"platform": {
"name": "API Platform",
"tagline": "统一 AI 开发者平台",
"description": "模型聚合、智能路由、成本优化——所有 DAL 产品背后的基础设施。",
"features": ["模型聚合", "智能路由", "API 折扣"],
"cta": "探索平台"
}
}
},
"workflow": {
"label": "HOW IT WORKS",
"title": "不是更好的 prompt,是更好的工作方式",
"steps": {
"intent": {
"number": "01",
"name": "INTENT",
"title": "先把需求想清楚",
"description": "AI 主动采访你,用结构化问题把模糊想法变成可执行的工程需求——不是等你写出完美的 prompt。"
},
"build": {
"number": "02",
"name": "BUILD",
"title": "智能拆解,并行执行",
"description": "Agent 自动分解任务,为每个子任务选择最优模型,多线并行推进——你监督方向,它负责落地。"
},
"ship": {
"number": "03",
"name": "SHIP",
"title": "代码、测试、文档一起交付",
"description": "不只是输出代码片段。测试、文档同步生成,关键操作需要你的审批,结果全程可追溯。"
}
}
},
"features": {
"label": "EVERYTHING YOU NEED",
"title": "为认真做产品的开发者而建",
"items": {
"routing": {
"title": "多模型智能路由",
"description": "同一工作流里,不同子任务自动匹配最优模型。质量、速度、成本不再是单选题。"
},
"skills": {
"title": "Skills 引擎",
"description": "把工程经验封装成可复用的引导式工作流。不是 prompt 模板,是方法论的产品化。"
},
"mission": {
"title": "Mission Mode",
"description": "复杂任务自动拆解,进度实时可见,断点可续跑。长任务终于不再是黑盒。"
},
"byok": {
"title": "自带 API Key",
"description": "用你自己的 API Key 接入任何模型。不被平台绑定,完全掌控成本和数据流向。"
},
"context": {
"title": "上下文引擎",
"description": "五层智能压缩,让百万行项目也能保持上下文连贯。大项目不再是 AI 的盲区。"
},
"audit": {
"title": "审批与审计",
"description": "危险操作需人工确认,每一步操作可追溯可审计。给个人效率,给团队安全感。"
},
"rag": {
"title": "知识库接入",
"description": "连接你的私有文档和知识库,AI 的回答基于你的真实上下文,而不是通用训练数据。"
},
"cost": {
"title": "成本透明化",
"description": "每次 AI 交互的成本实时可见。花了多少、省了多少,用数据说话。"
}
}
},
"platform": {
"label": "ONE PLATFORM, ONE ACCOUNT",
"title": "DeepAILab — 连接一切的 AI 开发者平台",
"advantages": {
"account": {
"title": "一个账号",
"description": "登录一次,Code、CLI、Office、API Platform 全部打通。无缝切换,统一管理。"
},
"discount": {
"title": "API 折扣",
"description": "通过平台调用主流模型,费率优于直连。用得越多,省得越多。"
},
"dashboard": {
"title": "成本仪表盘",
"description": "跨产品的用量统计和成本拆解,一目了然。告别月底账单惊喜。"
}
},
"cta": "探索 DeepAILab 平台"
},
"bottomCta": {
"headline": "准备好用新方式开发了吗?",
"subheadline": "从一次 Intent 采访开始,让 AI 先帮你想清楚要做什么。",
"ctaPrimary": "下载 DAL Code",
"ctaSecondary": "安装 CLI"
},
"faq": {
"label": "FAQ",
"title": "常见问题",
"items": {
"vsCursor": {
"q": "DAL Code 和 Cursor / Windsurf 有什么不同?",
"a": "Cursor 和 Windsurf 的核心是让你写更好的代码。DAL Code 的起点更早——它先帮你把需求想清楚,再把任务拆解、执行和交付。同时,DAL 不绑定单一模型,支持多模型智能路由和自带 API Key。"
},
"vsClaude": {
"q": "DAL CLI 和 Claude Code CLI 有什么不同?",
"a": "Claude Code 绑定 Anthropic 模型生态。DAL CLI 支持多模型路由,可以用你自己的 API Key,并且和 DAL Code、DAL Office 共享同一个账号和工作流体系。"
},
"byok": {
"q": "我可以用自己的 API Key 吗?",
"a": "可以。DAL 支持接入你自己的 API Key,包括 OpenAI、Anthropic、Google 等主流提供商。你也可以使用 DeepAILab 平台提供的 API 折扣。"
},
"apiDiscount": {
"q": "DeepAILab API 折扣怎么计算?",
"a": "通过 DeepAILab 平台统一调用模型 API,费率低于各厂商直连价格。具体折扣取决于用量层级,详见定价页面。"
},
"models": {
"q": "支持哪些 AI 模型?",
"a": "支持 Claude (Opus/Sonnet/Haiku)、GPT 系列、Gemini 系列等 20+ 主流模型,并持续接入新模型。Smart Routing 会根据任务类型自动选择最合适的模型。"
},
"enterprise": {
"q": "支持企业私有化部署吗?",
"a": "私有化部署、SSO、审计日志和自定义安全策略是产品路线的重点方向。如果你的团队有明确需求,欢迎联系我们从一个具体场景开始落地。"
}
}
},
"footer": {
"newsletter": {
"placeholder": "输入邮箱,订阅产品动态",
"submit": "订阅",
"success": "已订阅。",
"error": "订阅失败,请重试。"
},
"groups": {
"products": "产品",
"resources": "资源",
"community": "社区",
"company": "公司"
},
"links": {
"code": "DAL Code",
"cli": "DAL CLI",
"office": "DAL Office",
"apiPlatform": "API Platform",
"pricing": "定价",
"docs": "文档",
"blog": "博客",
"changelog": "更新日志",
"faq": "FAQ",
"discord": "Discord",
"github": "GitHub",
"twitter": "X / Twitter",
"about": "关于",
"careers": "加入我们",
"contact": "联系"
},
"copyright": "© 2026 DeepAILab. All rights reserved.",
"privacy": "隐私政策",
"terms": "服务条款"
},
"codePage": {
"hero": {
"label": "DAL CODE",
"headline": "不只是编辑器,是 AI 工程工作台",
"subheadline": "从需求采访到代码交付,一个工作台覆盖完整开发流程。Intent Capture 让 AI 先帮你想清楚要做什么,Mission Mode 让复杂任务自动拆解执行。",
"cta": "下载 DAL Code"
}
},
"cliPage": {
"hero": {
"label": "DAL CLI",
"headline": "终端里的 AI 开发搭档",
"subheadline": "轻量、快速、管道友好。在你熟悉的终端环境里,用 Agent 完成从需求到代码的全流程。",
"cta": "安装 DAL CLI",
"cliCommand": "curl -fsSL https://cli.deepailab.ai/install | bash"
}
},
"officePage": {
"hero": {
"label": "DAL OFFICE",
"headline": "AI 驱动的文档工作台",
"subheadline": "开发者的工作不只有代码。用 AI 生成和编辑 Word 文档、Excel 表格、PPT 演示文稿——和 DAL Code 无缝协作。",
"cta": "了解 DAL Office"
}
},
"platformPage": {
"hero": {
"label": "API PLATFORM",
"headline": "所有 DAL 产品背后的 AI 基础设施",
"subheadline": "模型聚合、智能路由、成本优化、用量分析——一个平台,为所有 AI 开发场景提供统一的基础能力。",
"cta": "探索 API Platform"
}
},
"pricingPage": {
"hero": {
"label": "PRICING",
"headline": "简单透明的定价",
"subheadline": "从个人开发者到企业团队,选择适合你的方案。"
}
},
"about": {
"hero": {
"label": "ABOUT",
"headline": "我们在构建下一代 AI 开发基础设施",
"subheadline": "DeepAILab 相信 AI 开发工具应该是开放的、可组合的、为开发者真正服务的。"
}
},
"contact": {
"hero": {
"label": "CONTACT",
"headline": "和我们聊聊你的真实场景",
"subheadline": "无论是产品试用、企业方案还是生态合作,从一个具体场景开始。"
}
},
"blog": {
"hero": {
"label": "BLOG",
"headline": "产品思考与工程实践",
"subheadline": "关于 AI 开发工具、多模型路由、工程工作流的深度内容。"
}
},
"common": {
"learnMore": "了解更多",
"getStarted": "开始使用",
"comingSoon": "即将推出",
"backToHome": "返回首页"
}
}
```
- [ ] **Step 2: Write en.json**
```json
{
"site": {
"name": "DAL",
"brand": "DAL by DeepAILab",
"tagline": "The Open AI Development Platform",
"description": "The complete AI development platform. Choose your models, cover the full workflow, one account for everything."
},
"nav": {
"products": "Products",
"docs": "Docs",
"pricing": "Pricing",
"blog": "Blog",
"community": "Community",
"downloads": "Downloads",
"signIn": "Sign In",
"toggleMenu": "Toggle menu",
"productItems": {
"code": { "name": "DAL Code", "tagline": "AI-native development environment" },
"cli": { "name": "DAL CLI", "tagline": "Your AI partner in the terminal" },
"office": { "name": "DAL Office", "tagline": "AI-powered document workspace" },
"platform": { "name": "API Platform", "tagline": "Unified AI developer platform" }
}
},
"hero": {
"badge": "by DeepAILab",
"headline": "The Open AI Development Platform",
"subheadline": "From idea to production. Choose your models, cover the full workflow from code to docs. One account, complete ecosystem.",
"ctaPrimary": "Download DAL Code",
"ctaSecondary": "Install CLI",
"cliCommand": "curl -fsSL https://cli.deepailab.ai/install | bash"
},
"ecosystem": {
"label": "PRODUCT ECOSYSTEM",
"title": "One platform, every AI development scenario",
"products": {
"code": {
"name": "DAL Code",
"tagline": "AI-native development environment",
"description": "More than a code editor — a complete workspace from requirements clarification to engineering delivery.",
"features": ["Intent Capture", "Mission Mode", "Multi-model Routing"],
"cta": "Explore DAL Code"
},
"cli": {
"name": "DAL CLI",
"tagline": "Your AI development partner in the terminal",
"description": "Lightweight, fast, pipeline-friendly. Run agent tasks and ship code from your terminal.",
"features": ["Agent Execution", "Pipeline Integration", "Lightweight"],
"cta": "Explore DAL CLI"
},
"office": {
"name": "DAL Office",
"tagline": "AI-powered document workspace",
"description": "Generate and edit documents, spreadsheets, and presentations with AI — because developers do more than write code.",
"features": ["Word", "Excel", "PPT"],
"cta": "Explore DAL Office"
},
"platform": {
"name": "API Platform",
"tagline": "Unified AI developer platform",
"description": "Model aggregation, smart routing, cost optimization — the infrastructure behind every DAL product.",
"features": ["Model Aggregation", "Smart Routing", "API Discounts"],
"cta": "Explore Platform"
}
}
},
"workflow": {
"label": "HOW IT WORKS",
"title": "Not a better prompt. A better workflow.",
"steps": {
"intent": {
"number": "01",
"name": "INTENT",
"title": "Clarify what you're building",
"description": "AI interviews you with structured questions, turning vague ideas into actionable engineering requirements — no perfect prompt needed."
},
"build": {
"number": "02",
"name": "BUILD",
"title": "Decompose and execute in parallel",
"description": "Agents break down tasks, select the optimal model for each subtask, and execute in parallel — you steer, they build."
},
"ship": {
"number": "03",
"name": "SHIP",
"title": "Code, tests, and docs — delivered together",
"description": "Not just code snippets. Tests and documentation generated in sync, critical actions require your approval, full audit trail."
}
}
},
"features": {
"label": "EVERYTHING YOU NEED",
"title": "Built for developers who ship",
"items": {
"routing": {
"title": "Multi-model Smart Routing",
"description": "Each subtask automatically matched to the optimal model. Quality, speed, and cost are no longer trade-offs."
},
"skills": {
"title": "Skills Engine",
"description": "Engineering experience packaged as reusable guided workflows. Not prompt templates — methodology as a product."
},
"mission": {
"title": "Mission Mode",
"description": "Complex tasks decomposed automatically, progress visible in real time, resume from any breakpoint."
},
"byok": {
"title": "Bring Your Own Key",
"description": "Connect your own API keys from any provider. No vendor lock-in, full control over cost and data flow."
},
"context": {
"title": "Context Engine",
"description": "Five-layer intelligent compression keeps context coherent across million-line projects."
},
"audit": {
"title": "Approval & Audit",
"description": "Critical actions require human confirmation. Every step traceable, every decision auditable."
},
"rag": {
"title": "Knowledge Integration",
"description": "Connect your private docs and knowledge bases. AI answers grounded in your real context, not generic training data."
},
"cost": {
"title": "Cost Transparency",
"description": "Real-time cost visibility for every AI interaction. See what you spend and what you save."
}
}
},
"platform": {
"label": "ONE PLATFORM, ONE ACCOUNT",
"title": "DeepAILab — The AI developer platform that connects everything",
"advantages": {
"account": {
"title": "One Account",
"description": "Sign in once. Code, CLI, Office, and API Platform — all connected, all managed from one place."
},
"discount": {
"title": "API Discounts",
"description": "Access leading models through the platform at better rates than direct connections."
},
"dashboard": {
"title": "Cost Dashboard",
"description": "Cross-product usage analytics and cost breakdown at a glance. No more billing surprises."
}
},
"cta": "Explore DeepAILab Platform"
},
"bottomCta": {
"headline": "Ready to build the new way?",
"subheadline": "Start with an Intent interview. Let AI help you figure out what to build.",
"ctaPrimary": "Download DAL Code",
"ctaSecondary": "Install CLI"
},
"faq": {
"label": "FAQ",
"title": "Frequently Asked Questions",
"items": {
"vsCursor": {
"q": "How is DAL Code different from Cursor or Windsurf?",
"a": "Cursor and Windsurf focus on helping you write better code. DAL Code starts earlier — it helps you clarify what to build before decomposing, executing, and delivering the work. It also supports multi-model routing and bring-your-own API keys."
},
"vsClaude": {
"q": "How is DAL CLI different from Claude Code?",
"a": "Claude Code is tied to the Anthropic model ecosystem. DAL CLI supports multi-model routing, your own API keys, and shares the same account and workflow system with DAL Code and DAL Office."
},
"byok": {
"q": "Can I use my own API keys?",
"a": "Yes. DAL supports connecting your own API keys from OpenAI, Anthropic, Google, and other major providers. You can also take advantage of DeepAILab platform API discounts."
},
"apiDiscount": {
"q": "How do DeepAILab API discounts work?",
"a": "Calling model APIs through the DeepAILab platform costs less than connecting to providers directly. Exact discounts depend on your usage tier — see the pricing page for details."
},
"models": {
"q": "Which AI models are supported?",
"a": "We support Claude (Opus/Sonnet/Haiku), GPT series, Gemini series, and 20+ other leading models, with new models added continuously. Smart Routing automatically selects the best model for each task."
},
"enterprise": {
"q": "Do you support enterprise private deployment?",
"a": "Private deployment, SSO, audit logs, and custom security policies are priority items on our roadmap. If your team has specific requirements, contact us to start with a concrete use case."
}
}
},
"footer": {
"newsletter": {
"placeholder": "Your email for product updates",
"submit": "Subscribe",
"success": "Subscribed.",
"error": "Failed to subscribe. Please try again."
},
"groups": {
"products": "Products",
"resources": "Resources",
"community": "Community",
"company": "Company"
},
"links": {
"code": "DAL Code",
"cli": "DAL CLI",
"office": "DAL Office",
"apiPlatform": "API Platform",
"pricing": "Pricing",
"docs": "Docs",
"blog": "Blog",
"changelog": "Changelog",
"faq": "FAQ",
"discord": "Discord",
"github": "GitHub",
"twitter": "X / Twitter",
"about": "About",
"careers": "Careers",
"contact": "Contact"
},
"copyright": "© 2026 DeepAILab. All rights reserved.",
"privacy": "Privacy",
"terms": "Terms"
},
"codePage": {
"hero": {
"label": "DAL CODE",
"headline": "Not just an editor. An AI engineering workspace.",
"subheadline": "From requirements interview to code delivery, one workspace covering the complete development workflow. Intent Capture helps you think clearly, Mission Mode handles the heavy lifting.",
"cta": "Download DAL Code"
}
},
"cliPage": {
"hero": {
"label": "DAL CLI",
"headline": "Your AI development partner in the terminal",
"subheadline": "Lightweight, fast, pipeline-friendly. Use agents to go from requirements to shipped code, right in your terminal.",
"cta": "Install DAL CLI",
"cliCommand": "curl -fsSL https://cli.deepailab.ai/install | bash"
}
},
"officePage": {
"hero": {
"label": "DAL OFFICE",
"headline": "AI-powered document workspace",
"subheadline": "Developers do more than write code. Generate and edit Word documents, Excel spreadsheets, and PowerPoint presentations with AI — seamlessly connected to DAL Code.",
"cta": "Explore DAL Office"
}
},
"platformPage": {
"hero": {
"label": "API PLATFORM",
"headline": "The AI infrastructure behind every DAL product",
"subheadline": "Model aggregation, smart routing, cost optimization, usage analytics — one platform providing unified capabilities for every AI development scenario.",
"cta": "Explore API Platform"
}
},
"pricingPage": {
"hero": {
"label": "PRICING",
"headline": "Simple, transparent pricing",
"subheadline": "From individual developers to enterprise teams, choose the plan that fits."
}
},
"about": {
"hero": {
"label": "ABOUT",
"headline": "Building next-generation AI development infrastructure",
"subheadline": "DeepAILab believes AI development tools should be open, composable, and built to genuinely serve developers."
}
},
"contact": {
"hero": {
"label": "CONTACT",
"headline": "Tell us about your real-world scenario",
"subheadline": "Whether it's a product trial, enterprise deployment, or ecosystem partnership — start with a concrete use case."
}
},
"blog": {
"hero": {
"label": "BLOG",
"headline": "Product thinking and engineering practice",
"subheadline": "Deep dives on AI development tools, multi-model routing, and engineering workflows."
}
},
"common": {
"learnMore": "Learn more",
"getStarted": "Get started",
"comingSoon": "Coming soon",
"backToHome": "Back to home"
}
}
```
- [ ] **Step 3: Commit**
```bash
git add messages/
git commit -m "feat: rewrite i18n content for platform redesign"
```
---
## Task 3: Site content data + ScrollReveal component
**Files:**
- Rewrite: `lib/site-content.ts`
- Create: `components/ScrollReveal.tsx`
- [ ] **Step 1: Rewrite lib/site-content.ts**
```typescript
export const SITE_NAME = "DAL"
export const SITE_BRAND = "DAL by DeepAILab"
export const SITE_TAGLINE = "The Open AI Development Platform"
export const SITE_DESCRIPTION =
"从想法到产品的完整 AI 开发平台。自由选模型,全链路覆盖,一个账号搞定一切。"
export interface NavProductItem {
key: string
href: string
}
export const NAV_PRODUCT_ITEMS: NavProductItem[] = [
{ key: "code", href: "/code" },
{ key: "cli", href: "/cli" },
{ key: "office", href: "/office" },
{ key: "platform", href: "/platform" },
]
export interface FooterGroup {
key: string
links: { key: string; href: string; external?: boolean }[]
}
export const FOOTER_GROUPS: FooterGroup[] = [
{
key: "products",
links: [
{ key: "code", href: "/code" },
{ key: "cli", href: "/cli" },
{ key: "office", href: "/office" },
{ key: "apiPlatform", href: "/platform" },
{ key: "pricing", href: "/pricing" },
],
},
{
key: "resources",
links: [
{ key: "docs", href: "/docs" },
{ key: "blog", href: "/blog" },
{ key: "changelog", href: "/coming-soon" },
{ key: "faq", href: "/#faq" },
],
},
{
key: "community",
links: [
{ key: "discord", href: "https://discord.gg/deepailab", external: true },
{ key: "github", href: "https://github.com/deepailab", external: true },
{ key: "twitter", href: "https://x.com/deepailab", external: true },
],
},
{
key: "company",
links: [
{ key: "about", href: "/about" },
{ key: "careers", href: "/careers" },
{ key: "contact", href: "/contact" },
],
},
]
export const PRODUCT_KEYS = ["code", "cli", "office", "platform"] as const
export type ProductKey = (typeof PRODUCT_KEYS)[number]
export const PRODUCT_ICONS: Record<ProductKey, string> = {
code: "/assets/icons/product-code.svg",
cli: "/assets/icons/product-cli.svg",
office: "/assets/icons/product-office.svg",
platform: "/assets/icons/product-platform.svg",
}
export const PRODUCT_HREFS: Record<ProductKey, string> = {
code: "/code",
cli: "/cli",
office: "/office",
platform: "/platform",
}
export const WORKFLOW_STEPS = ["intent", "build", "ship"] as const
export type WorkflowStep = (typeof WORKFLOW_STEPS)[number]
export const FEATURE_KEYS = [
"routing", "skills", "mission", "byok",
"context", "audit", "rag", "cost",
] as const
export type FeatureKey = (typeof FEATURE_KEYS)[number]
export const FEATURE_ICONS: Record<FeatureKey, string> = {
routing: "⚡",
skills: "🧩",
mission: "🎯",
byok: "🔑",
context: "🧠",
audit: "🛡️",
rag: "📚",
cost: "📊",
}
export const PLATFORM_ADVANTAGE_KEYS = ["account", "discount", "dashboard"] as const
export const FAQ_KEYS = [
"vsCursor", "vsClaude", "byok", "apiDiscount", "models", "enterprise",
] as const
```
- [ ] **Step 2: Create ScrollReveal component**
Create `components/ScrollReveal.tsx`:
```tsx
"use client"
import { useEffect, useRef } from "react"
interface ScrollRevealProps {
children: React.ReactNode
className?: string
delay?: number
as?: keyof HTMLElementTagNameMap
}
export default function ScrollReveal({
children,
className = "",
delay = 0,
as: Tag = "div" as any,
}: ScrollRevealProps) {
const ref = useRef<HTMLElement>(null)
useEffect(() => {
const el = ref.current
if (!el) return
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setTimeout(() => {
el.classList.add("reveal-visible")
}, delay)
observer.unobserve(el)
}
},
{ threshold: 0.1 },
)
observer.observe(el)
return () => observer.disconnect()
}, [delay])
return (
<Tag ref={ref} className={`reveal-up ${className}`}>
{children}
</Tag>
)
}
```
- [ ] **Step 3: Commit**
```bash
git add lib/site-content.ts components/ScrollReveal.tsx
git commit -m "feat: add new site content data and ScrollReveal component"
```
---
## Task 4: Header — New navigation with Products dropdown
**Files:**
- Rewrite: `components/Header.tsx`
- [ ] **Step 1: Write new Header.tsx**
```tsx
"use client"
import { useState, useEffect, useCallback } from "react"
import Image from "next/image"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { useTranslations } from "next-intl"
import LocaleSwitcher from "@/components/LocaleSwitcher"
import { NAV_PRODUCT_ITEMS } from "@/lib/site-content"
export default function Header() {
const t = useTranslations("nav")
const [mobileOpen, setMobileOpen] = useState(false)
const [productsOpen, setProductsOpen] = useState(false)
const [scrolled, setScrolled] = useState(false)
const pathname = usePathname()
const closeAll = useCallback(() => {
setMobileOpen(false)
setProductsOpen(false)
}, [])
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 20)
window.addEventListener("scroll", onScroll, { passive: true })
return () => window.removeEventListener("scroll", onScroll)
}, [])
useEffect(() => { closeAll() }, [pathname, closeAll])
const navLinks = [
{ href: "/docs", label: t("docs") },
{ href: "/pricing", label: t("pricing") },
{ href: "/blog", label: t("blog") },
]
return (
<header
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
scrolled
? "bg-bg-primary/80 backdrop-blur-xl border-b border-border"
: "bg-transparent"
}`}
>
<div className="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
{/* Logo */}
<Link href="/" className="flex items-center gap-2" onClick={closeAll}>
<Image
src="/assets/dalcode-app-icon.svg"
width={32}
height={32}
alt="DAL"
/>
<span className="font-display font-semibold text-lg text-text-primary">
DAL
</span>
</Link>
{/* Desktop Nav */}
<nav className="hidden md:flex items-center gap-1">
{/* Products Dropdown */}
<div
className="relative"
onMouseEnter={() => setProductsOpen(true)}
onMouseLeave={() => setProductsOpen(false)}
>
<button
type="button"
className="px-3 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors flex items-center gap-1"
onClick={() => setProductsOpen((v) => !v)}
>
{t("products")}
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" className={`transition-transform ${productsOpen ? "rotate-180" : ""}`}>
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
{productsOpen && (
<div className="absolute top-full left-0 pt-2">
<div className="bg-bg-card border border-border rounded-xl p-2 min-w-[240px] shadow-2xl">
{NAV_PRODUCT_ITEMS.map((item) => (
<Link
key={item.key}
href={item.href}
className="flex flex-col gap-0.5 px-3 py-2.5 rounded-lg hover:bg-bg-card-hover transition-colors"
onClick={closeAll}
>
<span className="text-sm font-medium text-text-primary">
{t(`productItems.${item.key}.name`)}
</span>
<span className="text-xs text-text-muted">
{t(`productItems.${item.key}.tagline`)}
</span>
</Link>
))}
</div>
</div>
)}
</div>
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className={`px-3 py-2 text-sm transition-colors ${
pathname === link.href
? "text-text-primary"
: "text-text-secondary hover:text-text-primary"
}`}
>
{link.label}
</Link>
))}
</nav>
{/* Right side */}
<div className="hidden md:flex items-center gap-3">
<LocaleSwitcher />
<Link
href="/contact"
className="text-sm text-text-secondary hover:text-text-primary transition-colors"
>
{t("signIn")}
</Link>
<Link
href="/code"
className="px-4 py-2 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("downloads")}
</Link>
</div>
{/* Mobile hamburger */}
<button
type="button"
className="md:hidden p-2"
onClick={() => setMobileOpen((v) => !v)}
aria-label={t("toggleMenu")}
>
<div className="w-5 flex flex-col gap-1.5">
<span className={`block h-px bg-text-primary transition-all ${mobileOpen ? "rotate-45 translate-y-[3.5px]" : ""}`} />
<span className={`block h-px bg-text-primary transition-all ${mobileOpen ? "-rotate-45 -translate-y-[3.5px]" : ""}`} />
</div>
</button>
</div>
{/* Mobile menu */}
{mobileOpen && (
<div className="md:hidden bg-bg-primary border-t border-border">
<div className="px-6 py-4 flex flex-col gap-2">
{NAV_PRODUCT_ITEMS.map((item) => (
<Link
key={item.key}
href={item.href}
className="py-2 text-sm text-text-secondary hover:text-text-primary"
onClick={closeAll}
>
{t(`productItems.${item.key}.name`)}
</Link>
))}
<hr className="border-border my-2" />
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className="py-2 text-sm text-text-secondary hover:text-text-primary"
onClick={closeAll}
>
{link.label}
</Link>
))}
<hr className="border-border my-2" />
<Link
href="/code"
className="py-2 text-sm font-medium text-accent"
onClick={closeAll}
>
{t("downloads")}
</Link>
<LocaleSwitcher />
</div>
</div>
)}
</header>
)
}
```
- [ ] **Step 2: Verify Header renders**
```bash
cd /Users/leon/本地开发项目/claude-code/dalcode-website && PORT=55132 npx next dev &
sleep 5
curl -s http://localhost:55132 | head -50
```
- [ ] **Step 3: Commit**
```bash
git add components/Header.tsx
git commit -m "feat: new Header with Products dropdown and dark theme"
```
---
## Task 5: Footer — New 4-column layout
**Files:**
- Rewrite: `components/Footer.tsx`
- [ ] **Step 1: Write new Footer.tsx**
```tsx
"use client"
import Image from "next/image"
import Link from "next/link"
import { useTranslations } from "next-intl"
import NewsletterForm from "@/components/NewsletterForm"
import LocaleSwitcher from "@/components/LocaleSwitcher"
import { FOOTER_GROUPS } from "@/lib/site-content"
export default function Footer() {
const t = useTranslations("footer")
return (
<footer className="border-t border-border bg-bg-primary">
<div className="max-w-7xl mx-auto px-6">
{/* Top: logo + newsletter */}
<div className="py-12 flex flex-col md:flex-row justify-between items-start gap-8">
<div className="flex items-center gap-2">
<Image src="/assets/dalcode-app-icon.svg" width={28} height={28} alt="DAL" />
<span className="font-display font-semibold text-text-primary">DAL</span>
</div>
<div className="w-full md:w-80">
<NewsletterForm />
</div>
</div>
{/* Link columns */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 pb-12">
{FOOTER_GROUPS.map((group) => (
<div key={group.key}>
<h3 className="text-xs font-semibold uppercase tracking-wider text-text-muted mb-4">
{t(`groups.${group.key}`)}
</h3>
<ul className="flex flex-col gap-2.5">
{group.links.map((link) => (
<li key={link.key}>
<Link
href={link.href}
className="text-sm text-text-secondary hover:text-text-primary transition-colors"
{...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
>
{t(`links.${link.key}`)}
</Link>
</li>
))}
</ul>
</div>
))}
</div>
{/* Bottom bar */}
<div className="border-t border-border py-6 flex flex-col md:flex-row justify-between items-center gap-4 text-xs text-text-muted">
<p>{t("copyright")}</p>
<div className="flex items-center gap-6">
<Link href="/privacy" className="hover:text-text-secondary transition-colors">
{t("privacy")}
</Link>
<Link href="/terms" className="hover:text-text-secondary transition-colors">
{t("terms")}
</Link>
<LocaleSwitcher />
</div>
</div>
</div>
</footer>
)
}
```
- [ ] **Step 2: Commit**
```bash
git add components/Footer.tsx
git commit -m "feat: new Footer with 4-column layout"
```
---
## Task 6: Homepage sections — Hero + ProductEcosystem
**Files:**
- Rewrite: `components/home/HeroSection.tsx`
- Create: `components/home/ProductEcosystem.tsx`
- [ ] **Step 1: Write new HeroSection.tsx**
```tsx
"use client"
import Link from "next/link"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
export default function HeroSection() {
const t = useTranslations("hero")
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden pt-16">
{/* Background gradient */}
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,var(--color-accent-glow)_0%,transparent_70%)]" />
<div className="relative z-10 max-w-4xl mx-auto px-6 text-center">
<ScrollReveal>
<span className="inline-block px-3 py-1 text-xs font-medium text-accent border border-accent/30 rounded-full mb-8">
{t("badge")}
</span>
</ScrollReveal>
<ScrollReveal delay={100}>
<h1 className="font-display text-5xl md:text-7xl font-bold tracking-tight text-text-primary leading-[1.1]">
{t("headline")}
</h1>
</ScrollReveal>
<ScrollReveal delay={200}>
<p className="mt-6 text-lg md:text-xl text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
</ScrollReveal>
<ScrollReveal delay={300}>
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
<Link
href="/code"
className="px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("ctaPrimary")}
</Link>
<Link
href="/cli"
className="px-6 py-3 text-sm font-medium text-text-primary border border-border hover:border-border-hover rounded-lg transition-colors"
>
{t("ctaSecondary")}
</Link>
</div>
</ScrollReveal>
<ScrollReveal delay={400}>
<div className="mt-6 inline-flex items-center gap-2 px-4 py-2 bg-bg-card border border-border rounded-lg font-mono text-sm text-text-muted">
<span className="text-accent">$</span>
<span>{t("cliCommand")}</span>
<button
type="button"
className="ml-2 text-text-muted hover:text-text-primary transition-colors"
onClick={() => navigator.clipboard.writeText(t("cliCommand"))}
aria-label="Copy command"
>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
</button>
</div>
</ScrollReveal>
{/* Product screenshot placeholder */}
<ScrollReveal delay={500}>
<div className="mt-16 rounded-xl border border-border bg-bg-card overflow-hidden shadow-2xl">
<div className="aspect-video flex items-center justify-center text-text-muted">
<div className="text-center">
<div className="text-4xl mb-2"></div>
<p className="text-sm">Product screenshot</p>
</div>
</div>
</div>
</ScrollReveal>
</div>
</section>
)
}
```
- [ ] **Step 2: Write ProductEcosystem.tsx**
```tsx
"use client"
import Link from "next/link"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
import { PRODUCT_KEYS, PRODUCT_HREFS } from "@/lib/site-content"
export default function ProductEcosystem() {
const t = useTranslations("ecosystem")
return (
<section className="py-32 px-6">
<div className="max-w-6xl mx-auto">
<ScrollReveal>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary">
{t("title")}
</h2>
</ScrollReveal>
<div className="mt-16 grid grid-cols-1 md:grid-cols-2 gap-4">
{PRODUCT_KEYS.map((key, i) => (
<ScrollReveal key={key} delay={i * 100}>
<Link
href={PRODUCT_HREFS[key]}
className="group block p-8 rounded-xl border border-border bg-bg-card hover:bg-bg-card-hover hover:border-border-hover transition-all card-glow"
>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-3">
{t(`products.${key}.name`)}
</p>
<h3 className="font-display text-xl font-semibold text-text-primary mb-2">
{t(`products.${key}.tagline`)}
</h3>
<p className="text-sm text-text-secondary mb-6 leading-relaxed">
{t(`products.${key}.description`)}
</p>
<div className="flex flex-wrap gap-2 mb-6">
{(t.raw(`products.${key}.features`) as string[]).map((f: string) => (
<span key={f} className="px-2 py-1 text-xs text-text-muted border border-border rounded-md">
{f}
</span>
))}
</div>
<span className="text-sm text-accent group-hover:underline">
{t(`products.${key}.cta`)}
</span>
</Link>
</ScrollReveal>
))}
</div>
</div>
</section>
)
}
```
- [ ] **Step 3: Commit**
```bash
git add components/home/HeroSection.tsx components/home/ProductEcosystem.tsx
git commit -m "feat: new Hero and ProductEcosystem sections"
```
---
## Task 7: Homepage sections — WorkflowSteps + FeatureGrid
**Files:**
- Create: `components/home/WorkflowSteps.tsx`
- Create: `components/home/FeatureGrid.tsx`
- [ ] **Step 1: Write WorkflowSteps.tsx**
```tsx
"use client"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
import { WORKFLOW_STEPS } from "@/lib/site-content"
export default function WorkflowSteps() {
const t = useTranslations("workflow")
return (
<section className="py-32 px-6 bg-bg-secondary">
<div className="max-w-6xl mx-auto">
<ScrollReveal>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary max-w-2xl">
{t("title")}
</h2>
</ScrollReveal>
<div className="mt-16 grid grid-cols-1 md:grid-cols-3 gap-6">
{WORKFLOW_STEPS.map((step, i) => (
<ScrollReveal key={step} delay={i * 150}>
<div className="relative p-8 rounded-xl border border-border bg-bg-card h-full">
<span className="font-display text-6xl font-bold text-border">
{t(`steps.${step}.number`)}
</span>
<p className="mt-4 text-xs font-semibold uppercase tracking-widest text-accent">
{t(`steps.${step}.name`)}
</p>
<h3 className="mt-2 font-display text-xl font-semibold text-text-primary">
{t(`steps.${step}.title`)}
</h3>
<p className="mt-3 text-sm text-text-secondary leading-relaxed">
{t(`steps.${step}.description`)}
</p>
{/* Screenshot placeholder */}
<div className="mt-6 rounded-lg border border-border bg-bg-secondary aspect-video flex items-center justify-center">
<span className="text-xs text-text-muted">Screenshot</span>
</div>
</div>
</ScrollReveal>
))}
</div>
{/* Connecting line */}
<div className="hidden md:flex items-center justify-center mt-8 gap-2">
{WORKFLOW_STEPS.map((_, i) => (
<div key={i} className="flex items-center">
<div className="w-3 h-3 rounded-full border-2 border-accent bg-bg-primary" />
{i < WORKFLOW_STEPS.length - 1 && (
<div className="w-32 h-px bg-gradient-to-r from-accent to-border" />
)}
</div>
))}
</div>
</div>
</section>
)
}
```
- [ ] **Step 2: Write FeatureGrid.tsx**
```tsx
"use client"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
import { FEATURE_KEYS, FEATURE_ICONS } from "@/lib/site-content"
export default function FeatureGrid() {
const t = useTranslations("features")
return (
<section className="py-32 px-6">
<div className="max-w-6xl mx-auto">
<ScrollReveal>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary">
{t("title")}
</h2>
</ScrollReveal>
<div className="mt-16 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{FEATURE_KEYS.map((key, i) => (
<ScrollReveal key={key} delay={i * 80}>
<div className="p-6 rounded-xl border border-border bg-bg-card hover:bg-bg-card-hover hover:border-border-hover transition-all card-glow h-full">
<span className="text-2xl">{FEATURE_ICONS[key]}</span>
<h3 className="mt-4 font-display text-base font-semibold text-text-primary">
{t(`items.${key}.title`)}
</h3>
<p className="mt-2 text-sm text-text-secondary leading-relaxed">
{t(`items.${key}.description`)}
</p>
</div>
</ScrollReveal>
))}
</div>
</div>
</section>
)
}
```
- [ ] **Step 3: Commit**
```bash
git add components/home/WorkflowSteps.tsx components/home/FeatureGrid.tsx
git commit -m "feat: add WorkflowSteps and FeatureGrid homepage sections"
```
---
## Task 8: Homepage sections — EcosystemSection + BottomCta + FaqSection
**Files:**
- Create: `components/home/EcosystemSection.tsx`
- Create: `components/home/BottomCta.tsx`
- Create: `components/home/FaqSection.tsx`
- [ ] **Step 1: Write EcosystemSection.tsx**
```tsx
"use client"
import Link from "next/link"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
import { PLATFORM_ADVANTAGE_KEYS } from "@/lib/site-content"
export default function EcosystemSection() {
const t = useTranslations("platform")
return (
<section className="py-32 px-6 bg-gradient-to-b from-bg-secondary to-[#0d0518]">
<div className="max-w-6xl mx-auto">
<ScrollReveal>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary max-w-3xl">
{t("title")}
</h2>
</ScrollReveal>
{/* Architecture diagram */}
<ScrollReveal delay={200}>
<div className="mt-16 flex justify-center">
<div className="relative">
{/* Center node */}
<div className="w-40 h-40 rounded-2xl border-2 border-accent bg-bg-card flex flex-col items-center justify-center text-center">
<span className="text-sm font-semibold text-accent">DeepAILab</span>
<span className="text-xs text-text-muted mt-1">Platform</span>
</div>
{/* Branch nodes positioned absolutely */}
{(["Code", "CLI", "Office", "API"] as const).map((name, i) => {
const positions = [
"-top-20 left-1/2 -translate-x-1/2",
"top-1/2 -right-28 -translate-y-1/2",
"-bottom-20 left-1/2 -translate-x-1/2",
"top-1/2 -left-28 -translate-y-1/2",
]
return (
<div key={name} className={`absolute ${positions[i]} px-3 py-2 rounded-lg border border-border bg-bg-card text-xs text-text-secondary`}>
{name}
</div>
)
})}
</div>
</div>
</ScrollReveal>
{/* Advantage cards */}
<div className="mt-20 grid grid-cols-1 md:grid-cols-3 gap-4">
{PLATFORM_ADVANTAGE_KEYS.map((key, i) => (
<ScrollReveal key={key} delay={i * 100}>
<div className="p-6 rounded-xl border border-border bg-bg-card/50 backdrop-blur-sm">
<h3 className="font-display text-lg font-semibold text-text-primary">
{t(`advantages.${key}.title`)}
</h3>
<p className="mt-2 text-sm text-text-secondary leading-relaxed">
{t(`advantages.${key}.description`)}
</p>
</div>
</ScrollReveal>
))}
</div>
<ScrollReveal delay={400}>
<div className="mt-12 text-center">
<a
href="https://deepailab.ai"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 py-3 text-sm font-medium text-accent border border-accent/30 hover:border-accent rounded-lg transition-colors"
>
{t("cta")}
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M7 17L17 7M17 7H7M17 7V17" />
</svg>
</a>
</div>
</ScrollReveal>
</div>
</section>
)
}
```
- [ ] **Step 2: Write BottomCta.tsx**
```tsx
"use client"
import Link from "next/link"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
export default function BottomCta() {
const t = useTranslations("bottomCta")
const hero = useTranslations("hero")
return (
<section className="relative py-32 px-6 overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,var(--color-accent-glow)_0%,transparent_70%)]" />
<div className="relative z-10 max-w-3xl mx-auto text-center">
<ScrollReveal>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary">
{t("headline")}
</h2>
</ScrollReveal>
<ScrollReveal delay={100}>
<p className="mt-6 text-lg text-text-secondary">
{t("subheadline")}
</p>
</ScrollReveal>
<ScrollReveal delay={200}>
<div className="mt-10 flex flex-col sm:flex-row items-center justify-center gap-4">
<Link
href="/code"
className="px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("ctaPrimary")}
</Link>
<Link
href="/cli"
className="px-6 py-3 text-sm font-medium text-text-primary border border-border hover:border-border-hover rounded-lg transition-colors"
>
{t("ctaSecondary")}
</Link>
</div>
</ScrollReveal>
<ScrollReveal delay={300}>
<div className="mt-6 inline-flex items-center gap-2 px-4 py-2 bg-bg-card border border-border rounded-lg font-mono text-sm text-text-muted">
<span className="text-accent">$</span>
<span>{hero("cliCommand")}</span>
</div>
</ScrollReveal>
</div>
</section>
)
}
```
- [ ] **Step 3: Write FaqSection.tsx**
```tsx
"use client"
import { useState } from "react"
import { useTranslations } from "next-intl"
import ScrollReveal from "@/components/ScrollReveal"
import { FAQ_KEYS } from "@/lib/site-content"
export default function FaqSection() {
const t = useTranslations("faq")
const [openIndex, setOpenIndex] = useState<number | null>(null)
return (
<section id="faq" className="py-32 px-6 bg-bg-secondary">
<div className="max-w-3xl mx-auto">
<ScrollReveal>
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h2 className="font-display text-3xl md:text-5xl font-bold text-text-primary">
{t("title")}
</h2>
</ScrollReveal>
<div className="mt-12 flex flex-col divide-y divide-border">
{FAQ_KEYS.map((key, i) => (
<ScrollReveal key={key} delay={i * 60}>
<div>
<button
type="button"
className="w-full py-5 flex items-center justify-between text-left group"
onClick={() => setOpenIndex(openIndex === i ? null : i)}
>
<span className="text-base font-medium text-text-primary group-hover:text-accent transition-colors pr-4">
{t(`items.${key}.q`)}
</span>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
className={`flex-shrink-0 text-text-muted transition-transform ${openIndex === i ? "rotate-45" : ""}`}
>
<path d="M12 5v14M5 12h14" />
</svg>
</button>
{openIndex === i && (
<div className="pb-5 text-sm text-text-secondary leading-relaxed">
{t(`items.${key}.a`)}
</div>
)}
</div>
</ScrollReveal>
))}
</div>
</div>
</section>
)
}
```
- [ ] **Step 4: Commit**
```bash
git add components/home/EcosystemSection.tsx components/home/BottomCta.tsx components/home/FaqSection.tsx
git commit -m "feat: add EcosystemSection, BottomCta, and FaqSection"
```
---
## Task 9: Wire up homepage + delete old components
**Files:**
- Rewrite: `app/page.tsx`
- Rewrite: `components/home/index.ts`
- Delete: `components/home/IntegrationsSection.tsx`
- Delete: `components/home/PrinciplesSection.tsx`
- Delete: `components/home/BlogPreviewSection.tsx`
- Delete: `components/home/CtaSection.tsx`
- [ ] **Step 1: Rewrite components/home/index.ts**
```typescript
export { default as HeroSection } from "./HeroSection"
export { default as ProductEcosystem } from "./ProductEcosystem"
export { default as WorkflowSteps } from "./WorkflowSteps"
export { default as FeatureGrid } from "./FeatureGrid"
export { default as EcosystemSection } from "./EcosystemSection"
export { default as BottomCta } from "./BottomCta"
export { default as FaqSection } from "./FaqSection"
```
- [ ] **Step 2: Rewrite app/page.tsx**
```tsx
import type { Metadata } from "next"
import {
HeroSection,
ProductEcosystem,
WorkflowSteps,
FeatureGrid,
EcosystemSection,
BottomCta,
FaqSection,
} from "@/components/home"
import { SITE_BRAND, SITE_DESCRIPTION } from "@/lib/site-content"
export const metadata: Metadata = {
title: SITE_BRAND,
description: SITE_DESCRIPTION,
openGraph: {
title: SITE_BRAND,
description: SITE_DESCRIPTION,
},
}
export default function HomePage() {
return (
<>
<HeroSection />
<ProductEcosystem />
<WorkflowSteps />
<FeatureGrid />
<EcosystemSection />
<BottomCta />
<FaqSection />
</>
)
}
```
- [ ] **Step 3: Delete old components**
```bash
rm components/home/IntegrationsSection.tsx
rm components/home/PrinciplesSection.tsx
rm components/home/BlogPreviewSection.tsx
rm components/home/CtaSection.tsx
```
- [ ] **Step 4: Verify homepage loads**
Start dev server, navigate to `http://localhost:55132`, take a screenshot and verify all 7 sections render.
- [ ] **Step 5: Commit**
```bash
git add -A
git commit -m "feat: wire up new homepage sections, remove old components"
```
---
## Task 10: Subpages — /code, /cli, /office, /platform, /pricing
**Files:**
- Create: `app/code/page.tsx`
- Create: `app/cli/page.tsx`
- Create: `app/office/page.tsx`
- Create: `app/platform/page.tsx`
- Create: `app/pricing/page.tsx`
- [ ] **Step 1: Write app/code/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
import Link from "next/link"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("codePage.hero")
return { title: t("headline") }
}
export default async function CodePage() {
const t = await getTranslations("codePage.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
<div className="mt-10">
<Link
href="/contact"
className="px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("cta")}
</Link>
</div>
<div className="mt-16 rounded-xl border border-border bg-bg-card overflow-hidden">
<div className="aspect-video flex items-center justify-center text-text-muted">
<p className="text-sm">DAL Code product screenshots coming soon</p>
</div>
</div>
</div>
</section>
)
}
```
- [ ] **Step 2: Write app/cli/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
import Link from "next/link"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("cliPage.hero")
return { title: t("headline") }
}
export default async function CliPage() {
const t = await getTranslations("cliPage.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
<div className="mt-10 flex flex-col items-center gap-4">
<div className="inline-flex items-center gap-2 px-4 py-2 bg-bg-card border border-border rounded-lg font-mono text-sm text-text-muted">
<span className="text-accent">$</span>
<span>{t("cliCommand")}</span>
</div>
</div>
<div className="mt-16 rounded-xl border border-border bg-bg-card overflow-hidden">
<div className="aspect-video flex items-center justify-center text-text-muted bg-[#1a1a2e]">
<div className="font-mono text-sm text-left max-w-md">
<p><span className="text-accent">$</span> dal init</p>
<p className="text-text-muted mt-1">Initializing DAL CLI...</p>
<p className="text-green-400 mt-1"> Connected to DeepAILab Platform</p>
<p className="text-text-muted mt-1">Ready. Type `dal` to get started.</p>
</div>
</div>
</div>
</div>
</section>
)
}
```
- [ ] **Step 3: Write app/office/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
import Link from "next/link"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("officePage.hero")
return { title: t("headline") }
}
export default async function OfficePage() {
const t = await getTranslations("officePage.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
<div className="mt-10">
<Link
href="/contact"
className="px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("cta")}
</Link>
</div>
<div className="mt-16 grid grid-cols-1 md:grid-cols-3 gap-4">
{(["Word", "Excel", "PPT"] as const).map((name) => (
<div key={name} className="p-8 rounded-xl border border-border bg-bg-card">
<h3 className="font-display text-lg font-semibold text-text-primary">{name}</h3>
<p className="mt-2 text-sm text-text-muted">Coming soon</p>
</div>
))}
</div>
</div>
</section>
)
}
```
- [ ] **Step 4: Write app/platform/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("platformPage.hero")
return { title: t("headline") }
}
export default async function PlatformPage() {
const t = await getTranslations("platformPage.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
<div className="mt-10">
<a
href="https://deepailab.ai"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors"
>
{t("cta")}
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M7 17L17 7M17 7H7M17 7V17" />
</svg>
</a>
</div>
</div>
</section>
)
}
```
- [ ] **Step 5: Write app/pricing/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("pricingPage.hero")
return { title: t("headline") }
}
export default async function PricingPage() {
const t = await getTranslations("pricingPage.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
<div className="mt-16 text-text-muted text-sm">
Pricing details coming soon
</div>
</div>
</section>
)
}
```
- [ ] **Step 6: Commit**
```bash
git add app/code/ app/cli/ app/office/ app/platform/ app/pricing/
git commit -m "feat: add product subpages (code, cli, office, platform, pricing)"
```
---
## Task 11: Update existing subpages (about, blog, contact, careers) for dark theme
**Files:**
- Modify: `app/about/page.tsx`
- Modify: `app/blog/page.tsx`
- Modify: `app/contact/page.tsx`
- Modify: `app/careers/page.tsx`
- Modify: `app/coming-soon/page.tsx`
- Modify: `app/not-found.tsx`
These pages currently use webflow CSS classes. They need to be converted to Tailwind. Since they are secondary pages, we use a minimal hero + content pattern consistent with the new subpages.
- [ ] **Step 1: Rewrite app/about/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("about.hero")
return { title: t("headline") }
}
export default async function AboutPage() {
const t = await getTranslations("about.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
</div>
</section>
)
}
```
- [ ] **Step 2: Rewrite app/blog/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("blog.hero")
return { title: t("headline") }
}
export default async function BlogPage() {
const t = await getTranslations("blog.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
</div>
</section>
)
}
```
- [ ] **Step 3: Rewrite app/contact/page.tsx**
```tsx
import type { Metadata } from "next"
import { getTranslations } from "next-intl/server"
import ContactForm from "@/components/ContactForm"
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations("contact.hero")
return { title: t("headline") }
}
export default async function ContactPage() {
const t = await getTranslations("contact.hero")
return (
<section className="min-h-screen pt-32 pb-20 px-6">
<div className="max-w-4xl mx-auto">
<div className="text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">
{t("label")}
</p>
<h1 className="font-display text-4xl md:text-6xl font-bold text-text-primary leading-tight">
{t("headline")}
</h1>
<p className="mt-6 text-lg text-text-secondary max-w-2xl mx-auto leading-relaxed">
{t("subheadline")}
</p>
</div>
<div className="mt-16 max-w-xl mx-auto">
<ContactForm />
</div>
</div>
</section>
)
}
```
- [ ] **Step 4: Simplify app/careers/page.tsx, app/coming-soon/page.tsx, app/not-found.tsx**
Apply the same pattern: minimal hero with label + headline + description, using Tailwind classes, no webflow references.
For `not-found.tsx`:
```tsx
import Link from "next/link"
export default function NotFound() {
return (
<section className="min-h-screen pt-32 pb-20 px-6 flex items-center">
<div className="max-w-xl mx-auto text-center">
<p className="text-xs font-semibold uppercase tracking-widest text-accent mb-4">404</p>
<h1 className="font-display text-4xl font-bold text-text-primary">Page not found</h1>
<p className="mt-4 text-text-secondary">The page you're looking for doesn't exist or has been moved.</p>
<div className="mt-8">
<Link href="/" className="px-6 py-3 text-sm font-medium bg-accent hover:bg-accent-hover text-white rounded-lg transition-colors">
Back to home
</Link>
</div>
</div>
</section>
)
}
```
- [ ] **Step 5: Delete old about/blog/contact subcomponents that use webflow classes**
```bash
rm -rf components/about/
rm -rf components/blog/
rm -rf components/contact/
```
- [ ] **Step 6: Commit**
```bash
git add -A
git commit -m "feat: rewrite all subpages for dark Tailwind theme"
```
---
## Task 12: Update GsapAnimations + NewsletterForm + LocaleSwitcher
**Files:**
- Modify: `components/GsapAnimations.tsx`
- Modify: `components/NewsletterForm.tsx`
- Modify: `components/LocaleSwitcher.tsx`
- [ ] **Step 1: Simplify GsapAnimations.tsx**
Remove marquee, counter, and button hover init (no longer needed). Keep scroll reveal and smooth scroll:
```tsx
"use client"
import { useEffect } from "react"
export default function GsapAnimations() {
useEffect(() => {
let ctx: ReturnType<typeof import("gsap").gsap.context> | null = null
import("gsap").then(async ({ gsap }) => {
const { ScrollTrigger } = await import("gsap/ScrollTrigger")
gsap.registerPlugin(ScrollTrigger)
ctx = gsap.context(() => {
ScrollTrigger.batch(".reveal-up:not(.reveal-visible)", {
onEnter: (batch) =>
gsap.to(batch, {
opacity: 1,
y: 0,
stagger: 0.1,
duration: 0.6,
ease: "power2.out",
overwrite: true,
}),
})
})
})
return () => { ctx?.revert() }
}, [])
return null
}
```
- [ ] **Step 2: Update NewsletterForm.tsx to use Tailwind**
The existing form needs its webflow classes replaced with Tailwind. Update the component to use:
- `bg-bg-card border border-border` for input
- `bg-accent text-white` for submit button
- Use `useTranslations("footer.newsletter")` for all strings
- [ ] **Step 3: Update LocaleSwitcher.tsx to use Tailwind**
Replace webflow classes with:
- `text-sm text-text-muted hover:text-text-primary` styling
- Simple `<select>` or button toggle between zh-CN and en
- [ ] **Step 4: Commit**
```bash
git add components/GsapAnimations.tsx components/NewsletterForm.tsx components/LocaleSwitcher.tsx
git commit -m "refactor: update GsapAnimations, NewsletterForm, LocaleSwitcher for new design"
```
---
## Task 13: Update ContactForm for dark theme
**Files:**
- Modify: `components/ContactForm.tsx`
- [ ] **Step 1: Update ContactForm to use Tailwind classes**
Replace all webflow CSS classes with Tailwind equivalents:
- Inputs: `w-full px-4 py-3 bg-bg-card border border-border rounded-lg text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none`
- Labels: `text-sm text-text-secondary`
- Submit button: `w-full px-6 py-3 bg-accent hover:bg-accent-hover text-white font-medium rounded-lg transition-colors`
- Error messages: `text-xs text-red-400`
Keep all existing React Hook Form + Zod validation logic unchanged.
- [ ] **Step 2: Commit**
```bash
git add components/ContactForm.tsx
git commit -m "refactor: update ContactForm for dark Tailwind theme"
```
---
## Task 14: Full build verification + browser test
**Files:** None (verification only)
- [ ] **Step 1: Run TypeScript check**
```bash
cd /Users/leon/本地开发项目/claude-code/dalcode-website && npx tsc --noEmit 2>&1 | tail -30
```
Expected: No type errors.
- [ ] **Step 2: Run Next.js build**
```bash
npx next build 2>&1 | tail -30
```
Expected: Build succeeds with all pages generated.
- [ ] **Step 3: Start dev server and verify in browser**
```bash
PORT=55132 npx next dev &
```
Navigate to `http://localhost:55132` and verify:
- Homepage: all 7 sections render (Hero, ProductEcosystem, WorkflowSteps, FeatureGrid, EcosystemSection, BottomCta, FAQ)
- Navigation: Products dropdown works, all links navigate correctly
- Subpages: `/code`, `/cli`, `/office`, `/platform`, `/pricing`, `/about`, `/blog`, `/contact` all load
- Footer: 4-column layout renders correctly
- Language switch: toggle between zh-CN and en
- Mobile: responsive layout works at mobile breakpoints
- Scroll animations: sections fade in on scroll
- [ ] **Step 4: Take screenshots of key pages**
Screenshot homepage, `/code`, `/cli` pages and verify visual quality.
- [ ] **Step 5: Final commit if any fixes needed**
```bash
git add -A
git commit -m "fix: address build and visual issues from full verification"
```