返回 CodeWhale
page.tsx
根目录 / web / app / [locale] / docs / guide / page.tsx
1 import Link from "next/link";
2 import { GettingStartedSteps } from "@/components/getting-started-steps";
3 import { SessionMedia } from "@/components/session-media";
4 import { NativeTerminalGallery } from "@/components/native-terminal-gallery";
5 import { GUIDE_NEXT_LINKS } from "@/lib/content/getting-started";
6 import { fill, getDocsGuide, getHome, pickText } from "@/lib/i18n/dictionaries";
7 import { getMediaAsset, TERMINAL_SCREENSHOT } from "@/lib/media-manifest";
8 import { buildPageMetadata } from "@/lib/page-meta";
9 import { getNativeTerminalCopy } from "@/lib/content/native-terminal";
10
11 export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
12 const { locale } = await params;
13 const t = getDocsGuide(locale);
14 return buildPageMetadata({
15 path: "/docs/guide",
16 locale,
17 title: t.metaTitle,
18 description: t.metaDescription,
19 });
20 }
21
22 export default async function GuidePage({ params }: { params: Promise<{ locale: string }> }) {
23 const { locale } = await params;
24 const t = getDocsGuide(locale);
25 const session = getMediaAsset("first-fleet-session");
26 const terminal = getNativeTerminalCopy(locale);
27 const home = getHome(locale);
28
29 return (
30 <section className="space-y-10">
31 <section id="overview" className="scroll-mt-32">
32 <h1 className="font-display text-3xl mb-1">{t.overviewTitle}</h1>
33 <p className={`${t.bodyClassName} mt-3`}>{t.overviewLead}</p>
34 </section>
35
36 <section id="path" className="scroll-mt-32">
37 <GettingStartedSteps locale={locale} headingLevel={2} />
38 </section>
39
40 <section id="terminal-views" className="scroll-mt-32">
41 <h2 className="font-display text-2xl mb-1">{terminal.title}</h2>
42 <p className={`${t.bodyClassName} mt-3 mb-4`}>{terminal.description}</p>
43 <div className="figure-frame">
44 <NativeTerminalGallery
45 locale={locale}
46 defaultFrame="composer"
47 regionLabel={home.shotPreview}
48 label={fill(home.screenshotAlt, { version: TERMINAL_SCREENSHOT.version })}
49 />
50 </div>
51 </section>
52
53 {session?.status === "published" && (
54 <section id="session-media" className="scroll-mt-32">
55 <h2 className="font-display text-2xl mb-1">{t.sessionTitle}</h2>
56 <p className={`${t.bodyClassName} mt-3 mb-4`}>{t.sessionLead}</p>
57 <SessionMedia asset={session} locale={locale} />
58 </section>
59 )}
60
61 <section id="next" className="scroll-mt-32">
62 <h2 className="font-display text-2xl mb-1">{t.nextTitle}</h2>
63 <div className="hairline-t mt-4">
64 {GUIDE_NEXT_LINKS.map((item) => (
65 <div key={item.href} className="py-4 hairline-b">
66 <h3 className="font-display text-xl">
67 <Link href={`/${locale}${item.href}`} className="hover:text-indigo transition-colors">
68 {pickText(item.label, locale)}
69 </Link>
70 </h3>
71 <p className={`${t.bodyClassName} mt-1 text-sm`}>{pickText(item.note, locale)}</p>
72 </div>
73 ))}
74 </div>
75 </section>
76
77 {/* Maintainer pointer: kept out of the rendered copy (experience mark 5). */}
78 <div hidden data-source-note={t.sourceNote} />
79 </section>
80 );
81 }
82
82 lines Plain Text