This is an automated email from the ASF dual-hosted git repository. chaokunyang pushed a commit to branch refine_website in repository https://gitbox.apache.org/repos/asf/fory-site.git
commit 69f44f3d661d31ab0c38aae7d429c5f21da3d538 Author: chaokunyang <[email protected]> AuthorDate: Sun May 31 10:23:30 2026 +0800 Refine homepage design --- src/components/home/HomepageLanding.module.css | 432 ++++++++++++------- src/components/home/HomepageLanding.tsx | 553 ++++++++++++++----------- src/css/custom.css | 28 +- 3 files changed, 606 insertions(+), 407 deletions(-) diff --git a/src/components/home/HomepageLanding.module.css b/src/components/home/HomepageLanding.module.css index c3a43801dd..a51836e64f 100644 --- a/src/components/home/HomepageLanding.module.css +++ b/src/components/home/HomepageLanding.module.css @@ -10,20 +10,19 @@ } .hero { - align-items: stretch; + align-items: center; background: linear-gradient(90deg, rgba(255, 112, 1, 0.055), transparent 32%), linear-gradient(180deg, var(--ifm-background-color), #f9fafb); display: grid; gap: 2rem; - grid-template-columns: minmax(0, 1fr) minmax(420px, 0.9fr); - min-height: 720px; + grid-template-columns: minmax(0, 0.9fr) minmax(440px, 0.82fr); + min-height: 560px; padding: 4rem max(2rem, calc((100vw - 1180px) / 2)) 4rem; } .heroContent { - align-self: center; - max-width: 680px; + max-width: 690px; } .eyebrow, @@ -70,8 +69,9 @@ display: inline-flex; font-weight: 700; justify-content: center; + min-width: 11.25rem; min-height: 44px; - padding: 0.7rem 1rem; + padding: 0.7rem 1.1rem; text-decoration: none; transition: border-color 160ms ease, background 160ms ease, color 160ms ease, transform 160ms ease; } @@ -106,152 +106,119 @@ } .ghostButton { - background: transparent; - border: 1px solid transparent; - color: var(--ifm-color-emphasis-800); -} - -.ghostButton:hover { - background: var(--ifm-color-emphasis-100); - color: var(--ifm-font-color-base); -} - -.trustList { - display: grid; - gap: 0.75rem; - grid-template-columns: repeat(4, minmax(0, 1fr)); - margin: 2.25rem 0 0; -} - -.trustList div { - border-left: 2px solid var(--ifm-color-primary); - padding-left: 0.85rem; -} - -.trustList dt { - color: var(--ifm-font-color-base); - font-size: 0.86rem; - font-weight: 800; -} - -.trustList dd { - color: var(--ifm-color-emphasis-700); - font-size: 0.82rem; - margin: 0.25rem 0 0; -} - -.heroVisual { - align-self: center; - background: var(--fory-surface); - border: 1px solid var(--fory-border); - border-radius: 8px; - box-shadow: var(--fory-card-shadow); + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); color: var(--ifm-font-color-base); - overflow: hidden; } -.panelHeader { - align-items: flex-start; - border-bottom: 1px solid var(--fory-border); - display: flex; - gap: 1rem; - justify-content: space-between; - padding: 1.1rem; +.ghostButton:hover { + border-color: var(--ifm-color-primary); + color: var(--ifm-color-primary); } -.panelHeader strong, .runtimeTitleRow span { display: block; font-size: 1rem; } -.panelHeader span { - color: var(--fory-muted); - display: block; - font-size: 0.86rem; - line-height: 1.5; - margin-top: 0.25rem; +.surfacePanel { + justify-self: end; + max-width: 540px; + min-width: 0; + width: 100%; } -.panelBadge { - background: #ecfdf5; - border: 1px solid #a7f3d0; - border-radius: 999px; - color: #047857 !important; - flex: 0 0 auto; - font-size: 0.76rem !important; - font-weight: 800; - margin-top: 0 !important; - padding: 0.28rem 0.58rem; +.surfaceOptions { + display: grid; + gap: 0.85rem; + grid-template-columns: repeat(2, minmax(0, 1fr)); } -.flowGrid { +.surfaceOption { + --surface-accent: var(--ifm-color-primary); + --surface-badge-bg: rgba(255, 112, 1, 0.09); + --surface-badge-border: rgba(255, 112, 1, 0.2); + --surface-wash: rgba(255, 112, 1, 0.045); + align-items: flex-start; + background: + linear-gradient(180deg, var(--surface-wash), rgba(255, 255, 255, 0) 74px), + var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-top: 1px solid var(--surface-badge-border); + border-radius: 8px; + color: var(--ifm-font-color-base); display: grid; - gap: 0.75rem; - grid-template-columns: 1fr 28px 1fr 28px 1fr; - padding: 1.1rem; + gap: 0.7rem; + min-height: 136px; + padding: 1rem; + text-decoration: none; + transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; } -.flowNode { - background: var(--fory-code-bg); - border: 1px solid var(--fory-border); - border-radius: 8px; - min-width: 0; - padding: 0.85rem; +.surfaceOption:nth-child(2) { + --surface-accent: #0f766e; + --surface-badge-bg: rgba(15, 118, 110, 0.09); + --surface-badge-border: rgba(15, 118, 110, 0.18); + --surface-wash: rgba(15, 118, 110, 0.045); } -.flowNode span { - color: #0e7490; - display: block; - font-size: 0.72rem; - font-weight: 900; - margin-bottom: 0.45rem; +.surfaceOption:nth-child(3) { + --surface-accent: #2563eb; + --surface-badge-bg: rgba(37, 99, 235, 0.08); + --surface-badge-border: rgba(37, 99, 235, 0.16); + --surface-wash: rgba(37, 99, 235, 0.04); } -.flowNode strong { - display: block; - font-size: 0.86rem; +.surfaceOption:nth-child(4) { + --surface-accent: #475569; + --surface-badge-bg: rgba(71, 85, 105, 0.08); + --surface-badge-border: rgba(71, 85, 105, 0.16); + --surface-wash: rgba(71, 85, 105, 0.035); } -.flowNode code { - background: transparent; - color: #6941c6; - display: block; - font-size: 0.72rem; - line-height: 1.4; - margin-top: 0.45rem; - overflow-wrap: anywhere; - padding: 0; +.surfaceOption:hover { + border-color: var(--surface-accent); + box-shadow: 0 14px 34px rgba(31, 41, 55, 0.08); + color: var(--ifm-font-color-base); + text-decoration: none; + transform: translateY(-1px); } -.flowLine { - align-self: center; - background: var(--ifm-color-primary); - height: 2px; - opacity: 0.75; +.surfaceOptionBadge { + background: var(--surface-badge-bg); + border: 1px solid var(--surface-badge-border); + border-radius: 999px; + color: var(--surface-accent); + display: inline-flex; + font-size: 0.72rem; + font-weight: 900; + justify-content: center; + max-width: max-content; + padding: 0.25rem 0.45rem; + text-align: center; } -.heroCode { - border-top: 1px solid var(--fory-border); +.surfaceOptionBody { + display: grid; + gap: 0.35rem; min-width: 0; } -.heroCode :global(.theme-code-block) { - background: var(--fory-code-bg); - border-radius: 0; - box-shadow: none; - margin: 0; +.surfaceOptionBody strong { + font-size: 1.02rem; + font-weight: 800; + line-height: 1.25; } -.heroCode :global(pre.prism-code) { - background: var(--fory-code-bg) !important; - font-size: 0.85rem; - line-height: 1.6; - padding: 1.1rem; +.surfaceOptionBody small { + color: var(--ifm-color-emphasis-800); + font-size: 0.82rem; + line-height: 1.45; } .quickStart, .capabilities, +.schemaIdl, .useCases { padding: 5rem max(2rem, calc((100vw - 1180px) / 2)); } @@ -444,6 +411,129 @@ margin: 0; } +.schemaIdl { + background: linear-gradient(180deg, var(--fory-soft-band), var(--ifm-background-color)); +} + +.schemaLayout { + align-items: stretch; + display: grid; + gap: 1.4rem; + grid-template-columns: minmax(0, 0.84fr) minmax(480px, 1fr); +} + +.schemaCopy { + align-self: center; + max-width: 520px; +} + +.schemaCopy h2 { + font-size: 2.35rem; + line-height: 1.12; + margin: 0; +} + +.schemaCopy > p { + color: var(--ifm-color-emphasis-800); + font-size: 1.04rem; + line-height: 1.7; + margin: 1rem 0 0; +} + +.schemaFeatureList { + display: grid; + gap: 0.85rem; + margin: 1.8rem 0 1.4rem; +} + +.schemaFeature { + align-items: flex-start; + background: + linear-gradient(90deg, rgba(255, 112, 1, 0.055), transparent 44%), + var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + display: grid; + gap: 0.85rem; + grid-template-columns: 42px minmax(0, 1fr); + padding: 0.95rem; +} + +.schemaFeature > span { + align-items: center; + background: rgba(255, 112, 1, 0.11); + border-radius: 7px; + color: var(--ifm-color-primary); + display: inline-flex; + font-size: 0.78rem; + font-weight: 900; + height: 34px; + justify-content: center; +} + +.schemaFeature h3 { + font-size: 1rem; + margin: 0 0 0.35rem; +} + +.schemaFeature p { + color: var(--ifm-color-emphasis-800); + font-size: 0.9rem; + line-height: 1.55; + margin: 0; +} + +.schemaPreview { + align-self: stretch; + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + box-shadow: 0 16px 40px rgba(31, 41, 55, 0.07); + display: flex; + flex-direction: column; + min-width: 0; + overflow: hidden; +} + +.schemaPreviewHeader { + align-items: center; + border-bottom: 1px solid var(--ifm-color-emphasis-200); + display: flex; + gap: 1rem; + justify-content: space-between; + padding: 0.85rem 1rem; +} + +.schemaPreviewHeader span { + color: var(--fory-muted); + font-size: 0.82rem; + font-weight: 800; +} + +.schemaPreviewHeader strong { + color: var(--ifm-color-primary); + font-size: 0.8rem; + text-transform: uppercase; +} + +.schemaPreview :global(.theme-code-block) { + background: var(--fory-code-bg); + border-radius: 0; + box-shadow: none; + flex: 1; + margin: 0; +} + +.schemaPreview :global(pre.prism-code) { + background: var(--fory-code-bg) !important; + height: 100%; + font-size: 0.86rem; + line-height: 1.6; + margin: 0; + min-height: 430px; + padding: 1.2rem; +} + .performance { align-items: center; display: grid; @@ -476,8 +566,8 @@ .performanceCard strong { color: var(--ifm-color-primary); display: block; - font-size: 2.2rem; - line-height: 1; + font-size: 1.28rem; + line-height: 1.15; } .performanceCard span { @@ -541,50 +631,69 @@ } .adoptionCard { + align-items: flex-start; background: #ffffff; border: 1px solid var(--fory-border); - border-top: 3px solid rgba(255, 112, 1, 0.55); + border-left: 3px solid rgba(255, 112, 1, 0.65); border-radius: 8px; color: var(--ifm-font-color-base); - min-height: 220px; - padding: 1.25rem; + display: grid; + gap: 0.9rem; + grid-template-columns: 34px minmax(0, 1fr); + min-height: 0; + padding: 1rem; text-decoration: none; - transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; + transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease; } .adoptionCard:hover { + background: rgba(255, 112, 1, 0.045); border-color: var(--ifm-color-primary); - color: var(--ifm-color-primary); box-shadow: 0 14px 36px rgba(31, 41, 55, 0.08); + color: var(--ifm-font-color-base); text-decoration: none; transform: translateY(-2px); } -.adoptionCard span { +.adoptionStep { + align-items: center; + background: rgba(255, 112, 1, 0.1); + border-radius: 7px; color: var(--ifm-color-primary); - display: block; + display: inline-flex; font-size: 0.76rem; font-weight: 900; - margin-bottom: 1rem; + height: 34px; + justify-content: center; } -.adoptionCard h3 { +.adoptionDocText { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.adoptionDocText strong { color: var(--ifm-font-color-base); - font-size: 1.18rem; - margin: 0 0 0.65rem; + font-size: 1rem; + font-weight: 900; + line-height: 1.25; } -.adoptionCard p { +.adoptionDocText small { color: var(--ifm-color-emphasis-800); - line-height: 1.65; - margin: 0; + font-size: 0.82rem; + line-height: 1.35; } -.adoptionCard strong { +.adoptionDocText code { + background: transparent; + border: 0; color: var(--ifm-color-primary); - display: inline-block; - font-size: 0.88rem; - margin-top: 1rem; + font-size: 0.72rem; + line-height: 1.35; + overflow-wrap: anywhere; + padding: 0; } [data-theme="dark"] .hero { @@ -604,6 +713,8 @@ [data-theme="dark"] .runtimeShell, [data-theme="dark"] .capabilityCard, +[data-theme="dark"] .schemaFeature, +[data-theme="dark"] .schemaPreview, [data-theme="dark"] .performanceCard, [data-theme="dark"] .useCaseCard, [data-theme="dark"] .adoptionCard { @@ -619,10 +730,15 @@ color: #99f6e4; } -[data-theme="dark"] .panelBadge { - background: rgba(20, 184, 166, 0.14); - border-color: rgba(20, 184, 166, 0.34); - color: #99f6e4 !important; +[data-theme="dark"] .surfaceOption { + background: + linear-gradient(180deg, var(--surface-wash), rgba(23, 32, 51, 0) 74px), + #172033; + border-color: rgba(148, 163, 184, 0.24); +} + +[data-theme="dark"] .surfaceOption:hover { + border-color: var(--surface-accent); } [data-theme="dark"] .ecosystem { @@ -636,6 +752,7 @@ @media (max-width: 1100px) { .hero, + .schemaLayout, .performance { grid-template-columns: 1fr; } @@ -644,19 +761,29 @@ min-height: auto; } - .heroVisual { - max-width: 760px; + .surfacePanel { + justify-self: start; + max-width: 640px; } .performanceCopy { max-width: none; } + + .schemaCopy { + max-width: 760px; + } + + .schemaPreview :global(pre.prism-code) { + min-height: auto; + } } @media (max-width: 996px) { .hero, .quickStart, .capabilities, + .schemaIdl, .performance, .useCases, .ecosystem { @@ -673,12 +800,12 @@ } .sectionHeader h2, + .schemaCopy h2, .performanceCopy h2, .ecosystem h2 { font-size: 2rem; } - .trustList, .capabilityGrid, .performanceCards, .useCaseGrid, @@ -695,15 +822,6 @@ border-right: 0; } - .flowGrid { - grid-template-columns: 1fr; - } - - .flowLine { - height: 18px; - justify-self: center; - width: 2px; - } } @media (max-width: 560px) { @@ -734,9 +852,17 @@ flex-direction: column; } + .surfaceOption { + grid-template-columns: 1fr; + } + + .surfaceOptions { + grid-template-columns: 1fr; + } + .installBlock :global(pre.prism-code), .codeBlock :global(pre.prism-code), - .heroCode :global(pre.prism-code) { + .schemaPreview :global(pre.prism-code) { font-size: 0.78rem; } } diff --git a/src/components/home/HomepageLanding.tsx b/src/components/home/HomepageLanding.tsx index 6af4c2acb8..73ac691ffc 100644 --- a/src/components/home/HomepageLanding.tsx +++ b/src/components/home/HomepageLanding.tsx @@ -15,8 +15,7 @@ type RuntimeId = | "swift" | "dart" | "scala" - | "kotlin" - | "xlang"; + | "kotlin"; type RuntimeExample = { id: RuntimeId; @@ -36,15 +35,6 @@ type Copy = { heroPrimary: string; heroSecondary: string; heroGithub: string; - heroVersion: string; - heroRuntimes: string; - heroBenchmarks: string; - heroApache: string; - heroPanelTitle: string; - heroPanelSubtitle: string; - heroFlowSource: string; - heroFlowWire: string; - heroFlowTarget: string; quickEyebrow: string; quickTitle: string; quickSubtitle: string; @@ -54,6 +44,9 @@ type Copy = { capabilitiesEyebrow: string; capabilitiesTitle: string; capabilitiesSubtitle: string; + schemaEyebrow: string; + schemaTitle: string; + schemaSubtitle: string; performanceEyebrow: string; performanceTitle: string; performanceSubtitle: string; @@ -67,88 +60,76 @@ type Copy = { const copies: Record<"en" | "zh", Copy> = { en: { - heroEyebrow: "Apache Fory 1.0", - heroTitle: "Fast object serialization across languages.", + heroEyebrow: "Multi-language serialization framework", + heroTitle: "Apache Fory™", heroSubtitle: - "Fory serializes native domain objects, preserves object graphs, and gives teams a compact cross-language wire format with Schema IDL when contracts need to be explicit.", + "A blazingly-fast multi-language serialization framework for idiomatic domain objects, Schema IDL, and cross-language data exchange.", heroPrimary: "Get Started", heroSecondary: "View Docs", - heroGithub: "GitHub", - heroVersion: "1.0.0 release", - heroRuntimes: "12 runtime entries", - heroBenchmarks: "Benchmarks by language", - heroApache: "Apache project", - heroPanelTitle: "Native objects in, portable bytes out", - heroPanelSubtitle: - "Use xlang mode for payloads that cross runtime boundaries, or native mode for same-runtime hot paths.", - heroFlowSource: "Java object", - heroFlowWire: "Fory payload", - heroFlowTarget: "Python object", + heroGithub: "View GitHub", quickEyebrow: "Quick start", - quickTitle: "Choose a runtime and copy a current example.", + quickTitle: "Start from native domain objects.", quickSubtitle: - "The homepage examples are intentionally short. Each one links to the full guide for configuration, schema evolution, references, and production notes.", + "Pick a language, register a native type with a stable name, then serialize and deserialize with a small Fory runtime.", installLabel: "Install", codeLabel: "Serialize / deserialize", guideLabel: "Open guide", capabilitiesEyebrow: "Core capabilities", - capabilitiesTitle: "Built for language boundaries, object graphs, and hot paths.", + capabilitiesTitle: "What Fory is built to handle.", capabilitiesSubtitle: - "Fory combines a portable wire format with runtime-specific optimization and object-graph semantics that ordinary IDL-first serializers often flatten away.", + "Fory brings together cross-language serialization, native object support, Schema IDL/code generation, reference tracking, schema evolution, and row-format access.", + schemaEyebrow: "Schema IDL", + schemaTitle: "Model contracts that still understand object graphs.", + schemaSubtitle: + "Fory IDL starts with familiar message definitions, then adds unions and reference-aware fields for data models that ordinary IDLs tend to flatten.", performanceEyebrow: "Performance", - performanceTitle: "Keep hot paths compact, typed, and fast.", + performanceTitle: "Measure the runtime you plan to ship.", performanceSubtitle: - "Homepage numbers stay high level; the full charts, raw notes, and reproduction details remain in the benchmark documentation.", + "Compare language-specific benchmark results with the same workloads, chart notes, and reproduction details.", benchmarkCta: "View full benchmark charts", - useCasesEyebrow: "Use cases", - useCasesTitle: "Built for language boundaries and data-heavy systems.", + useCasesEyebrow: "Data boundaries", + useCasesTitle: "Match Fory to each data boundary.", useCasesSubtitle: - "Use Fory where object graphs, schema evolution, and high-throughput binary data need to coexist.", - ecosystemTitle: "Choose the adoption path that matches your system.", + "Use one serialization layer, but choose the payload surface by the boundary your data crosses.", + ecosystemTitle: "Adopt Fory without changing the object model.", ecosystemSubtitle: - "Move from a single runtime to shared schemas and measured performance without changing the object model.", + "Start with native objects, promote shared contracts to Schema IDL when teams need them, then validate the exact runtime path with benchmarks.", }, zh: { - heroEyebrow: "Apache Fory 1.0", - heroTitle: "面向多语言系统的高性能对象序列化。", + heroEyebrow: "多语言序列化框架", + heroTitle: "Apache Fory™", heroSubtitle: - "Fory 直接序列化原生领域对象,保留对象图语义,并提供紧凑的跨语言线格式;当团队需要显式契约时,也可以使用 Schema IDL。", + "一个面向原生领域对象、Schema IDL 和跨语言数据交换的高性能多语言序列化框架。", heroPrimary: "开始使用", heroSecondary: "查看文档", - heroGithub: "GitHub", - heroVersion: "1.0.0 版本", - heroRuntimes: "12 个运行时入口", - heroBenchmarks: "多语言性能测试", - heroApache: "Apache 项目", - heroPanelTitle: "原生对象输入,可移植字节输出", - heroPanelSubtitle: - "跨运行时载荷使用 xlang 模式;同一运行时的热点路径可以选择 native 模式。", - heroFlowSource: "Java 对象", - heroFlowWire: "Fory 载荷", - heroFlowTarget: "Python 对象", + heroGithub: "查看 GitHub", quickEyebrow: "快速开始", - quickTitle: "选择运行时,复制当前可用示例。", + quickTitle: "从原生领域对象开始。", quickSubtitle: - "首页示例刻意保持精简。每个示例都会链接到完整指南,覆盖配置、Schema 演进、引用和生产使用注意事项。", + "选择一种语言,用稳定名称注册原生类型,然后通过 Fory 运行时完成序列化和反序列化。", installLabel: "安装", codeLabel: "序列化 / 反序列化", guideLabel: "打开指南", capabilitiesEyebrow: "核心能力", - capabilitiesTitle: "面向语言边界、对象图和热点路径而设计。", + capabilitiesTitle: "Fory 面向这些问题而设计。", capabilitiesSubtitle: - "Fory 将可移植线格式、运行时定制优化和对象图语义结合起来,避免传统 IDL 优先序列化器常见的语义压平。", + "Fory 将跨语言序列化、原生对象支持、Schema IDL/codegen、引用跟踪、Schema 演进和 row-format 访问组合在一起。", + schemaEyebrow: "Schema IDL", + schemaTitle: "理解对象图的模型契约。", + schemaSubtitle: + "Fory IDL 从熟悉的 message 定义开始,并提供 union 与引用感知字段,表达普通 IDL 容易压平的对象模型。", performanceEyebrow: "性能", - performanceTitle: "让热点路径保持紧凑、类型化和高速。", + performanceTitle: "测量你真正要上线的运行时。", performanceSubtitle: - "首页只保留高层性能入口;完整图表、原始说明和复现细节仍保留在 Benchmark 文档中。", + "按语言对比相同工作负载下的 Benchmark 结果、图表说明和复现细节。", benchmarkCta: "查看完整性能图表", - useCasesEyebrow: "使用场景", - useCasesTitle: "为语言边界和数据密集型系统而设计。", + useCasesEyebrow: "数据边界", + useCasesTitle: "让 Fory 匹配每一种数据边界。", useCasesSubtitle: - "当对象图、Schema 演进和高吞吐二进制数据需要共存时,Fory 可以作为统一的序列化层。", - ecosystemTitle: "选择适合当前系统的采用路径。", + "使用同一层序列化能力,但根据数据跨越的边界选择不同 payload 表面。", + ecosystemTitle: "不改变对象模型地采用 Fory。", ecosystemSubtitle: - "从单一运行时开始,再逐步走向共享 Schema 和可复现性能验证,而不改变领域对象模型。", + "从原生对象开始;当契约需要跨团队共享时推进到 Schema IDL;上线前用 Benchmark 验证具体运行时路径。", }, }; @@ -164,7 +145,7 @@ const runtimeExamples: RuntimeExample[] = [ </dependency>`, codeLanguage: "java", guide: "/docs/guide/java/", - summary: "JVM runtime with xlang and native modes, JIT serializers, and object graph support.", + summary: "Java supports xlang and native modes, JIT serializers, schema evolution, and Java-native object graph features.", code: `import org.apache.fory.Fory; public record Person(String name, int age) {} @@ -172,7 +153,7 @@ public record Person(String name, int age) {} Fory fory = Fory.builder() .withXlang(true) .build(); -fory.register(Person.class, "example", "Person"); +fory.register(Person.class, "Person"); byte[] bytes = fory.serialize(new Person("Alice", 30)); Person out = (Person) fory.deserialize(bytes);`, @@ -181,10 +162,10 @@ Person out = (Person) fory.deserialize(bytes);`, id: "python", label: "Python", installLanguage: "bash", - install: `pip install pyfory==1.0.0`, + install: `pip install pyfory`, codeLanguage: "python", guide: "/docs/guide/python/", - summary: "Python dataclasses, native Python object graphs, and xlang payloads.", + summary: "pyfory supports xlang, Python native mode, dataclasses, row format, and out-of-band buffers.", code: `from dataclasses import dataclass import pyfory @@ -194,7 +175,7 @@ class Person: age: pyfory.Int32 fory = pyfory.Fory(xlang=True) -fory.register(Person, typename="example.Person") +fory.register(Person, typename="Person") data = fory.serialize(Person("Alice", 30)) out = fory.deserialize(data)`, @@ -206,10 +187,10 @@ out = fory.deserialize(data)`, install: `cargo add [email protected]`, codeLanguage: "rust", guide: "/docs/guide/rust/", - summary: "Typed Rust structs with derive-based registration and xlang support.", - code: `use fory::{Error, Fory, ForyObject}; + summary: "Rust uses derive macros for type-safe structs and supports both xlang and native payloads.", + code: `use fory::{Error, Fory, ForyStruct}; -#[derive(ForyObject, Debug, PartialEq)] +#[derive(ForyStruct, Debug, PartialEq)] struct Person { name: String, age: i32, @@ -217,7 +198,7 @@ struct Person { fn main() -> Result<(), Error> { let mut fory = Fory::builder().xlang(true).build(); - fory.register_by_name::<Person>("example", "Person")?; + fory.register_by_name::<Person>("", "Person")?; let bytes = fory.serialize(&Person { name: "Alice".into(), age: 30 })?; let out: Person = fory.deserialize(&bytes)?; @@ -228,17 +209,17 @@ fn main() -> Result<(), Error> { id: "go", label: "Go", installLanguage: "bash", - install: `go get github.com/apache/fory/go/[email protected]`, + install: `go get github.com/apache/fory/go/fory`, codeLanguage: "go", guide: "/docs/guide/go/", - summary: "Go structs, native mode, xlang mode, and explicit registration.", + summary: "Go supports xlang and native modes with exported structs, circular references, and schema-aware serializers.", code: `type Person struct { Name string Age int32 } f := fory.New(fory.WithXlang(true)) -_ = f.RegisterStruct(Person{}, 1) +_ = f.RegisterStructByName(Person{}, "Person") payload, _ := f.Serialize(&Person{Name: "Alice", Age: 30}) var out Person @@ -256,7 +237,7 @@ _ = f.Deserialize(payload, &out)`, )`, codeLanguage: "cpp", guide: "/docs/guide/cpp/", - summary: "Modern C++17 serialization with compile-time type safety and xlang mode.", + summary: "C++17 support covers xlang/native payloads, macro-based type registration, and row-format APIs.", code: `struct Person { std::string name; int32_t age; @@ -267,8 +248,8 @@ _ = f.Deserialize(payload, &out)`, }; FORY_STRUCT(Person, name, age); -auto fory = Fory::builder().xlang(true).build(); -fory.register_struct<Person>(1); +auto fory = Fory::builder().xlang(true).track_ref(false).build(); +fory.register_struct<Person>("Person"); auto bytes = fory.serialize(Person{"Alice", 30}).value(); auto out = fory.deserialize<Person>(bytes).value();`, @@ -280,11 +261,11 @@ auto out = fory.deserialize<Person>(bytes).value();`, install: `npm install @apache-fory/core`, codeLanguage: "typescript", guide: "/docs/guide/javascript/", - summary: "JavaScript and TypeScript xlang payloads for Node.js and browsers.", + summary: "JavaScript/TypeScript is xlang-only, schema-driven, and runs in Node.js or browsers.", code: `import Fory, { Type } from "@apache-fory/core"; const personType = Type.struct( - { typeName: "example.Person" }, + { typeName: "Person" }, { name: Type.string(), age: Type.int32() }, ); @@ -301,7 +282,7 @@ const out = deserialize(payload);`, install: `dotnet add package Apache.Fory --version 1.0.0`, codeLanguage: "csharp", guide: "/docs/guide/csharp/", - summary: ".NET runtime with source-generated serializers and xlang compatibility.", + summary: ".NET support uses source-generated serializers for Fory structs, enums, and unions.", code: `using Apache.Fory; [ForyStruct] @@ -312,7 +293,7 @@ public sealed class Person } Fory fory = Fory.Builder().Build(); -fory.Register<Person>(1); +fory.Register<Person>("Person"); byte[] payload = fory.Serialize(new Person { Name = "Alice", Age = 30 }); Person out = fory.Deserialize<Person>(payload);`, @@ -324,7 +305,7 @@ Person out = fory.Deserialize<Person>(payload);`, install: `.package(url: "https://github.com/apache/fory.git", exact: "1.0.0")`, codeLanguage: "swift", guide: "/docs/guide/swift/", - summary: "Swift value types with macro-based registration and strong type safety.", + summary: "Swift uses @ForyStruct, @ForyEnum, and @ForyUnion macros for xlang-compatible models.", code: `import Fory @ForyStruct @@ -334,7 +315,7 @@ struct Person: Equatable { } let fory = Fory() -fory.register(Person.self, id: 1) +try fory.register(Person.self, name: "Person") let payload = try fory.serialize(Person(name: "Alice", age: 30)) let out: Person = try fory.deserialize(payload)`, @@ -350,8 +331,12 @@ dev_dependencies: build_runner: ^2.4.13`, codeLanguage: "dart", guide: "/docs/guide/dart/", - summary: "Generated Dart serializers for VM, Flutter, and web xlang payloads.", - code: `@ForyStruct() + summary: "Dart uses generated serializers across Dart VM, Flutter, AOT, and web targets.", + code: `import 'package:fory/fory.dart'; + +part 'person.fory.dart'; + +@ForyStruct() class Person { Person(); String name = ""; @@ -361,7 +346,12 @@ class Person { } final fory = Fory(); -PersonForyModule.register(fory, Person, namespace: "example", typeName: "Person"); +PersonForyModule.register( + fory, + Person, + namespace: '', + typeName: 'Person', +); final payload = fory.serialize(Person()..name = "Alice"..age = 30); final out = fory.deserialize<Person>(payload);`, @@ -373,7 +363,7 @@ final out = fory.deserialize<Person>(payload);`, install: `libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.0.0"`, codeLanguage: "scala", guide: "/docs/guide/scala/", - summary: "Scala case classes and collections on top of optimized JVM serialization.", + summary: "Scala builds on Fory Java with optimized serializers for case classes, collections, tuples, and Option.", code: `import org.apache.fory.scala.ForyScala case class Person(name: String, age: Int) @@ -381,7 +371,7 @@ case class Person(name: String, age: Int) val fory = ForyScala.builder() .withXlang(true) .build() -fory.register(classOf[Person]) +fory.register(classOf[Person], "Person") val payload = fory.serialize(Person("Alice", 30)) val out = fory.deserialize(payload).asInstanceOf[Person]`, @@ -393,7 +383,7 @@ val out = fory.deserialize(payload).asInstanceOf[Person]`, install: `implementation("org.apache.fory:fory-kotlin:1.0.0")`, codeLanguage: "kotlin", guide: "/docs/guide/kotlin/", - summary: "Kotlin data classes, Android support, and JVM xlang/native modes.", + summary: "Kotlin adds data-class support, Android guidance, and KSP static serializers for xlang/schema mode.", code: `import org.apache.fory.kotlin.ForyKotlin data class Person(val name: String, val age: Int) @@ -402,162 +392,238 @@ val fory = ForyKotlin.builder() .withXlang(true) .requireClassRegistration(true) .buildThreadSafeFory() -fory.register(Person::class.java) +fory.register(Person::class.java, "Person") val payload = fory.serialize(Person("Alice", 30)) val out = fory.deserialize(payload) as Person`, }, - { - id: "xlang", - label: "Schema IDL", - installLanguage: "fory", - install: `foryc example.fdl --lang rust --output ./generated`, - codeLanguage: "protobuf", - guide: "/docs/guide/xlang/", - summary: "Define a stable schema once and generate a native Rust model.", - code: `package example; - -message Person { - string name = 1; - int32 age = 2; - optional string email = 3; -} - -// This follows the Fory IDL Quick Start schema.`, - }, ]; const capabilities = [ { - title: "Cross-language wire format", - zhTitle: "跨语言线格式", + title: "Cross-language encoding", + zhTitle: "跨语言编码", label: "XLANG", description: - "Use one compact binary payload across supported runtimes when services cross language boundaries.", - zhDescription: "跨服务语言边界时,用同一套紧凑二进制载荷连接不同运行时。", + "Serialize in one supported runtime and deserialize in another with the xlang wire format.", + zhDescription: "通过 xlang 线格式,在一个受支持运行时序列化,在另一个运行时反序列化。", link: "/docs/guide/xlang/", }, { - title: "Object graph semantics", - zhTitle: "对象图语义", - label: "GRAPH", + title: "Domain objects first", + zhTitle: "领域对象优先", + label: "OBJECTS", description: - "Preserve shared references, circular references, and polymorphic runtime types instead of flattening them away.", - zhDescription: "保留共享引用、循环引用和多态运行时类型,而不是把对象图语义压平。", - link: "/docs/introduction/overview/", + "Work with Java classes, Python dataclasses, Go structs, Rust/C++ structs, and generated or annotated models.", + zhDescription: "直接使用 Java 类、Python dataclass、Go struct、Rust/C++ struct,以及生成或注解模型。", + link: "/docs/start/usage", }, { - title: "Schema IDL and compiler", - zhTitle: "Schema IDL 与编译器", + title: "Reference-aware Schema IDL", + zhTitle: "支持引用语义的 Schema IDL", label: "IDL", description: - "Define stable contracts once and generate idiomatic domain objects for each target language.", - zhDescription: "一次定义稳定契约,为不同语言生成符合习惯的领域对象。", + "Define schemas once with optional fields, refs, IDs, unions, and services, then generate native code.", + zhDescription: "一次定义 optional、ref、ID、union 和 service 等 schema,再生成各语言原生代码。", link: "/docs/compiler/", }, { - title: "Row format and zero-copy", - zhTitle: "Row format 与零拷贝", + title: "Row-format random access", + zhTitle: "Row format 随机访问", label: "ROW", description: - "Read fields, arrays, and nested values without rebuilding whole objects for analytics and partial-read paths.", - zhDescription: "无需重建完整对象即可读取字段、数组和嵌套值,适合分析和部分读取路径。", - link: "/docs/specification/row_format_spec", + "Read fields, arrays, and nested values without deserializing the whole object; integrate with Arrow where supported.", + zhDescription: "无需反序列化完整对象即可读取字段、数组和嵌套值,并在支持语言中对接 Arrow。", + link: "/docs/guide/xlang/row_format", }, { title: "Optimized runtimes", zhTitle: "运行时优化", - label: "JIT", + label: "FAST", description: - "Combine Java JIT serializers with generated or static serializers in other runtimes.", - zhDescription: "结合 Java JIT 序列化器,以及其他运行时的生成式或静态序列化器。", + "Use Java JIT serializers, generated JavaScript schemas, C# source generators, Kotlin KSP, and Dart build_runner output.", + zhDescription: "使用 Java JIT、JavaScript schema 生成缓存、C# source generator、Kotlin KSP 和 Dart build_runner 输出。", link: "/docs/guide/java/", }, { - title: "Multi-runtime ecosystem", + title: "Broad platform support", zhTitle: "多运行时生态", - label: "12X", + label: "11X", description: - "Work from Java, Python, Rust, Go, C++, JavaScript, C#, Swift, Dart, Scala, Kotlin, and cross-language guides.", - zhDescription: "覆盖 Java、Python、Rust、Go、C++、JavaScript、C#、Swift、Dart、Scala、Kotlin 和跨语言指南。", + "Use Fory from Java, Python, C++, Go, Rust, JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin.", + zhDescription: "覆盖 Java、Python、C++、Go、Rust、JavaScript/TypeScript、C#、Swift、Dart、Scala 和 Kotlin。", link: "/docs/start/usage", }, ]; +const heroSurfaces = [ + { + label: "Native", + zhLabel: "Native", + title: "Native Objects", + zhTitle: "原生对象", + text: "Serialize existing domain objects inside one runtime.", + zhText: "在单一运行时内序列化已有领域对象。", + link: "/docs/start/usage", + }, + { + label: "xlang", + zhLabel: "xlang", + title: "Cross-language Payloads", + zhTitle: "跨语言 Payload", + text: "Exchange typed payloads across supported languages.", + zhText: "在受支持语言之间交换类型化 payload。", + link: "/docs/guide/xlang/", + }, + { + label: "IDL", + zhLabel: "IDL", + title: "Schema IDL", + zhTitle: "Schema IDL", + text: "Define shared contracts and generate native code.", + zhText: "定义共享契约,并生成各语言原生代码。", + link: "/docs/compiler/", + }, + { + label: "Row", + zhLabel: "Row", + title: "Row Format", + zhTitle: "Row Format", + text: "Read selected fields for partial-read and analytics workloads.", + zhText: "面向部分读取和分析工作负载读取指定字段。", + link: "/docs/guide/xlang/row_format", + }, +]; + +const schemaExamples = [ + { + title: "Simple object", + zhTitle: "简单对象", + text: "Define ordinary typed fields with explicit field IDs and optional values.", + zhText: "用明确字段 ID 和 optional 值定义普通类型化对象。", + code: `message Person { + string name = 1; + int32 age = 2; + optional string email = 3; +}`, + }, + { + title: "Typed union", + zhTitle: "类型化 union", + text: "Represent one-of-many domain cases without flattening every payload into a generic map.", + zhText: "表达 one-of-many 领域分支,而不是把所有载荷压平成通用 map。", + code: `message Dog [id=104] { + string name = 1; + int32 bark_volume = 2; +} + +message Cat [id=105] { + string name = 1; + int32 lives = 2; +} + +union Animal [id=106] { + Dog dog = 1; + Cat cat = 2; +}`, + }, + { + title: "Circular references", + zhTitle: "循环引用", + text: "Use ref-tracked fields when the same object can be shared or a graph contains cycles.", + zhText: "当对象会被共享,或图结构中存在环时,用 ref 字段保留引用语义。", + code: `message Node { + string value = 1; + ref Node parent = 2; + list<ref Node> children = 3; +}`, + }, +]; + +const schemaPreviewCode = `package example;\n\n${schemaExamples + .map((item) => item.code) + .join("\n\n")}`; + const performanceCards = [ { - value: "9", - label: "benchmark reports", - zhLabel: "份性能报告", - text: "Java, Python, Rust, C++, Go, C#, Swift, JavaScript, and Dart have dedicated benchmark pages.", - zhText: "Java、Python、Rust、C++、Go、C#、Swift、JavaScript 和 Dart 均有独立性能报告。", + value: "Per language", + zhValue: "按语言", + label: "runtime benchmarks", + zhLabel: "运行时性能", + text: "Compare Fory with the serializers a team would realistically choose for that language.", + zhText: "把 Fory 与该语言中团队实际会选择的序列化方案进行对比。", }, { - value: "2", - label: "wire modes", - zhLabel: "种线格式模式", - text: "Use xlang for portable payloads and native mode for same-runtime object surfaces.", - zhText: "xlang 用于可移植载荷,native mode 用于同一运行时的原生对象面。", + value: "Same workloads", + zhValue: "同工作负载", + label: "reproducible setup", + zhLabel: "可复现设置", + text: "Use the benchmark notes to understand payload shape, environment, and methodology.", + zhText: "通过 Benchmark 说明理解载荷形态、环境和测试方法。", }, { - value: "1", - label: "object model", - zhLabel: "套对象模型", - text: "Keep domain objects central while choosing schema, row format, or runtime-specific paths as needed.", - zhText: "以领域对象为中心,并按需选择 Schema、Row format 或运行时定制路径。", + value: "By boundary", + zhValue: "按边界", + label: "mode selection", + zhLabel: "模式选择", + text: "Measure the path you intend to ship: xlang payloads, native mode, or row format.", + zhText: "测量你真正要上线的路径:xlang payload、native mode 或 row format。", }, ]; const useCases = [ { - title: "Cross-language service payloads", - zhTitle: "跨语言服务载荷", - text: "Share objects between JVM, Python, Rust, Go, JavaScript, .NET, Swift, and Dart services.", - zhText: "在 JVM、Python、Rust、Go、JavaScript、.NET、Swift、Dart 服务之间共享对象。", + title: "Language boundary", + zhTitle: "语言边界", + text: "Use xlang when services in different languages need to exchange the same typed payload directly.", + zhText: "当不同语言服务需要直接交换同一份类型化载荷时,使用 xlang。", }, { - title: "Cache and state snapshots", - zhTitle: "缓存与状态快照", - text: "Serialize rich object graphs without losing reference structure.", - zhText: "序列化复杂对象图,同时保留引用结构。", + title: "Runtime boundary", + zhTitle: "运行时边界", + text: "Use native mode when objects stay inside one runtime and object graph fidelity matters.", + zhText: "当对象只在同一运行时内流转,且对象图语义重要时,使用 native mode。", }, { - title: "Data pipelines and partial reads", - zhTitle: "数据管道与部分读取", - text: "Use row format when pipelines need zero-copy access to selected fields.", - zhText: "当管道只需要读取部分字段时,使用 Row format 获得零拷贝访问。", + title: "Read boundary", + zhTitle: "读取边界", + text: "Use row format for partial reads and analytics workloads that should not rebuild whole objects.", + zhText: "当部分读取和分析类工作负载不应重建完整对象时,使用 row format。", }, ]; const adoptionPaths = [ { label: "01", - title: "Start with one runtime", - zhTitle: "从单一运行时开始", - text: "Install the package for your language and serialize native domain objects first.", - zhText: "安装当前语言的运行时包,先序列化原生领域对象。", - cta: "Install guide", - zhCta: "安装指南", - link: "/docs/start/install", + title: "Serialize native objects", + zhTitle: "序列化原生对象", + text: "Start with the object model your service already owns, then register stable names when payloads cross runtimes.", + zhText: "从服务已有的对象模型开始;当 payload 跨运行时边界时,再注册稳定类型名。", + cta: "Usage guide", + zhCta: "使用指南", + doc: "/docs/start/usage", + link: "/docs/start/usage", }, { label: "02", - title: "Standardize with Schema IDL", - zhTitle: "用 Schema IDL 标准化", - text: "Define shared contracts when teams need stable models across services and languages.", - zhText: "当团队需要跨服务、跨语言稳定模型时,用 Schema IDL 定义共享契约。", - cta: "Compiler docs", - zhCta: "编译器文档", + title: "Define shared schemas", + zhTitle: "定义共享 Schema", + text: "Use Fory IDL when models become long-lived, span teams, or need generated code across languages.", + zhText: "当模型生命周期变长、跨团队协作,或需要多语言代码生成时,使用 Fory IDL。", + cta: "Schema IDL guide", + zhCta: "Schema IDL", + doc: "/docs/compiler", link: "/docs/compiler/", }, { label: "03", title: "Validate performance", - zhTitle: "验证性能表现", - text: "Use the benchmark notes and charts to compare runtime behavior before rollout.", - zhText: "上线前通过 Benchmark 说明和图表比较不同运行时表现。", - cta: "Benchmarks", - zhCta: "性能测试", + zhTitle: "验证性能", + text: "Compare the language and payload path you plan to ship before committing to a production rollout.", + zhText: "上线前对比你实际计划使用的语言和 payload 路径。", + cta: "Benchmark charts", + zhCta: "Benchmark", + doc: "/docs/introduction/benchmark", link: "/docs/introduction/benchmark", }, ]; @@ -597,60 +663,37 @@ function HomepageLanding(): JSX.Element { {copy.heroGithub} </Link> </div> - <dl className={styles.trustList}> - <div> - <dt>{copy.heroVersion}</dt> - <dd>2026-05-21</dd> - </div> - <div> - <dt>{copy.heroRuntimes}</dt> - <dd>Java to Dart</dd> - </div> - <div> - <dt>{copy.heroBenchmarks}</dt> - <dd>9 reports</dd> - </div> - <div> - <dt>{copy.heroApache}</dt> - <dd>ASF</dd> - </div> - </dl> </div> - <div className={styles.heroVisual} aria-label={copy.heroPanelTitle}> - <div className={styles.panelHeader}> - <div> - <strong>{copy.heroPanelTitle}</strong> - <span>{copy.heroPanelSubtitle}</span> - </div> - <span className={styles.panelBadge}>xlang=true</span> - </div> - <div className={styles.flowGrid}> - <div className={styles.flowNode}> - <span>01</span> - <strong>{copy.heroFlowSource}</strong> - <code>Person("Alice", 30)</code> - </div> - <div className={styles.flowLine} /> - <div className={styles.flowNode}> - <span>02</span> - <strong>{copy.heroFlowWire}</strong> - <code>compact bytes</code> - </div> - <div className={styles.flowLine} /> - <div className={styles.flowNode}> - <span>03</span> - <strong>{copy.heroFlowTarget}</strong> - <code>Person(name="Alice")</code> - </div> + <div className={styles.surfacePanel} aria-label={isZh ? "Fory 文档入口" : "Fory documentation paths"}> + <div className={styles.surfaceOptions}> + {heroSurfaces.map((item) => ( + <Link className={styles.surfaceOption} key={item.title} to={item.link}> + <span className={styles.surfaceOptionBadge}>{isZh ? item.zhLabel : item.label}</span> + <span className={styles.surfaceOptionBody}> + <strong>{isZh ? item.zhTitle : item.title}</strong> + <small>{isZh ? item.zhText : item.text}</small> + </span> + </Link> + ))} </div> - <div className={styles.heroCode}> - <CodeBlock language="java">{`Fory fory = Fory.builder().withXlang(true).build(); -fory.register(Person.class, "example", "Person"); + </div> + </section> -byte[] bytes = fory.serialize(new Person("Alice", 30)); -Person out = (Person) fory.deserialize(bytes);`}</CodeBlock> - </div> + <section className={styles.capabilities}> + <div className={styles.sectionHeader}> + <span>{copy.capabilitiesEyebrow}</span> + <h2>{copy.capabilitiesTitle}</h2> + <p>{copy.capabilitiesSubtitle}</p> + </div> + <div className={styles.capabilityGrid}> + {capabilities.map((item) => ( + <Link className={styles.capabilityCard} key={item.title} to={item.link}> + <span>{item.label}</span> + <h3>{isZh ? item.zhTitle : item.title}</h3> + <p>{isZh ? item.zhDescription : item.description}</p> + </Link> + ))} </div> </section> @@ -698,20 +741,34 @@ Person out = (Person) fory.deserialize(bytes);`}</CodeBlock> </div> </section> - <section className={styles.capabilities}> - <div className={styles.sectionHeader}> - <span>{copy.capabilitiesEyebrow}</span> - <h2>{copy.capabilitiesTitle}</h2> - <p>{copy.capabilitiesSubtitle}</p> - </div> - <div className={styles.capabilityGrid}> - {capabilities.map((item) => ( - <Link className={styles.capabilityCard} key={item.title} to={item.link}> - <span>{item.label}</span> - <h3>{isZh ? item.zhTitle : item.title}</h3> - <p>{isZh ? item.zhDescription : item.description}</p> + <section className={styles.schemaIdl}> + <div className={styles.schemaLayout}> + <div className={styles.schemaCopy}> + <span className={styles.eyebrow}>{copy.schemaEyebrow}</span> + <h2>{copy.schemaTitle}</h2> + <p>{copy.schemaSubtitle}</p> + <div className={styles.schemaFeatureList}> + {schemaExamples.map((item, index) => ( + <article className={styles.schemaFeature} key={item.title}> + <span>{String(index + 1).padStart(2, "0")}</span> + <div> + <h3>{isZh ? item.zhTitle : item.title}</h3> + <p>{isZh ? item.zhText : item.text}</p> + </div> + </article> + ))} + </div> + <Link className={styles.secondaryButton} to="/docs/compiler/"> + {copy.guideLabel} </Link> - ))} + </div> + <div className={styles.schemaPreview} aria-label={copy.schemaTitle}> + <div className={styles.schemaPreviewHeader}> + <span>model.fdl</span> + <strong>Fory IDL</strong> + </div> + <CodeBlock language="protobuf">{schemaPreviewCode}</CodeBlock> + </div> </div> </section> @@ -727,7 +784,7 @@ Person out = (Person) fory.deserialize(bytes);`}</CodeBlock> <div className={styles.performanceCards}> {performanceCards.map((item) => ( <div className={styles.performanceCard} key={item.label}> - <strong>{item.value}</strong> + <strong>{isZh ? item.zhValue : item.value}</strong> <span>{isZh ? item.zhLabel : item.label}</span> <p>{isZh ? item.zhText : item.text}</p> </div> @@ -753,17 +810,19 @@ Person out = (Person) fory.deserialize(bytes);`}</CodeBlock> <section className={styles.ecosystem}> <div className={styles.ecosystemHeader}> - <span className={styles.eyebrow}>{isZh ? "采用路径" : "Adoption paths"}</span> + <span className={styles.eyebrow}>{isZh ? "采用路径" : "Adoption path"}</span> <h2>{copy.ecosystemTitle}</h2> <p>{copy.ecosystemSubtitle}</p> </div> <div className={styles.adoptionGrid}> {adoptionPaths.map((item) => ( <Link className={styles.adoptionCard} key={item.title} to={item.link}> - <span>{item.label}</span> - <h3>{isZh ? item.zhTitle : item.title}</h3> - <p>{isZh ? item.zhText : item.text}</p> - <strong>{isZh ? item.zhCta : item.cta}</strong> + <span className={styles.adoptionStep}>{item.label}</span> + <span className={styles.adoptionDocText}> + <strong>{isZh ? item.zhCta : item.cta}</strong> + <small>{isZh ? item.zhTitle : item.title}</small> + <code>{item.doc}</code> + </span> </Link> ))} </div> diff --git a/src/css/custom.css b/src/css/custom.css index 1bd8049e7c..1790e63f23 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -6,6 +6,7 @@ /* You can override the default Infima variables here. */ :root { + --ifm-navbar-height: 4rem; --ifm-color-primary: #ff6f01d2; --ifm-color-primary-dark: #FF7001; --ifm-color-primary-darker: #FF7001; @@ -41,8 +42,8 @@ max-width: 1180px; } - .navbar__brand { - margin-right: 1.25rem; +.navbar__brand { + margin-right: 1.5rem; } } @@ -52,8 +53,14 @@ box-shadow: 0 1px 0 rgba(15, 23, 42, .06); } +.navbar__brand { + flex-shrink: 0; + min-width: max-content; +} + .navbar__logo { - height: 1.75rem; + flex-shrink: 0; + height: 2rem; } .navbar__item { @@ -65,12 +72,19 @@ .navbar__link { color: var(--ifm-navbar-link-color); font-size: .9375rem; - padding-left: .5rem; - padding-right: .5rem; + padding-left: .55rem; + padding-right: .55rem; +} + +.navbar__items--right .dropdown > .navbar__link { + color: var(--ifm-navbar-link-color); + font-size: .9375rem; + font-weight: 600; } .navbar__link:hover, -.navbar__link--active { +.navbar__link--active, +.navbar__items--right .dropdown > .navbar__link:hover { color: var(--ifm-navbar-link-hover-color); } @@ -79,7 +93,7 @@ border: 1px solid #edf0f5; color: #475569; font-size: .9375rem; - height: 2rem; + height: 2.125rem; } .navbar__search-input::placeholder { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
