feat(site): redesign with product pages, ecosystem sections and pixel reveal

Add cli/code/office/platform/pricing pages, new home sections
(Ecosystem, FeatureGrid, Faq, WorkflowSteps, BottomCta, ProductEcosystem),
ScrollReveal and PixelTextReveal animation components, brand assets,
and expanded site-content.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leon-in
2026-05-30 14:00:18 +08:00
parent 3213f00b7b
commit 97db9ee8c7
27 changed files with 1709 additions and 32 deletions
+151
View File
@@ -0,0 +1,151 @@
import type { Metadata } from "next"
import Link from "next/link"
export const metadata: Metadata = {
title: "DAL CLI — 终端不退出,AI 已就位",
description:
"同样的意图引导和多模型路由,跑在你最顺手的 shell 里。带上自己的 Key,离线也能用。",
}
const FEATURES = [
{
title: "Shell 原生集成",
description: "不用打开新窗口。在你的终端里直接启动 DAL,上下文自动继承。",
},
{
title: "Task 管道",
description: "把复杂任务拆成管道式的步骤,每步结果可以 pipe 到下一步。",
},
{
title: "BYOK 直连",
description: "你的 API Key 直连供应商,CLI 不做中间人,数据不绕路。",
},
{
title: "离线可用",
description: "本地模型支持,网络断了也能继续工作。",
},
]
export default function CliPage() {
return (
<main>
<section className="section hero-v1">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="cli-hero"
style={{ opacity: "0", filter: "blur(8px)" }}
className="inner-container _480px _100-tablet"
>
<div className="subtitle">DAL CLI</div>
<h1>退AI </h1>
<div className="mg-top-4x-extra-small">
<p>
shell Key线
</p>
</div>
<div className="mg-top-2x-extra-small">
<div
style={{
display: "inline-flex",
alignItems: "center",
gap: "8px",
padding: "8px 16px",
border: "1px solid var(--core--colors--neutral--400)",
borderRadius: "8px",
fontFamily: "monospace",
fontSize: "0.875rem",
color: "var(--font--colors--paragraph)",
}}
>
<span style={{ color: "var(--font--colors--title)" }}>$</span>
<span>npx dalcode</span>
</div>
</div>
</div>
</div>
</section>
<section className="section overflow-hidden">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="cli-features-title"
style={{ opacity: "0", filter: "blur(8px)" }}
className="text-center"
>
<div className="subtitle">Features</div>
<div className="mg-top-4x-extra-small">
<h2> IDE </h2>
</div>
</div>
<div className="mg-top-large">
<div
data-w-id="cli-features-grid"
style={{ opacity: "0", filter: "blur(8px)" }}
className="corner-gradient-container"
>
<div className="border-wrapper">
<div
className="w-layout-grid"
style={{ gridTemplateColumns: "1fr 1fr" }}
>
{FEATURES.map((feat) => (
<div key={feat.title} className="card principles-card">
<div>
<h3 className="display-4">{feat.title}</h3>
<div className="mg-top-5x-extra-small">
<p>{feat.description}</p>
</div>
</div>
</div>
))}
</div>
</div>
<div data-wf--corner-gradient-outline--variant="base" className="corner-gradient-wrapper">
<div className="corner-gradient-horizontal top-left" />
<div className="corner-gradient-horizontal bottom-left" />
<div className="corner-gradient-horizontal top-right" />
<div className="corner-gradient-horizontal bottom-right" />
<div className="corner-gradient-vertical bottom-left" />
<div className="corner-gradient-vertical bottom-right" />
<div className="corner-gradient-vertical top-left" />
<div className="corner-gradient-vertical top-right" />
</div>
</div>
</div>
</div>
</section>
<section className="cta-section v1">
<div className="w-layout-blockcontainer container-default position-relative---z-index-1 w-container">
<div className="inner-container _430px">
<div className="subtitle">Get Started</div>
<div className="mg-top-3x-extra-small">
<h2 className="text-titles-dm"></h2>
</div>
<div className="mg-top-4x-extra-small">
<p className="text-paragraph-dm">
Key
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="secondary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg bg-neutral-800" />
<div className="button-icon-bg-inside bg-neutral-600" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
</main>
)
}
+150
View File
@@ -0,0 +1,150 @@
import type { Metadata } from "next"
import Link from "next/link"
export const metadata: Metadata = {
title: "DAL Code — 写代码之前,先把事情想清楚",
description:
"AI 先采访需求、再拆解任务、最后交付代码+测试+文档——不是更快的补全,是更完整的工程闭环。",
}
const CAPABILITIES = [
{
title: "Intent Capture",
description:
"你说方向,AI 来追问细节。结构化问题把模糊想法收敛成可执行的工程规格。",
},
{
title: "Mission Mode",
description:
"一个目标拆成十步计划,逐步推进,关键节点等你确认再继续。",
},
{
title: "Smart Routing",
description:
"架构设计用强模型,格式化用快模型。每个子任务自动选对模型。",
},
{
title: "Diff 审批",
description:
"代码变更、文件操作、命令执行——敏感操作必须经过你的确认。",
},
{
title: "Skills 引擎",
description:
"把团队最佳实践封装成可复用工作流,新人上手即用,经验不再只在某个人脑子里。",
},
{
title: "上下文压缩",
description:
"五层压缩策略,对话再长也不丢关键信息。token 花在刀刃上。",
},
]
export default function CodePage() {
return (
<main>
<section className="section hero-v1">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="code-hero"
style={{ opacity: "0", filter: "blur(8px)" }}
className="inner-container _480px _100-tablet"
>
<div className="subtitle">DAL Code</div>
<h1></h1>
<div className="mg-top-4x-extra-small">
<p>
AI 访++
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="primary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper primary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg" />
<div className="button-icon-bg-inside" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
<section className="section overflow-hidden">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="code-caps-title"
style={{ opacity: "0", filter: "blur(8px)" }}
className="text-center"
>
<div className="subtitle">Capabilities</div>
<div className="mg-top-4x-extra-small">
<h2></h2>
</div>
</div>
<div className="mg-top-large">
<div
data-w-id="code-caps-grid"
style={{ opacity: "0", filter: "blur(8px)" }}
>
<div
className="w-layout-grid values-grid"
style={{ gridTemplateColumns: "1fr 1fr 1fr" }}
>
{CAPABILITIES.map((cap) => (
<div key={cap.title} className="value-item">
<div>
<h3 className="display-4">{cap.title}</h3>
<div className="mg-top-5x-extra-small">
<p style={{ fontSize: "0.875rem" }}>{cap.description}</p>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</section>
<section className="cta-section v1">
<div className="w-layout-blockcontainer container-default position-relative---z-index-1 w-container">
<div className="inner-container _430px">
<div className="subtitle">Next Step</div>
<div className="mg-top-3x-extra-small">
<h2 className="text-titles-dm"></h2>
</div>
<div className="mg-top-4x-extra-small">
<p className="text-paragraph-dm">
DAL Code
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="secondary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg bg-neutral-800" />
<div className="button-icon-bg-inside bg-neutral-600" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
</main>
)
}
+153 -1
View File
@@ -211,11 +211,29 @@
color: #f5f5f5;
}
/* Primary button in dark sections */
/* Primary button: in dark mode, bg becomes light (#f5f5f5) via variable inversion,
so text must be dark for contrast */
.dark .primary-button {
color: #0d0d0d;
border-color: #2a2a2a;
}
.dark .primary-button:hover {
color: #0d0d0d;
}
.dark .primary-button .button-icon-wrapper svg {
color: #0d0d0d;
}
.dark .primary-button .button-icon-bg {
background-color: #1a1a1a;
}
.dark .primary-button .button-icon-bg-inside {
background-color: #2a2a2a;
}
/* Badge */
.dark .badge {
background-color: #1e1e1e;
@@ -235,6 +253,28 @@
background-color: #2a2a2a;
}
/* Newsletter input in dark mode */
.dark .input.dark-mode {
background-color: #1a1a1a;
border-color: #333;
color: #f5f5f5;
}
.dark .input.dark-mode:hover,
.dark .input.dark-mode:focus {
background-color: #222;
border-color: #444;
}
.dark .input.dark-mode::placeholder {
color: #666;
}
.dark .form-button.inside-input.dark-mode {
background-color: #f5f5f5;
color: #0d0d0d;
}
/* Dropdown menu */
.dark .w-dropdown-list {
background-color: #1e1e1e;
@@ -282,3 +322,115 @@
background-color: var(--core--colors--neutral--300);
}
/* Careers page — positions list */
.positions-list-wrapper {
display: flex;
flex-direction: column;
}
.position-item {
display: flex !important;
align-items: center;
padding: 24px 28px;
text-decoration: none;
border-bottom: 1px solid var(--core--colors--neutral--300);
transition: background-color 0.2s;
}
.position-item:last-child {
border-bottom: none;
}
.position-item:hover {
background-color: var(--core--colors--neutral--200);
}
.dark .position-item:hover {
background-color: #1a1a1a;
}
.position-item-content {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 24px;
}
.position-info {
flex: 1;
}
.position-details {
display: flex;
align-items: center;
gap: 8px;
margin-top: 8px;
}
/* Locale switcher */
.locale-switcher {
position: relative;
margin-left: 8px;
}
.locale-switcher-trigger {
display: flex;
align-items: center;
gap: 4px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--core--colors--neutral--400);
background: transparent;
cursor: pointer;
color: var(--core--colors--neutral--700);
font-size: 0.8rem;
font-weight: 500;
transition: background-color 0.2s;
}
.locale-switcher-trigger:hover {
background-color: var(--core--colors--neutral--300);
}
.locale-switcher-dropdown {
position: absolute;
top: calc(100% + 4px);
right: 0;
min-width: 80px;
border: 1px solid var(--core--colors--neutral--400);
border-radius: 8px;
background: var(--core--colors--neutral--100);
z-index: 100;
overflow: hidden;
}
.dark .locale-switcher-dropdown {
background: #1e1e1e;
}
.locale-switcher-option {
display: block;
width: 100%;
padding: 8px 12px;
border: none;
background: transparent;
cursor: pointer;
font-size: 0.8rem;
color: var(--font--colors--paragraph);
text-align: left;
transition: background-color 0.15s;
}
.locale-switcher-option:hover {
background-color: var(--core--colors--neutral--300);
}
.dark .locale-switcher-option:hover {
background-color: #2a2a2a;
}
.locale-switcher-option.active {
font-weight: 600;
}
+142
View File
@@ -0,0 +1,142 @@
import type { Metadata } from "next"
import Link from "next/link"
export const metadata: Metadata = {
title: "DAL Office — 文档也该有 AI 原生体验",
description:
"文字、表格、演示文稿——内置 AI 辅助起草、数据洞察和版式生成,非技术团队也能高效产出。",
}
const EDITORS = [
{
name: "文字处理",
description: "AI 辅助起草、润色、翻译。长文档自动摘要,会议纪要一键生成。",
},
{
name: "数据表格",
description: "自然语言查询数据,公式自动生成,异常值智能标注。",
},
{
name: "演示文稿",
description: "描述主题即可生成结构化幻灯片,版式和配图自动匹配。",
},
]
export default function OfficePage() {
return (
<main>
<section className="section hero-v1">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="office-hero"
style={{ opacity: "0", filter: "blur(8px)" }}
className="inner-container _480px _100-tablet"
>
<div className="subtitle">DAL Office</div>
<h1> AI </h1>
<div className="mg-top-4x-extra-small">
<p>
稿 AI
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="primary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper primary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg" />
<div className="button-icon-bg-inside" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
<section className="section overflow-hidden">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="office-editors-title"
style={{ opacity: "0", filter: "blur(8px)" }}
className="text-center"
>
<div className="subtitle">Editors</div>
<div className="mg-top-4x-extra-small">
<h2> AI </h2>
</div>
</div>
<div className="mg-top-large">
<div
data-w-id="office-editors-grid"
style={{ opacity: "0", filter: "blur(8px)" }}
className="corner-gradient-container"
>
<div className="border-wrapper">
<div className="w-layout-grid principles-grid">
{EDITORS.map((editor) => (
<div key={editor.name} className="card principles-card">
<div>
<h3 className="display-4">{editor.name}</h3>
<div className="mg-top-5x-extra-small">
<p>{editor.description}</p>
</div>
</div>
</div>
))}
</div>
</div>
<div data-wf--corner-gradient-outline--variant="base" className="corner-gradient-wrapper">
<div className="corner-gradient-horizontal top-left" />
<div className="corner-gradient-horizontal bottom-left" />
<div className="corner-gradient-horizontal top-right" />
<div className="corner-gradient-horizontal bottom-right" />
<div className="corner-gradient-vertical bottom-left" />
<div className="corner-gradient-vertical bottom-right" />
<div className="corner-gradient-vertical top-left" />
<div className="corner-gradient-vertical top-right" />
</div>
</div>
</div>
</div>
</section>
<section className="cta-section v1">
<div className="w-layout-blockcontainer container-default position-relative---z-index-1 w-container">
<div className="inner-container _430px">
<div className="subtitle">Early Access</div>
<div className="mg-top-3x-extra-small">
<h2 className="text-titles-dm">DAL Office </h2>
</div>
<div className="mg-top-4x-extra-small">
<p className="text-paragraph-dm">
AI 线
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="secondary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg bg-neutral-800" />
<div className="button-icon-bg-inside bg-neutral-600" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
</main>
)
}
+19 -1
View File
@@ -1,5 +1,17 @@
import type { Metadata } from "next"
import { HeroSection, IntegrationsSection, PrinciplesSection, CtaSection, BlogPreviewSection } from "@/components/home"
import {
HeroSection,
IntegrationsSection,
PrinciplesSection,
ProductEcosystem,
WorkflowSteps,
CtaSection,
FeatureGrid,
EcosystemSection,
FaqSection,
BottomCta,
BlogPreviewSection,
} from "@/components/home"
import { SITE_BRAND, SITE_DESCRIPTION } from "@/lib/site-content"
export const metadata: Metadata = {
@@ -17,7 +29,13 @@ export default function HomePage() {
<HeroSection />
<IntegrationsSection />
<PrinciplesSection />
<ProductEcosystem />
<WorkflowSteps />
<CtaSection />
<FeatureGrid />
<EcosystemSection />
<FaqSection />
<BottomCta />
<BlogPreviewSection />
</main>
)
+159
View File
@@ -0,0 +1,159 @@
import type { Metadata } from "next"
import Link from "next/link"
export const metadata: Metadata = {
title: "DeepAILab API Platform — 一层路由,连通所有模型",
description:
"20+ 供应商、统一密钥管理、按任务自动选模型。成本和质量不再是二选一。",
}
const CAPABILITIES = [
{
title: "智能路由",
description: "按任务类型、延迟要求和成本预算自动选择最优模型,策略统一管控。",
},
{
title: "密钥管理",
description: "BYOK 直连供应商 API,也支持平台托管。多团队、多项目独立配额。",
},
{
title: "用量分析",
description: "token 消耗、模型分布、成本趋势——实时仪表盘,数据驱动决策。",
},
{
title: "审计日志",
description: "每条请求可追溯:谁、什么时候、用了哪个模型、花了多少。满足企业合规需求。",
},
]
export default function PlatformPage() {
return (
<main>
<section className="section hero-v1">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="platform-hero"
style={{ opacity: "0", filter: "blur(8px)" }}
className="inner-container _480px _100-tablet"
>
<div className="subtitle">DeepAILab API Platform</div>
<h1></h1>
<div className="mg-top-4x-extra-small">
<p>
20+
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<a
href="https://deepailab.com"
target="_blank"
rel="noopener noreferrer"
className="primary-button w-inline-block"
>
<div className="button-content">
<div></div>
<div className="button-icon-wrapper primary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg" />
<div className="button-icon-bg-inside" />
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</section>
<section className="section overflow-hidden">
<div className="w-layout-blockcontainer container-default w-container">
<div
data-w-id="platform-caps-title"
style={{ opacity: "0", filter: "blur(8px)" }}
className="text-center"
>
<div className="subtitle">Capabilities</div>
<div className="mg-top-4x-extra-small">
<h2></h2>
</div>
<div className="mg-top-4x-extra-small">
<p>
DeepAILab AI
</p>
</div>
</div>
<div className="mg-top-large">
<div
data-w-id="platform-caps-grid"
style={{ opacity: "0", filter: "blur(8px)" }}
className="corner-gradient-container"
>
<div className="border-wrapper">
<div
className="w-layout-grid"
style={{ gridTemplateColumns: "1fr 1fr" }}
>
{CAPABILITIES.map((cap) => (
<div key={cap.title} className="card principles-card">
<div>
<h3 className="display-4">{cap.title}</h3>
<div className="mg-top-5x-extra-small">
<p>{cap.description}</p>
</div>
</div>
</div>
))}
</div>
</div>
<div data-wf--corner-gradient-outline--variant="base" className="corner-gradient-wrapper">
<div className="corner-gradient-horizontal top-left" />
<div className="corner-gradient-horizontal bottom-left" />
<div className="corner-gradient-horizontal top-right" />
<div className="corner-gradient-horizontal bottom-right" />
<div className="corner-gradient-vertical bottom-left" />
<div className="corner-gradient-vertical bottom-right" />
<div className="corner-gradient-vertical top-left" />
<div className="corner-gradient-vertical top-right" />
</div>
</div>
</div>
</div>
</section>
<section className="cta-section v1">
<div className="w-layout-blockcontainer container-default position-relative---z-index-1 w-container">
<div className="inner-container _430px">
<div className="subtitle">Get Started</div>
<div className="mg-top-3x-extra-small">
<h2 className="text-titles-dm"></h2>
</div>
<div className="mg-top-4x-extra-small">
<p className="text-paragraph-dm">
使
</p>
</div>
<div className="mg-top-2x-extra-small">
<div className="buttons-row left">
<Link href="/contact" className="secondary-button w-inline-block">
<div className="button-content">
<div></div>
<div className="button-icon-wrapper secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 17 17" fill="none" className="squared-icon">
<path d="M6.25391 3.45312L10.7458 8.01563L6.25391 12.5781" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" />
</svg>
<div className="button-icon-bg bg-neutral-800" />
<div className="button-icon-bg-inside bg-neutral-600" />
</div>
</div>
</Link>
</div>
</div>
</div>
</div>
</section>
</main>
)
}
+30
View File
@@ -0,0 +1,30 @@
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>
)
}