Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 KiB
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:
@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:
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
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
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
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
{
"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
{
"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
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
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:
"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
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
"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
cd /Users/leon/本地开发项目/claude-code/dalcode-website && PORT=55132 npx next dev &
sleep 5
curl -s http://localhost:55132 | head -50
- Step 3: Commit
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
"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
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
"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
"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
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
"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
"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
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
"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
"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
"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
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
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
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
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
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
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
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
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
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
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
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
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
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
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:
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
rm -rf components/about/
rm -rf components/blog/
rm -rf components/contact/
- Step 6: Commit
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:
"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-borderfor input -
bg-accent text-whitefor 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-primarystyling -
Simple
<select>or button toggle between zh-CN and en -
Step 4: Commit
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
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
cd /Users/leon/本地开发项目/claude-code/dalcode-website && npx tsc --noEmit 2>&1 | tail -30
Expected: No type errors.
- Step 2: Run Next.js build
npx next build 2>&1 | tail -30
Expected: Build succeeds with all pages generated.
- Step 3: Start dev server and verify in browser
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,/contactall 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
git add -A
git commit -m "fix: address build and visual issues from full verification"