Files
popiart-server/web/app/[locale]/page.tsx
T
wtgoku ede502a63c Show the safe OpenClaw PopiArt skill install path
The public site now points OpenClaw users at the dedicated popiartcli skill directory and raw SKILL.md copy path, so installers do not scan runtime PopiSkills as agent skills.

Constraint: The server worktree already contains unrelated billing and UI edits, so this commit is intentionally limited to the homepage content and renderer.

Rejected: Document only in popiartcli README | users may follow the website install flow instead.

Confidence: high

Scope-risk: narrow

Directive: Keep OpenClaw installation guidance pointed at popiartcli/tree/main/skill, not a repository-root skills directory.

Tested: npm run build in web

Not-tested: Live deployed website smoke test.
2026-04-29 13:02:56 +08:00

242 lines
10 KiB
TypeScript

import Link from "next/link";
import { getDictionary, type Locale } from "@/lib/site-content";
export default async function HomePage({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const typedLocale = locale as Locale;
const dictionary = getDictionary(typedLocale);
const isZh = typedLocale === "zh";
const integrationTitle = isZh ? "popiartcli 接入原生流程" : "Native integration flow for popiartcli";
const integrationSubtitle = isZh
? "按照以下步骤,将 popiartcli 无缝接入你的 agent 工作流"
: "Follow these steps to plug popiartcli directly into your coding agent workflow.";
const stepOneTitle = isZh ? "复制安装指令到你的环境" : "Copy the install command into your environment";
const stepOneHint = isZh
? "先安装 CLI,再登录获取产品层 key"
: "Install the CLI first, then sign in to get the product-layer key.";
const stepTwoTitle = isZh
? "执行 bootstrap,让 PopiArt 在你的 agent 环境中可发现"
: "Run bootstrap so PopiArt becomes discoverable in your agent environment.";
const stepTwoHint = isZh
? "生成 completion、默认 discovery profile,并接入 Codex / OpenCode / OpenClaw"
: "Generate completion, default discovery profiles, and wire into Codex, OpenCode, or OpenClaw.";
const stepThreeTitle = isZh
? "如需轮换或重置产品层 token,请前往控制台管理密钥"
: "Rotate or reset the product-layer token from the console when needed.";
const stepThreeHint = isZh
? "使用 API key 与 session,而不是把 provider 密钥直接分发到本地环境"
: "Use API keys and sessions instead of distributing raw provider credentials to local machines.";
const stepFourTitle = isZh
? "了解更多功能及服务使用须知,请查看开发者文档"
: "Read the developer docs for capabilities, runtime behavior, and usage guidance.";
const docsAction = isZh ? "查看开发者文档" : "Open developer docs";
const installAction = isZh ? "登录" : "Sign in";
const bootstrapAction = isZh ? "查看 Quick Start" : "Open Quick Start";
const consoleAction = isZh ? "前往控制台" : "Open console";
const sceneAction = isZh ? "了解更多" : "Learn more";
return (
<div className="page-stack">
<section className="hero-panel hero-panel-reference">
<div className="hero-copy">
<div className="eyebrow">{dictionary.home.tag}</div>
<h1>{dictionary.home.title}</h1>
<p className="hero-description">{dictionary.home.subtitle}</p>
<div className="hero-actions">
<Link className="button button-dark" href={`/${locale}#integration`}>
{dictionary.home.primaryCta}
</Link>
<Link className="button button-light" href={`/${locale}/docs`}>
{dictionary.home.secondaryCta}
</Link>
</div>
<div className="hero-proof">
<span>{dictionary.home.freeTrial}</span>
<span>{dictionary.home.socialProof}</span>
</div>
</div>
<div className="hero-stage hero-stage-reference">
<div className="hero-pattern" aria-hidden="true">
{Array.from({ length: 5 }).map((_, row) => (
<div className="hero-pattern-row" key={row}>
{dictionary.home.heroPhrases.map((phrase) => (
<span key={`${row}-${phrase}`}>{phrase}</span>
))}
</div>
))}
</div>
<div className="stage-card stage-card-floating stage-card-primary">
<div className="stage-label">{dictionary.home.stageLabel}</div>
<div className="stage-stat">{dictionary.home.stageValue}</div>
<p>{dictionary.home.stageDescription}</p>
</div>
</div>
</section>
<section className="section-panel">
<div className="section-heading">
<div className="eyebrow">{dictionary.home.scenesTag}</div>
<h2>{dictionary.home.scenesTitle}</h2>
<p>{dictionary.home.scenesSubtitle}</p>
</div>
<div className="card-grid card-grid-three">
{dictionary.home.scenes.map((scene, index) => (
<article className="feature-card scene-card" key={scene.name}>
<div className={`scene-visual scene-visual-${(index % 6) + 1}`}>
<span className="card-kicker">{scene.category}</span>
</div>
<span className="card-kicker">{scene.category}</span>
<h3>{scene.name}</h3>
<p>{scene.description}</p>
<Link className="scene-link" href={`/${locale}/docs`}>
{sceneAction}
</Link>
</article>
))}
</div>
</section>
<section className="integration-shell" id="integration">
<div className="integration-heading">
<div className="eyebrow">{dictionary.home.flowTag}</div>
<h2>{integrationTitle}</h2>
<p>{integrationSubtitle}</p>
</div>
<div className="integration-steps">
<article className="integration-step-card">
<div className="integration-step-head">
<span className="integration-step-dot" aria-hidden="true" />
<span className="integration-step-label">STEP 1</span>
<h3>{stepOneTitle}</h3>
</div>
<div className="integration-step-body">
<pre>
<code>{dictionary.home.installMethods[0]?.command}</code>
</pre>
<div className="integration-method-pills">
{dictionary.home.installMethods.map((method) => (
<span className="pill" key={method.name}>
{method.name}
</span>
))}
</div>
<div className="integration-step-actions">
<span>{stepOneHint}</span>
<Link className="button button-dark" href={`/${locale}/login`}>
{installAction}
</Link>
</div>
</div>
</article>
<article className="integration-step-card">
<div className="integration-step-head">
<span className="integration-step-dot" aria-hidden="true" />
<span className="integration-step-label">STEP 2</span>
<h3>{stepTwoTitle}</h3>
</div>
<div className="integration-step-body">
<pre>
<code>{dictionary.home.bootstrapCommand}</code>
</pre>
<div className="integration-step-actions">
<span>{stepTwoHint}</span>
<Link className="button button-light integration-docs-link" href={`/${locale}/docs`}>
{bootstrapAction}
<span aria-hidden="true"></span>
</Link>
</div>
</div>
</article>
<article className="integration-step-card">
<div className="integration-step-head">
<span className="integration-step-dot" aria-hidden="true" />
<span className="integration-step-label">OPENCLAW</span>
<h3>{dictionary.home.agentSkillTitle}</h3>
</div>
<div className="integration-step-body">
<p>{dictionary.home.agentSkillDescription}</p>
<pre>
<code>{dictionary.home.agentSkillCommand}</code>
</pre>
</div>
</article>
<article className="integration-step-card">
<div className="integration-step-head">
<span className="integration-step-dot" aria-hidden="true" />
<span className="integration-step-label">STEP 3</span>
<h3>{stepThreeTitle}</h3>
</div>
<div className="integration-step-body integration-step-body-compact">
<div className="integration-step-actions">
<span>{stepThreeHint}</span>
<Link className="button button-light integration-docs-link" href={`/${locale}/console`}>
{consoleAction}
<span aria-hidden="true"></span>
</Link>
</div>
</div>
</article>
<article className="integration-step-card">
<div className="integration-step-head">
<span className="integration-step-dot" aria-hidden="true" />
<span className="integration-step-label">STEP 4</span>
<h3>{stepFourTitle}</h3>
</div>
<div className="integration-step-body integration-step-body-compact">
<Link className="button button-light integration-docs-link" href={`/${locale}/docs`}>
{docsAction}
<span aria-hidden="true"></span>
</Link>
</div>
</article>
</div>
</section>
<section className="section-panel section-panel-accent">
<div className="section-heading">
<div className="eyebrow">{dictionary.pricing.tag}</div>
<h2>{dictionary.pricing.title}</h2>
<p>{dictionary.pricing.subtitle}</p>
</div>
<div className="pricing-grid">
{dictionary.pricing.plans.map((plan) => (
<article
className={`pricing-card ${plan.highlight ? "pricing-card-highlight" : ""}`}
key={plan.name}
>
<div className="pricing-top">
<div>
<div className="card-kicker">{plan.badge}</div>
<h3>{plan.name}</h3>
<p className="pricing-summary">{plan.summary}</p>
</div>
<div className="price-line">
<strong>{plan.price}</strong>
<span>{plan.cadence}</span>
</div>
</div>
<ul className="bullet-list">
{plan.features.map((feature) => (
<li key={feature}>{feature}</li>
))}
</ul>
<Link className={`button ${plan.highlight ? "button-dark" : "button-light"}`} href={`/${locale}/pricing`}>
{plan.cta}
</Link>
</article>
))}
</div>
</section>
</div>
);
}