mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-07 08:26:06 +00:00
feat(docs): redesign homepage and add traffic dashboard (#522)
Some checks failed
CI / Python tests / Unit Tests - py3.13 (push) Has been cancelled
CI / ReMe Studio / Studio checks (push) Has been cancelled
CI / TypeScript integrations / Type-check, test, and pack (push) Has been cancelled
CI / Windows / CLI smoke - py3.11 (push) Has been cancelled
Security / CodeQL / Analyze javascript-typescript (push) Has been cancelled
CI / Python tests / Unit Tests - py3.11 (push) Has been cancelled
CI / Documentation / Test and build documentation (push) Has been cancelled
CI / Python packages / Build and verify distributions (push) Has been cancelled
CI / Python quality / Pre-commit (push) Has been cancelled
CI / Python tests / Unit Tests - py3.12 (push) Has been cancelled
Deploy / Documentation / Build documentation (push) Has been cancelled
Security / CodeQL / Analyze python (push) Has been cancelled
Deploy / Documentation / deploy (push) Has been cancelled
Some checks failed
CI / Python tests / Unit Tests - py3.13 (push) Has been cancelled
CI / ReMe Studio / Studio checks (push) Has been cancelled
CI / TypeScript integrations / Type-check, test, and pack (push) Has been cancelled
CI / Windows / CLI smoke - py3.11 (push) Has been cancelled
Security / CodeQL / Analyze javascript-typescript (push) Has been cancelled
CI / Python tests / Unit Tests - py3.11 (push) Has been cancelled
CI / Documentation / Test and build documentation (push) Has been cancelled
CI / Python packages / Build and verify distributions (push) Has been cancelled
CI / Python quality / Pre-commit (push) Has been cancelled
CI / Python tests / Unit Tests - py3.12 (push) Has been cancelled
Deploy / Documentation / Build documentation (push) Has been cancelled
Security / CodeQL / Analyze python (push) Has been cancelled
Deploy / Documentation / deploy (push) Has been cancelled
* feat(docs): redesign homepage and add traffic dashboard * feat(docs): publish readmes as project overview
This commit is contained in:
parent
193fd418fb
commit
0eba6ea831
12 changed files with 665 additions and 111 deletions
|
|
@ -104,23 +104,24 @@ const legacyRedirectScript = `(() => {
|
|||
function nav(language: "zh" | "en"): DefaultTheme.NavItem[] {
|
||||
const zh = language === "zh";
|
||||
return [
|
||||
{ text: zh ? "开始使用" : "Get Started", link: `/${language}/quick_start` },
|
||||
{ text: zh ? "核心概念" : "Concepts", link: `/${language}/memory_as_file` },
|
||||
{ text: zh ? "指南" : "Guides", link: `/${language}/auto_memory` },
|
||||
{ text: zh ? "首页" : "Home", link: `/${language}/` },
|
||||
{ text: zh ? "文档" : "Docs", link: `/${language}/quick_start` },
|
||||
{ text: zh ? "集成" : "Integrations", link: `/${language}/integrations` },
|
||||
{ text: zh ? "API 参考" : "API Reference", link: `/${language}/reference/cli` },
|
||||
{ text: zh ? "插件" : "Plugins", link: `/${language}/plugin_management` },
|
||||
{ text: zh ? "评测" : "Benchmarks", link: `/${language}/benchmarks/longmemeval` },
|
||||
{ text: zh ? "博客" : "Blog", link: `/${language}/reme-blog` },
|
||||
{ text: zh ? "常见问题" : "FAQ", link: `/${language}/faq` },
|
||||
];
|
||||
}
|
||||
|
||||
function sidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
||||
function docsSidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
||||
const zh = language === "zh";
|
||||
return [
|
||||
{
|
||||
text: zh ? "开始使用" : "Get Started",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: zh ? "项目介绍" : "Introduction", link: `/${language}/` },
|
||||
{ text: zh ? "项目介绍" : "Introduction", link: `/${language}/overview` },
|
||||
{ text: zh ? "快速开始" : "Quick Start", link: `/${language}/quick_start` },
|
||||
{ text: zh ? "基础配置" : "Configuration", link: `/${language}/configuration` },
|
||||
{ text: zh ? "服务与部署" : "Services and Deployment", link: `/${language}/services` },
|
||||
|
|
@ -147,45 +148,13 @@ function sidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
|||
],
|
||||
},
|
||||
{
|
||||
text: zh ? "Agent 集成" : "Agent Integrations",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: zh ? "集成总览" : "Overview", link: `/${language}/integrations` },
|
||||
{ text: "Claude Code", link: `/${language}/integrations/claude-code` },
|
||||
{ text: "Hermes Agent", link: `/${language}/integrations/hermes` },
|
||||
{ text: zh ? "TypeScript 客户端" : "TypeScript Client", link: `/${language}/integrations/typescript` },
|
||||
{ text: "DeepSeek Harness", link: `/${language}/integrations/dsh` },
|
||||
{ text: "OpenClaw", link: `/${language}/integrations/openclaw` },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: zh ? "工作区与插件" : "Workspace and Plugins",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "ReMe Studio", link: `/${language}/workspace/studio` },
|
||||
{ text: zh ? "插件管理" : "Plugin Management", link: `/${language}/plugin_management` },
|
||||
{ text: zh ? "插件开发" : "Plugin Development", link: `/${language}/plugin_development` },
|
||||
{ text: zh ? "每日论文" : "Daily Paper", link: `/${language}/plugins/daily-paper` },
|
||||
{ text: "Auto Fin", link: `/${language}/plugins/auto-fin` },
|
||||
{ text: "LME", link: `/${language}/plugins/lme` },
|
||||
{ text: "BEAM", link: `/${language}/plugins/beam` },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: zh ? "API 参考" : "API Reference",
|
||||
text: zh ? "API 与运维" : "API and Operations",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "CLI", link: `/${language}/reference/cli` },
|
||||
{ text: zh ? "Job API" : "Job API", link: `/${language}/reference/jobs` },
|
||||
{ text: "HTTP / MCP", link: `/${language}/services#http-api` },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: zh ? "运维" : "Operations",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: zh ? "诊断、备份与恢复" : "Diagnostics, Backup, and Recovery", link: `/${language}/operations` },
|
||||
{ text: zh ? "常见问题" : "FAQ", link: `/${language}/faq` },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -196,19 +165,88 @@ function sidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
|||
{ text: zh ? "开源与贡献" : "Contributing", link: `/${language}/contributing` },
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function integrationsSidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
||||
const zh = language === "zh";
|
||||
return [{
|
||||
text: zh ? "Agent 集成" : "Agent Integrations",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: zh ? "集成总览" : "Overview", link: `/${language}/integrations` },
|
||||
{ text: "Claude Code", link: `/${language}/integrations/claude-code` },
|
||||
{ text: "Hermes Agent", link: `/${language}/integrations/hermes` },
|
||||
{ text: zh ? "TypeScript 客户端" : "TypeScript Client", link: `/${language}/integrations/typescript` },
|
||||
{ text: "DeepSeek Harness", link: `/${language}/integrations/dsh` },
|
||||
{ text: "OpenClaw", link: `/${language}/integrations/openclaw` },
|
||||
],
|
||||
}];
|
||||
}
|
||||
|
||||
function pluginsSidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
||||
const zh = language === "zh";
|
||||
return [
|
||||
{
|
||||
text: zh ? "评测" : "Benchmarks",
|
||||
collapsed: true,
|
||||
text: zh ? "工作区" : "Workspace",
|
||||
collapsed: false,
|
||||
items: [{ text: "ReMe Studio", link: `/${language}/workspace/studio` }],
|
||||
},
|
||||
{
|
||||
text: zh ? "插件" : "Plugins",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: "BEAM", link: `/${language}/benchmarks/beam` },
|
||||
{ text: "LongMemEval", link: `/${language}/benchmarks/longmemeval` },
|
||||
{ text: "π-Bench", link: `/${language}/benchmarks/pibench` },
|
||||
{ text: "Tool Memory / ExpG", link: `/${language}/benchmarks/toolmemory` },
|
||||
{ text: zh ? "插件管理" : "Plugin Management", link: `/${language}/plugin_management` },
|
||||
{ text: zh ? "插件开发" : "Plugin Development", link: `/${language}/plugin_development` },
|
||||
{ text: zh ? "每日论文" : "Daily Paper", link: `/${language}/plugins/daily-paper` },
|
||||
{ text: "Auto Fin", link: `/${language}/plugins/auto-fin` },
|
||||
{ text: "LME", link: `/${language}/plugins/lme` },
|
||||
{ text: "BEAM", link: `/${language}/plugins/beam` },
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function benchmarksSidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
|
||||
const zh = language === "zh";
|
||||
return [{
|
||||
text: zh ? "记忆能力评测" : "Memory Benchmarks",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: "LongMemEval", link: `/${language}/benchmarks/longmemeval` },
|
||||
{ text: "BEAM", link: `/${language}/benchmarks/beam` },
|
||||
{ text: "π-Bench", link: `/${language}/benchmarks/pibench` },
|
||||
{ text: "Tool Memory / ExpG", link: `/${language}/benchmarks/toolmemory` },
|
||||
],
|
||||
}];
|
||||
}
|
||||
|
||||
function singlePageSidebar(language: "zh" | "en", page: "blog" | "faq"): DefaultTheme.SidebarItem[] {
|
||||
const zh = language === "zh";
|
||||
return [{
|
||||
text: page === "blog" ? (zh ? "ReMe 博客" : "ReMe Blog") : (zh ? "帮助" : "Help"),
|
||||
collapsed: false,
|
||||
items: [{
|
||||
text: page === "blog" ? (zh ? "产品故事" : "Product Story") : (zh ? "常见问题" : "Frequently Asked Questions"),
|
||||
link: `/${language}/${page === "blog" ? "reme-blog" : "faq"}`,
|
||||
}],
|
||||
}];
|
||||
}
|
||||
|
||||
function sidebars(language: "zh" | "en"): DefaultTheme.SidebarMulti {
|
||||
return {
|
||||
[`/${language}/integrations`]: integrationsSidebar(language),
|
||||
[`/${language}/workspace/`]: pluginsSidebar(language),
|
||||
[`/${language}/plugins/`]: pluginsSidebar(language),
|
||||
[`/${language}/plugin_management`]: pluginsSidebar(language),
|
||||
[`/${language}/plugin_development`]: pluginsSidebar(language),
|
||||
[`/${language}/benchmarks/`]: benchmarksSidebar(language),
|
||||
[`/${language}/reme-blog`]: singlePageSidebar(language, "blog"),
|
||||
[`/${language}/faq`]: singlePageSidebar(language, "faq"),
|
||||
[`/${language}/`]: docsSidebar(language),
|
||||
};
|
||||
}
|
||||
|
||||
function configureRepositoryLinks(md: any) {
|
||||
for (const ruleName of ["link_open", "image"] as const) {
|
||||
const original = md.renderer.rules[ruleName];
|
||||
|
|
@ -258,6 +296,12 @@ export default defineConfig({
|
|||
head: [
|
||||
["link", { rel: "icon", type: "image/svg+xml", href: `${base}reme-icon.svg` }],
|
||||
["meta", { name: "theme-color", content: "#087f6a" }],
|
||||
["script", {
|
||||
defer: "",
|
||||
src: "https://cloud.umami.is/script.js",
|
||||
"data-website-id": "8cafe9df-d883-4046-b5e9-36dfd21a4884",
|
||||
"data-domains": "reme.agentscope.io",
|
||||
}],
|
||||
["script", {}, legacyRedirectScript],
|
||||
],
|
||||
markdown: {
|
||||
|
|
@ -320,7 +364,7 @@ export default defineConfig({
|
|||
link: "/zh/",
|
||||
themeConfig: {
|
||||
nav: nav("zh"),
|
||||
sidebar: { "/zh/": sidebar("zh") },
|
||||
sidebar: sidebars("zh"),
|
||||
outline: { label: "页面导航", level: [2, 3] },
|
||||
docFooter: { prev: "上一页", next: "下一页" },
|
||||
darkModeSwitchLabel: "外观",
|
||||
|
|
@ -335,7 +379,7 @@ export default defineConfig({
|
|||
link: "/en/",
|
||||
themeConfig: {
|
||||
nav: nav("en"),
|
||||
sidebar: { "/en/": sidebar("en") },
|
||||
sidebar: sidebars("en"),
|
||||
outline: { label: "On this page", level: [2, 3] },
|
||||
docFooter: { prev: "Previous page", next: "Next page" },
|
||||
},
|
||||
|
|
|
|||
407
docs/.vitepress/theme/HomePage.vue
Normal file
407
docs/.vitepress/theme/HomePage.vue
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive } from "vue";
|
||||
import { withBase } from "vitepress";
|
||||
|
||||
const props = defineProps<{ lang: "zh" | "en" }>();
|
||||
|
||||
const repository = "https://github.com/agentscope-ai/ReMe";
|
||||
const trafficShareUrl = "https://cloud.umami.is/analytics/us/share/S1OZK1PSDLEpyiU5?date=30day&page=1";
|
||||
const stats = reactive({ stars: "3.4K+", forks: "293" });
|
||||
|
||||
const translations = {
|
||||
zh: {
|
||||
eyebrow: "LOCAL-FIRST · FILE-NATIVE",
|
||||
title: "让 Agent 真正记住,\n让记忆始终属于你。",
|
||||
lead: "ReMe 将对话、资料与经验沉淀为可读、可编辑、可检索、相互链接的本地文件,让不同 Agent 共享同一套长期记忆。",
|
||||
quickStart: "快速开始",
|
||||
learnMore: "了解 ReMe",
|
||||
stars: "GitHub Stars",
|
||||
forks: "Forks",
|
||||
mapLabel: "SHARED MEMORY WORKSPACE",
|
||||
mapTitle: "一层记忆,连接所有 Agent",
|
||||
capabilities: [
|
||||
{ icon: "▱", title: "文件即记忆", detail: "用户拥有的文件是持久事实源", href: "/zh/memory_as_file", tone: "mint" },
|
||||
{ icon: "✦", title: "自动记忆", detail: "从 daily 到长期 digest 持续演化", href: "/zh/auto_memory", tone: "cyan" },
|
||||
{ icon: "⌕", title: "检索与图谱", detail: "关键词、向量与 wikilink 联合召回", href: "/zh/memory_search", tone: "blue" },
|
||||
{ icon: "⌁", title: "Agent 集成", detail: "通过 CLI、HTTP、MCP 与宿主适配器接入", href: "/zh/integrations", tone: "amber" },
|
||||
],
|
||||
benchmarkLabel: "02 / BENCHMARKS",
|
||||
benchmarkTitle: "用真实评测,\n验证长期记忆",
|
||||
benchmarkLead: "从跨会话检索到百万级上下文,ReMe 用可复现的公开基准验证长期记忆。",
|
||||
benchmarkAction: "查看全部评测",
|
||||
benchmarkNote: "仓库已发布参考结果 · Agentic score",
|
||||
benchmarks: [
|
||||
{ name: "LongMemEval", setting: "500 题 · cleaned-s", score: 89.4 },
|
||||
{ name: "BEAM 100K", setting: "20 cases · 400 题", score: 66.1 },
|
||||
{ name: "BEAM 1M", setting: "35 cases · 700 题", score: 65.0 },
|
||||
],
|
||||
piLabel: "π-Bench 主动性",
|
||||
piDetail: "5 类用户画像的平均 PROC 得分",
|
||||
piDelta: "较 NanoBot +2.4%",
|
||||
sectionLabel: "03 / PRODUCTS & PLUGINS",
|
||||
sectionTitle: "从记忆工作区,到自动研究",
|
||||
sectionLead: "三个完整入口,把 ReMe 用到真实工作流中。",
|
||||
products: [
|
||||
{ mark: "▣", label: "WORKSPACE", title: "ReMe Studio", detail: "在本地 Web 工作区中浏览、编辑、搜索记忆,并探索 wikilink 图谱。", href: "/zh/workspace/studio", tone: "mint" },
|
||||
{ mark: "◌", label: "DISCOVER", title: "Daily Paper", detail: "筛选值得阅读的论文,分析 PDF,并生成文件化笔记与五分钟简报。", href: "/zh/plugins/daily-paper", tone: "cyan" },
|
||||
{ mark: "↗", label: "RESEARCH", title: "Auto Fin", detail: "连接最新财联社新闻与本地历史记忆,生成带 wikilink 的研究报告。", href: "/zh/plugins/auto-fin", tone: "amber" },
|
||||
],
|
||||
trafficLabel: "04 / OPEN METRICS",
|
||||
trafficTitle: "公开、透明的访问趋势",
|
||||
trafficDetail: "最近 30 天的页面浏览量与访问趋势,由 Umami 提供匿名统计。",
|
||||
trafficAction: "打开完整数据页",
|
||||
trafficFrameTitle: "ReMe 最近 30 天访问数据",
|
||||
},
|
||||
en: {
|
||||
eyebrow: "LOCAL-FIRST · FILE-NATIVE",
|
||||
title: "Memory for AI agents.\nFiles that remain yours.",
|
||||
lead: "ReMe turns conversations, resources, and experience into readable, editable, searchable, interconnected local files—a shared long-term memory layer for every agent.",
|
||||
quickStart: "Quick Start",
|
||||
learnMore: "Meet ReMe",
|
||||
stars: "GitHub Stars",
|
||||
forks: "Forks",
|
||||
mapLabel: "SHARED MEMORY WORKSPACE",
|
||||
mapTitle: "One memory layer for every agent",
|
||||
capabilities: [
|
||||
{ icon: "▱", title: "Memory as files", detail: "User-owned files remain the durable source of truth", href: "/en/memory_as_file", tone: "mint" },
|
||||
{ icon: "✦", title: "Memory workflows", detail: "Evolve daily records into durable, connected digests", href: "/en/auto_memory", tone: "cyan" },
|
||||
{ icon: "⌕", title: "Search and graph", detail: "Combine keyword, vector, and wikilink retrieval", href: "/en/memory_search", tone: "blue" },
|
||||
{ icon: "⌁", title: "Agent integrations", detail: "Connect through CLI, HTTP, MCP, and host adapters", href: "/en/integrations", tone: "amber" },
|
||||
],
|
||||
benchmarkLabel: "02 / BENCHMARKS",
|
||||
benchmarkTitle: "Memory that holds up\nunder pressure",
|
||||
benchmarkLead: "From cross-session retrieval to million-token context, ReMe validates long-term memory with reproducible public benchmarks.",
|
||||
benchmarkAction: "Explore all benchmarks",
|
||||
benchmarkNote: "Published reference runs · Agentic score",
|
||||
benchmarks: [
|
||||
{ name: "LongMemEval", setting: "500 questions · cleaned-s", score: 89.4 },
|
||||
{ name: "BEAM 100K", setting: "20 cases · 400 questions", score: 66.1 },
|
||||
{ name: "BEAM 1M", setting: "35 cases · 700 questions", score: 65.0 },
|
||||
],
|
||||
piLabel: "π-Bench proactivity",
|
||||
piDetail: "Average PROC score across five personas",
|
||||
piDelta: "+2.4% over NanoBot",
|
||||
sectionLabel: "03 / PRODUCTS & PLUGINS",
|
||||
sectionTitle: "From memory workspace to automated research",
|
||||
sectionLead: "Three complete paths for putting ReMe into real workflows.",
|
||||
products: [
|
||||
{ mark: "▣", label: "WORKSPACE", title: "ReMe Studio", detail: "Browse, edit, and search memory in a local web workspace, then explore its wikilink graph.", href: "/en/workspace/studio", tone: "mint" },
|
||||
{ mark: "◌", label: "DISCOVER", title: "Daily Paper", detail: "Select useful papers, analyze PDFs, and create file-native notes plus a five-minute brief.", href: "/en/plugins/daily-paper", tone: "cyan" },
|
||||
{ mark: "↗", label: "RESEARCH", title: "Auto Fin", detail: "Connect recent CLS news with local memory to create traceable, wikilink-backed reports.", href: "/en/plugins/auto-fin", tone: "amber" },
|
||||
],
|
||||
trafficLabel: "04 / OPEN METRICS",
|
||||
trafficTitle: "Public, transparent traffic",
|
||||
trafficDetail: "Page views and traffic trends from the last 30 days, measured anonymously with Umami.",
|
||||
trafficAction: "Open the full report",
|
||||
trafficFrameTitle: "ReMe traffic for the last 30 days",
|
||||
},
|
||||
} as const;
|
||||
|
||||
const text = computed(() => translations[props.lang]);
|
||||
const localLink = (href: string) => withBase(href);
|
||||
|
||||
function normalizeCompactCount(value: string) {
|
||||
const normalized = value.trim().toUpperCase();
|
||||
return /[KMB]$/.test(normalized) ? `${normalized}+` : normalized;
|
||||
}
|
||||
|
||||
async function readBadge(metric: "stars" | "forks") {
|
||||
const response = await fetch(`https://img.shields.io/github/${metric}/agentscope-ai/ReMe.json`);
|
||||
if (!response.ok) throw new Error(`Unable to load ${metric}`);
|
||||
const payload = await response.json();
|
||||
return normalizeCompactCount(String(payload.message || payload.value || ""));
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const [stars, forks] = await Promise.allSettled([readBadge("stars"), readBadge("forks")]);
|
||||
if (stars.status === "fulfilled" && stars.value) stats.stars = stars.value;
|
||||
if (forks.status === "fulfilled" && forks.value) stats.forks = forks.value;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="reme-home" :class="{ 'is-zh': lang === 'zh' }">
|
||||
<section class="home-stage">
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow">{{ text.eyebrow }}</p>
|
||||
<h1>{{ text.title }}</h1>
|
||||
<p class="hero-lead">{{ text.lead }}</p>
|
||||
|
||||
<div class="hero-actions">
|
||||
<a class="action primary" :href="localLink(`/${lang}/quick_start`)">{{ text.quickStart }} <span>→</span></a>
|
||||
<a class="action secondary" :href="localLink(`/${lang}/memory_as_file`)">{{ text.learnMore }} <span>↗</span></a>
|
||||
</div>
|
||||
|
||||
<div class="repo-stats" aria-live="polite">
|
||||
<a :href="`${repository}/stargazers`" target="_blank" rel="noreferrer" :aria-label="`${stats.stars} ${text.stars}`">
|
||||
<span class="stat-icon">☆</span>
|
||||
<span><strong>{{ stats.stars }}</strong><small>{{ text.stars }}</small></span>
|
||||
</a>
|
||||
<a :href="`${repository}/forks`" target="_blank" rel="noreferrer" :aria-label="`${stats.forks} ${text.forks}`">
|
||||
<span class="stat-icon fork-icon">⑂</span>
|
||||
<span><strong>{{ stats.forks }}</strong><small>{{ text.forks }}</small></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="capability-map">
|
||||
<div class="map-heading">
|
||||
<div>
|
||||
<span>{{ text.mapLabel }}</span>
|
||||
<strong>{{ text.mapTitle }}</strong>
|
||||
</div>
|
||||
<img :src="localLink('/reme-icon.svg')" alt="" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="map-grid">
|
||||
<a
|
||||
v-for="(capability, index) in text.capabilities"
|
||||
:key="capability.title"
|
||||
class="capability-card"
|
||||
:class="capability.tone"
|
||||
:href="localLink(capability.href)"
|
||||
>
|
||||
<span class="capability-index">0{{ index + 1 }}</span>
|
||||
<span class="capability-icon" aria-hidden="true">{{ capability.icon }}</span>
|
||||
<div class="capability-copy">
|
||||
<strong>{{ capability.title }}</strong>
|
||||
<small>{{ capability.detail }}</small>
|
||||
</div>
|
||||
<span class="card-arrow">↗</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="benchmark-section page-panel">
|
||||
<div class="benchmark-intro">
|
||||
<p class="section-label">{{ text.benchmarkLabel }}</p>
|
||||
<h2>{{ text.benchmarkTitle }}</h2>
|
||||
<p>{{ text.benchmarkLead }}</p>
|
||||
<a :href="localLink(`/${lang}/benchmarks/longmemeval`)">{{ text.benchmarkAction }} <span>→</span></a>
|
||||
</div>
|
||||
|
||||
<div class="benchmark-board">
|
||||
<div class="benchmark-board-head">
|
||||
<span>{{ text.benchmarkNote }}</span>
|
||||
<span>0—100%</span>
|
||||
</div>
|
||||
<div class="benchmark-chart">
|
||||
<div v-for="benchmark in text.benchmarks" :key="benchmark.name" class="benchmark-row">
|
||||
<div class="benchmark-name">
|
||||
<strong>{{ benchmark.name }}</strong>
|
||||
<small>{{ benchmark.setting }}</small>
|
||||
</div>
|
||||
<div class="benchmark-track" aria-hidden="true">
|
||||
<span :style="{ width: `${benchmark.score}%` }"></span>
|
||||
</div>
|
||||
<strong class="benchmark-score">{{ benchmark.score.toFixed(1) }}%</strong>
|
||||
</div>
|
||||
</div>
|
||||
<a class="pi-score" :href="localLink(`/${lang}/benchmarks/pibench`)" :aria-label="`${text.piLabel}: 0.580`">
|
||||
<span class="pi-symbol">π</span>
|
||||
<span>
|
||||
<small>{{ text.piLabel }}</small>
|
||||
<strong>0.580</strong>
|
||||
<em>{{ text.piDetail }}</em>
|
||||
</span>
|
||||
<b>{{ text.piDelta }} ↗</b>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="product-section">
|
||||
<div class="section-heading">
|
||||
<p class="section-label">{{ text.sectionLabel }}</p>
|
||||
<div>
|
||||
<h2>{{ text.sectionTitle }}</h2>
|
||||
<p>{{ text.sectionLead }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-grid">
|
||||
<a
|
||||
v-for="product in text.products"
|
||||
:key="product.title"
|
||||
class="product-card"
|
||||
:class="product.tone"
|
||||
:href="localLink(product.href)"
|
||||
>
|
||||
<span class="product-mark">{{ product.mark }}</span>
|
||||
<span class="product-label">{{ product.label }}</span>
|
||||
<strong>{{ product.title }}</strong>
|
||||
<p>{{ product.detail }}</p>
|
||||
<span class="product-arrow">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="traffic-section page-panel">
|
||||
<div class="traffic-heading">
|
||||
<p class="section-label">{{ text.trafficLabel }}</p>
|
||||
<h2>{{ text.trafficTitle }}</h2>
|
||||
<p>{{ text.trafficDetail }}</p>
|
||||
<a :href="localLink(`/${lang}/traffic`)">{{ text.trafficAction }} <span>→</span></a>
|
||||
</div>
|
||||
<div class="traffic-window">
|
||||
<div class="traffic-window-bar" aria-hidden="true">
|
||||
<span></span><span></span><span></span><b>reme.agentscope.io · 30 days</b>
|
||||
</div>
|
||||
<iframe :src="trafficShareUrl" :title="text.trafficFrameTitle" loading="lazy" referrerpolicy="no-referrer" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.reme-home {
|
||||
--home-ink: #17231e;
|
||||
--home-muted: #66736d;
|
||||
--home-line: #d8e2dc;
|
||||
--section-light: #f8faf8;
|
||||
--section-tint: #edf4f1;
|
||||
max-width: 1720px;
|
||||
margin: 0 auto;
|
||||
padding: 0 clamp(24px, 4.5vw, 72px) 80px;
|
||||
color: var(--home-ink);
|
||||
}
|
||||
.home-stage {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 2fr) minmax(460px, 1fr);
|
||||
gap: clamp(42px, 4.5vw, 78px);
|
||||
align-items: center;
|
||||
min-height: calc(100vh - 64px);
|
||||
padding: 72px 0 82px;
|
||||
}
|
||||
.home-stage::before {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
inset: 0 calc(50% - 50vw);
|
||||
background:
|
||||
radial-gradient(ellipse 70% 105% at -8% 18%, rgba(21, 158, 126, 0.14), transparent 72%),
|
||||
radial-gradient(ellipse 68% 105% at 108% 10%, rgba(77, 103, 211, 0.13), transparent 73%),
|
||||
linear-gradient(115deg, #f7fbf8 0%, #fbfaf6 49%, #f7f8fd 100%);
|
||||
content: "";
|
||||
}
|
||||
.eyebrow, .section-label { margin: 0; color: #0a7f70; font: 750 13px/1.4 var(--vp-font-family-mono); letter-spacing: 0.16em; }
|
||||
.hero-copy h1 { max-width: 100%; margin: 23px 0 0; color: #121b17; font: 760 clamp(52px, 4.2vw, 78px)/1.04 Georgia, "Times New Roman", serif; white-space: pre; letter-spacing: -0.052em; }
|
||||
.is-zh .hero-copy h1 { max-width: 760px; font-size: clamp(52px, 3.6vw, 64px); white-space: pre-line; word-break: keep-all; }
|
||||
.hero-lead { max-width: 650px; margin: 28px 0 0; color: #5e6963; font-size: clamp(17px, 1.3vw, 20px); line-height: 1.75; }
|
||||
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }
|
||||
.action { display: inline-flex; align-items: center; justify-content: space-between; gap: 28px; min-width: 166px; min-height: 54px; padding: 0 19px; border: 1px solid #bfcac4; border-radius: 12px; color: #1b2721; background: rgba(255, 255, 255, 0.72); text-decoration: none; font-weight: 720; box-shadow: 0 8px 22px rgba(28, 57, 45, 0.06); transition: transform 160ms ease, box-shadow 160ms ease; }
|
||||
.action.primary { border-color: #17241e; color: white; background: #17241e; box-shadow: 0 12px 26px rgba(20, 34, 28, 0.2); }
|
||||
.action:hover { transform: translateY(-2px); box-shadow: 0 15px 28px rgba(28, 57, 45, 0.13); }
|
||||
.repo-stats { display: flex; flex-wrap: wrap; gap: 34px; margin-top: 40px; }
|
||||
.repo-stats a { display: flex; gap: 12px; align-items: flex-start; color: inherit; text-decoration: none; }
|
||||
.stat-icon { color: #087f6a; font-size: 30px; line-height: 1; }
|
||||
.fork-icon { transform: rotate(90deg); }
|
||||
.repo-stats strong { display: block; font: 740 28px/1 var(--vp-font-family-mono); letter-spacing: -0.04em; }
|
||||
.repo-stats small { display: block; margin-top: 8px; color: var(--home-muted); font-size: 13px; }
|
||||
.capability-map { position: relative; padding: 21px; border: 1px solid rgba(33, 73, 57, 0.16); border-radius: 26px; background: rgba(255, 255, 255, 0.58); box-shadow: 0 30px 70px rgba(36, 67, 54, 0.12); backdrop-filter: blur(18px); }
|
||||
.map-heading { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 20px; }
|
||||
.map-heading > div { display: flex; min-width: 0; flex-direction: column; gap: 8px; }
|
||||
.map-heading span { color: #1c8071; font: 700 10px/1.4 var(--vp-font-family-mono); letter-spacing: 0.12em; }
|
||||
.map-heading strong { font-size: 18px; line-height: 1.3; white-space: nowrap; }
|
||||
.map-heading img { width: 42px; height: 42px; flex: none; margin: 0; padding: 6px; border: 1px solid var(--home-line); border-radius: 13px; background: rgba(255, 255, 255, 0.82); box-shadow: 0 8px 18px rgba(25, 55, 43, 0.09); }
|
||||
.map-grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
|
||||
.capability-card { position: relative; display: grid; grid-template-columns: 25px 34px minmax(0, 1fr) 16px; gap: 11px; align-items: center; min-height: 96px; padding: 17px 18px; overflow: hidden; border: 1px solid color-mix(in srgb, var(--card-accent) 32%, #d9e1dc); border-radius: 15px; color: var(--home-ink); background: radial-gradient(circle at 92% 8%, color-mix(in srgb, var(--card-accent) 15%, transparent), transparent 42%), rgba(255, 255, 255, 0.88); text-decoration: none; transition: transform 170ms ease, box-shadow 170ms ease; }
|
||||
.capability-card:hover { transform: translateY(-3px); box-shadow: 0 16px 30px color-mix(in srgb, var(--card-accent) 13%, transparent); }
|
||||
.mint { --card-accent: #059b7f; }.cyan { --card-accent: #169cc4; }.blue { --card-accent: #536bd8; }.amber { --card-accent: #c48324; }.violet { --card-accent: #7654c2; }
|
||||
.capability-index { color: #8b9690; font: 650 10px/1 var(--vp-font-family-mono); letter-spacing: 0.12em; }
|
||||
.capability-copy { min-width: 0; }
|
||||
.capability-icon { display: grid; place-items: center; width: 32px; height: 32px; flex: none; border-radius: 9px; color: var(--card-accent); background: color-mix(in srgb, var(--card-accent) 11%, white); font: 600 21px/1 var(--vp-font-family-mono); }
|
||||
.capability-card strong { display: block; overflow: hidden; font-size: 17px; line-height: 1.25; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.capability-card small { display: block; overflow: hidden; margin-top: 6px; color: var(--home-muted); font-size: 12px; line-height: 1.45; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.card-arrow { color: var(--card-accent); font-size: 16px; }
|
||||
.page-panel { position: relative; min-height: calc(100vh - 64px); }
|
||||
.benchmark-section { display: grid; grid-template-columns: minmax(310px, 0.72fr) minmax(560px, 1.28fr); gap: clamp(54px, 7vw, 110px); align-items: center; padding: 112px 0 120px; color: var(--home-ink); }
|
||||
.benchmark-section::before { position: absolute; z-index: -1; inset: 0 calc(50% - 50vw); border-top: 1px solid rgba(27, 67, 52, 0.08); background: var(--section-tint); content: ""; }
|
||||
.benchmark-intro .section-label { color: #087f6a; }
|
||||
.benchmark-intro h2 { max-width: 620px; margin: 23px 0 0; color: var(--home-ink); font-size: clamp(42px, 4.2vw, 68px); line-height: 1.06; white-space: pre-line; letter-spacing: -0.052em; }
|
||||
.is-zh .benchmark-intro h2 { word-break: keep-all; }
|
||||
.benchmark-intro > p:not(.section-label) { max-width: 560px; margin: 24px 0 0; color: var(--home-muted); font-size: 17px; line-height: 1.75; }
|
||||
.benchmark-intro > a, .traffic-heading > a { display: inline-flex; align-items: center; gap: 32px; min-height: 50px; margin-top: 34px; padding: 0 18px; border: 1px solid color-mix(in srgb, var(--home-ink) 24%, transparent); border-radius: 11px; color: var(--home-ink); text-decoration: none; font-weight: 720; transition: background 160ms ease, transform 160ms ease; }
|
||||
.benchmark-intro > a:hover, .traffic-heading > a:hover { background: color-mix(in srgb, var(--home-ink) 6%, transparent); transform: translateY(-2px); }
|
||||
.benchmark-board { padding: clamp(24px, 3vw, 38px); border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 26px; color: white; background: #15352b; box-shadow: 0 28px 64px rgba(24, 58, 45, 0.2); }
|
||||
.benchmark-board-head { display: flex; justify-content: space-between; gap: 20px; padding-bottom: 22px; border-bottom: 1px solid rgba(255, 255, 255, 0.13); color: #94aca3; font: 700 11px/1.4 var(--vp-font-family-mono); letter-spacing: 0.1em; text-transform: uppercase; }
|
||||
.benchmark-chart { display: grid; gap: 28px; padding: 32px 0; }
|
||||
.benchmark-row { display: grid; grid-template-columns: 150px minmax(140px, 1fr) 72px; gap: 20px; align-items: center; }
|
||||
.benchmark-name strong { display: block; color: white; font-size: 16px; }
|
||||
.benchmark-name small { display: block; margin-top: 5px; color: #8fa69d; font-size: 12px; }
|
||||
.benchmark-track { height: 10px; overflow: hidden; border-radius: 99px; background: rgba(255, 255, 255, 0.09); }
|
||||
.benchmark-track span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #38d3ae, #85ead2); box-shadow: 0 0 22px rgba(66, 220, 182, 0.28); }
|
||||
.benchmark-score { color: white; font: 740 20px/1 var(--vp-font-family-mono); text-align: right; }
|
||||
.pi-score { display: grid; grid-template-columns: 58px minmax(0, 1fr) auto; gap: 18px; align-items: center; padding: 20px; border: 1px solid rgba(142, 160, 255, 0.27); border-radius: 18px; color: white; background: linear-gradient(110deg, rgba(82, 105, 216, 0.23), rgba(82, 105, 216, 0.08)); text-decoration: none; }
|
||||
.pi-symbol { display: grid; place-items: center; width: 58px; height: 58px; border-radius: 15px; color: #b9c6ff; background: rgba(107, 129, 236, 0.18); font: 700 31px/1 Georgia, serif; }
|
||||
.pi-score small, .pi-score em { display: block; color: #aabbb4; font-size: 12px; font-style: normal; }
|
||||
.pi-score strong { display: block; margin: 4px 0; font: 750 25px/1 var(--vp-font-family-mono); }
|
||||
.pi-score b { color: #a9b7ff; font-size: 13px; white-space: nowrap; }
|
||||
.product-section { position: relative; display: flex; min-height: calc(100vh - 64px); flex-direction: column; justify-content: center; padding: 112px 0 120px; }
|
||||
.product-section::before { position: absolute; z-index: -1; inset: 0 calc(50% - 50vw); border-top: 1px solid rgba(27, 67, 52, 0.08); background: var(--section-light); content: ""; }
|
||||
.section-heading { display: grid; grid-template-columns: minmax(190px, 0.38fr) minmax(0, 1fr); gap: 40px; align-items: start; margin-bottom: 36px; }
|
||||
.section-heading h2, .traffic-heading h2 { max-width: 820px; margin: 0; color: var(--home-ink); font-size: clamp(38px, 3.6vw, 58px); line-height: 1.1; letter-spacing: -0.045em; }
|
||||
.section-heading p:not(.section-label) { margin: 15px 0 0; color: var(--home-muted); font-size: 16px; }
|
||||
.product-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
|
||||
.product-card { position: relative; display: flex; min-height: 360px; flex-direction: column; padding: 30px; overflow: hidden; border: 1px solid color-mix(in srgb, var(--card-accent) 30%, var(--home-line)); border-radius: 22px; color: var(--home-ink); background: radial-gradient(circle at 80% 0, color-mix(in srgb, var(--card-accent) 14%, transparent), transparent 50%), linear-gradient(150deg, #fff, color-mix(in srgb, var(--card-accent) 5%, #f7f9f7)); text-decoration: none; transition: transform 170ms ease, box-shadow 170ms ease; }
|
||||
.product-card:hover { transform: translateY(-4px); box-shadow: 0 20px 38px color-mix(in srgb, var(--card-accent) 14%, transparent); }
|
||||
.product-mark { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 13px; color: var(--card-accent); background: color-mix(in srgb, var(--card-accent) 13%, white); font: 650 24px/1 var(--vp-font-family-mono); }
|
||||
.product-label { margin-top: 50px; color: var(--card-accent); font: 720 11px/1.3 var(--vp-font-family-mono); letter-spacing: 0.12em; }
|
||||
.product-card strong { margin-top: 10px; font-size: 23px; }
|
||||
.product-card p { max-width: 390px; margin: 13px 0 0; color: var(--home-muted); font-size: 15px; line-height: 1.65; }
|
||||
.product-arrow { position: absolute; right: 23px; bottom: 20px; color: var(--card-accent); font-size: 22px; }
|
||||
.traffic-section { display: grid; grid-template-columns: minmax(300px, 0.64fr) minmax(600px, 1.36fr); gap: clamp(48px, 6vw, 94px); align-items: center; padding: 112px 0 116px; color: var(--home-ink); }
|
||||
.traffic-section::before { position: absolute; z-index: -1; inset: 0 calc(50% - 50vw); border-top: 1px solid rgba(27, 67, 52, 0.08); background: var(--section-tint); content: ""; }
|
||||
.traffic-heading .section-label { color: #087f6a; }
|
||||
.traffic-heading h2 { margin-top: 22px; color: var(--home-ink); }
|
||||
.traffic-heading > p:not(.section-label) { max-width: 460px; margin: 22px 0 0; color: var(--home-muted); font-size: 17px; line-height: 1.7; }
|
||||
.traffic-window { overflow: hidden; height: min(650px, calc(100vh - 170px)); min-height: 520px; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 24px; background: white; box-shadow: 0 34px 80px rgba(0, 0, 0, 0.3); }
|
||||
.traffic-window-bar { display: flex; align-items: center; gap: 8px; height: 46px; padding: 0 16px; border-bottom: 1px solid #e5e8e7; background: #f6f8f7; }
|
||||
.traffic-window-bar span { width: 9px; height: 9px; border-radius: 50%; background: #a8b4af; }
|
||||
.traffic-window-bar span:first-child { background: #f08d78; }
|
||||
.traffic-window-bar span:nth-child(2) { background: #e6bf67; }
|
||||
.traffic-window-bar span:nth-child(3) { background: #69bd9a; }
|
||||
.traffic-window-bar b { margin-left: 8px; color: #7b8983; font: 650 11px/1 var(--vp-font-family-mono); }
|
||||
.traffic-window iframe { width: 100%; height: calc(100% - 46px); border: 0; }
|
||||
:global(.dark) .reme-home { --home-ink: #edf7f3; --home-muted: #a8bbb3; --home-line: #2d4038; --section-light: #0d1512; --section-tint: #14201b; }
|
||||
:global(.dark) .home-stage::before { background: radial-gradient(ellipse 70% 105% at -8% 18%, rgba(24, 169, 143, 0.13), transparent 72%), radial-gradient(ellipse 68% 105% at 108% 10%, rgba(74, 100, 218, 0.15), transparent 73%), linear-gradient(115deg, #0d1713 0%, #101713 49%, #10131c 100%); }
|
||||
:global(.dark) .hero-copy h1 { color: var(--home-ink); }
|
||||
:global(.dark) .action.secondary { border-color: #3b4c45; color: var(--home-ink); background: rgba(20, 32, 27, 0.76); }
|
||||
:global(.dark) .capability-map { border-color: #2c4037; background: rgba(17, 28, 23, 0.72); }
|
||||
:global(.dark) .capability-card, :global(.dark) .product-card { background: radial-gradient(circle at 92% 8%, color-mix(in srgb, var(--card-accent) 16%, transparent), transparent 42%), #14201b; }
|
||||
:global(.dark) .benchmark-section::before { background: var(--section-tint); }
|
||||
:global(.dark) .product-section::before { background: var(--section-light); }
|
||||
:global(.dark) .traffic-section::before { background: var(--section-tint); }
|
||||
:global(.dark) .benchmark-board { background: #0b1712; box-shadow: 0 28px 64px rgba(0, 0, 0, 0.28); }
|
||||
@media (max-width: 1320px) {
|
||||
.home-stage { grid-template-columns: 1fr; min-height: auto; }
|
||||
.hero-copy { max-width: 800px; padding-top: 26px; }
|
||||
.hero-copy h1 { white-space: normal; }
|
||||
.capability-map { max-width: 850px; }
|
||||
.map-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.benchmark-section, .traffic-section { grid-template-columns: 1fr; min-height: auto; }
|
||||
.benchmark-intro, .traffic-heading { max-width: 720px; }
|
||||
.traffic-window { width: 100%; max-width: 1000px; }
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
.reme-home { padding-right: 20px; padding-left: 20px; }
|
||||
.home-stage { gap: 42px; padding: 52px 0 62px; }
|
||||
.hero-copy h1 { font-size: clamp(43px, 13vw, 62px); }
|
||||
.hero-lead { font-size: 16px; }
|
||||
.map-heading strong { white-space: normal; }
|
||||
.map-grid { grid-template-columns: 1fr; }
|
||||
.capability-card { min-height: 96px; }
|
||||
.section-heading { grid-template-columns: 1fr; gap: 18px; }
|
||||
.product-grid { grid-template-columns: 1fr; }
|
||||
.product-card { min-height: 280px; }
|
||||
.benchmark-section, .product-section, .traffic-section { padding-top: 78px; padding-bottom: 84px; }
|
||||
.benchmark-row { grid-template-columns: minmax(0, 1fr) auto; gap: 12px; }
|
||||
.benchmark-track { grid-column: 1 / -1; grid-row: 2; }
|
||||
.benchmark-score { grid-column: 2; grid-row: 1; }
|
||||
.pi-score { grid-template-columns: 48px minmax(0, 1fr); }
|
||||
.pi-symbol { width: 48px; height: 48px; }
|
||||
.pi-score b { grid-column: 2; }
|
||||
.traffic-window { height: 660px; min-height: 0; border-radius: 17px; }
|
||||
}
|
||||
</style>
|
||||
52
docs/.vitepress/theme/TrafficPage.vue
Normal file
52
docs/.vitepress/theme/TrafficPage.vue
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{ lang: "zh" | "en" }>();
|
||||
const shareUrl = "https://cloud.umami.is/analytics/us/share/S1OZK1PSDLEpyiU5?date=30day&page=1";
|
||||
const text = computed(() => props.lang === "zh" ? {
|
||||
eyebrow: "OPEN METRICS",
|
||||
title: "ReMe 访问数据",
|
||||
description: "最近 30 天的页面浏览量与访问趋势,由 Umami 提供隐私友好的匿名统计。",
|
||||
action: "在 Umami 中打开完整页面",
|
||||
frameTitle: "ReMe 最近 30 天访问数据",
|
||||
} : {
|
||||
eyebrow: "OPEN METRICS",
|
||||
title: "ReMe traffic",
|
||||
description: "Page views and traffic trends from the last 30 days, measured anonymously with privacy-friendly Umami analytics.",
|
||||
action: "Open the full report in Umami",
|
||||
frameTitle: "ReMe traffic for the last 30 days",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="traffic-page">
|
||||
<header>
|
||||
<div>
|
||||
<p>{{ text.eyebrow }}</p>
|
||||
<h1>{{ text.title }}</h1>
|
||||
<span>{{ text.description }}</span>
|
||||
</div>
|
||||
<a :href="shareUrl" target="_blank" rel="noreferrer">{{ text.action }} ↗</a>
|
||||
</header>
|
||||
<div class="traffic-frame-wrap">
|
||||
<iframe :src="shareUrl" :title="text.frameTitle" loading="eager" referrerpolicy="no-referrer" />
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.traffic-page { max-width: 1440px; margin: 0 auto; padding: clamp(54px, 7vw, 96px) clamp(22px, 5vw, 74px) 90px; }
|
||||
.traffic-page header { display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; margin-bottom: 34px; }
|
||||
.traffic-page header p { margin: 0 0 15px; color: var(--vp-c-brand-1); font: 750 12px/1.4 var(--vp-font-family-mono); letter-spacing: 0.16em; }
|
||||
.traffic-page h1 { margin: 0; color: var(--vp-c-text-1); font-size: clamp(42px, 5.5vw, 68px); line-height: 1.05; letter-spacing: -0.05em; }
|
||||
.traffic-page header span { display: block; max-width: 720px; margin-top: 17px; color: var(--vp-c-text-2); font-size: 17px; line-height: 1.65; }
|
||||
.traffic-page header a { flex: none; padding: 11px 15px; border: 1px solid var(--vp-c-divider); border-radius: 10px; color: var(--vp-c-text-1); background: var(--vp-c-bg-soft); text-decoration: none; font-size: 14px; font-weight: 700; }
|
||||
.traffic-page header a:hover { border-color: var(--vp-c-brand-1); color: var(--vp-c-brand-1); }
|
||||
.traffic-frame-wrap { height: min(880px, calc(100vh - 210px)); min-height: 650px; overflow: hidden; border: 1px solid var(--vp-c-divider); border-radius: 20px; background: white; box-shadow: 0 24px 58px rgba(26, 62, 47, 0.12); }
|
||||
.traffic-frame-wrap iframe { width: 100%; height: 100%; border: 0; }
|
||||
@media (max-width: 700px) {
|
||||
.traffic-page { padding-top: 42px; }
|
||||
.traffic-page header { align-items: flex-start; flex-direction: column; gap: 20px; }
|
||||
.traffic-frame-wrap { height: 720px; min-height: 0; border-radius: 14px; }
|
||||
}
|
||||
</style>
|
||||
|
|
@ -63,6 +63,39 @@ body {
|
|||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.VPNavBar.has-sidebar .container > .title {
|
||||
width: 113px !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.VPNavBar.has-sidebar .content {
|
||||
padding-left: 113px !important;
|
||||
}
|
||||
|
||||
.VPNavBarSearch {
|
||||
padding-left: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1496px) {
|
||||
.VPNavBar.has-sidebar .container {
|
||||
position: relative !important;
|
||||
max-width: 1496px !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.VPNavBar.has-sidebar .container > .title {
|
||||
width: 81px !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
.VPNavBar.has-sidebar .content {
|
||||
padding-right: 0 !important;
|
||||
padding-left: 81px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.VPSidebar {
|
||||
border-right: 1px solid var(--vp-c-divider);
|
||||
background: color-mix(in srgb, var(--vp-c-bg-alt) 82%, transparent);
|
||||
|
|
@ -183,6 +216,7 @@ body {
|
|||
}
|
||||
|
||||
.VPHome {
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(circle at 14% 14%, rgba(25, 201, 176, 0.14), transparent 30rem),
|
||||
radial-gradient(circle at 86% 10%, rgba(49, 86, 217, 0.11), transparent 28rem);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import { h } from "vue";
|
||||
import DefaultTheme from "vitepress/theme";
|
||||
import CopyMarkdownButton from "./CopyMarkdownButton.vue";
|
||||
import HomePage from "./HomePage.vue";
|
||||
import SourceLink from "./SourceLink.vue";
|
||||
import TrafficPage from "./TrafficPage.vue";
|
||||
import "./custom.css";
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
app.component("HomePage", HomePage);
|
||||
app.component("TrafficPage", TrafficPage);
|
||||
},
|
||||
Layout() {
|
||||
return h(DefaultTheme.Layout, null, {
|
||||
"doc-before": () => h(CopyMarkdownButton),
|
||||
|
|
|
|||
|
|
@ -1,36 +1,9 @@
|
|||
---
|
||||
layout: home
|
||||
title: ReMe Documentation
|
||||
markdownStyles: false
|
||||
title: ReMe
|
||||
titleTemplate: false
|
||||
hero:
|
||||
name: ReMe
|
||||
text: Memory that works for agents
|
||||
tagline: Files remain yours. ReMe turns conversations and resources into readable, editable, searchable, interconnected local files.
|
||||
image:
|
||||
src: /reme-logo.svg
|
||||
alt: ReMe logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Quick Start
|
||||
link: /en/quick_start
|
||||
- theme: alt
|
||||
text: Configuration
|
||||
link: /en/configuration
|
||||
features:
|
||||
- icon: 📁
|
||||
title: Memory as files
|
||||
details: Workspace files are the durable source of truth; indexes, graphs, and caches remain rebuildable.
|
||||
link: /en/memory_as_file
|
||||
- icon: 🧠
|
||||
title: Memory workflows
|
||||
details: Turn conversations and resources into daily notes, then consolidate them into connected long-term digests.
|
||||
link: /en/auto_memory
|
||||
- icon: 🔎
|
||||
title: Search and graph
|
||||
details: Combine keyword and optional vector retrieval with wikilink graph expansion.
|
||||
link: /en/memory_search
|
||||
- icon: 🔌
|
||||
title: Agent integrations
|
||||
details: Connect existing agents through the CLI, HTTP, MCP, and host adapters.
|
||||
link: /en/integrations
|
||||
description: ReMe is a local-first, file-native memory system for agents.
|
||||
---
|
||||
|
||||
<HomePage lang="en" />
|
||||
|
|
|
|||
8
docs/en/traffic.md
Normal file
8
docs/en/traffic.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
layout: home
|
||||
markdownStyles: false
|
||||
title: ReMe Traffic
|
||||
description: Public traffic trends for the ReMe documentation site over the last 30 days.
|
||||
---
|
||||
|
||||
<TrafficPage lang="en" />
|
||||
|
|
@ -1,36 +1,9 @@
|
|||
---
|
||||
layout: home
|
||||
title: ReMe 文档
|
||||
markdownStyles: false
|
||||
title: ReMe
|
||||
titleTemplate: false
|
||||
hero:
|
||||
name: ReMe
|
||||
text: 让 Agent 真正记住
|
||||
tagline: 文件属于你,记忆服务于 Agent。ReMe 将对话和资料沉淀为可读、可编辑、可检索、相互链接的本地文件。
|
||||
image:
|
||||
src: /reme-logo.svg
|
||||
alt: ReMe Logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
link: /zh/quick_start
|
||||
- theme: alt
|
||||
text: 查看配置
|
||||
link: /zh/configuration
|
||||
features:
|
||||
- icon: 📁
|
||||
title: 文件即记忆
|
||||
details: Workspace 文件是持久事实源;索引、图谱和缓存都可以重新构建。
|
||||
link: /zh/memory_as_file
|
||||
- icon: 🧠
|
||||
title: 自动记忆
|
||||
details: 将对话和资料写入 daily,自动整理为互相关联的长期 digest。
|
||||
link: /zh/auto_memory
|
||||
- icon: 🔎
|
||||
title: 检索与图谱
|
||||
details: 结合关键词、可选向量检索与 wikilink 图谱,渐进式展开上下文。
|
||||
link: /zh/memory_search
|
||||
- icon: 🔌
|
||||
title: Agent 集成
|
||||
details: 通过 CLI、HTTP、MCP 和宿主适配器接入已有 Agent。
|
||||
link: /zh/integrations
|
||||
description: ReMe 是面向 Agent 的本地优先、文件原生记忆系统。
|
||||
---
|
||||
|
||||
<HomePage lang="zh" />
|
||||
|
|
|
|||
8
docs/zh/traffic.md
Normal file
8
docs/zh/traffic.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
layout: home
|
||||
markdownStyles: false
|
||||
title: ReMe 访问数据
|
||||
description: ReMe 文档站最近 30 天的公开访问趋势。
|
||||
---
|
||||
|
||||
<TrafficPage lang="zh" />
|
||||
|
|
@ -8,6 +8,8 @@ const repoDir = path.resolve(siteDir, "..");
|
|||
const outputDir = path.join(siteDir, ".generated", "site");
|
||||
|
||||
const externalDocuments = [
|
||||
["zh/overview.md", "README_ZH.md"],
|
||||
["en/overview.md", "README.md"],
|
||||
["en/integrations/claude-code.md", "integrations/claude_code/README.md"],
|
||||
["en/integrations/hermes.md", "integrations/hermes_agent/README.md"],
|
||||
["zh/integrations/typescript.md", "typescript/README_ZH.md"],
|
||||
|
|
@ -37,6 +39,20 @@ const externalDocuments = [
|
|||
];
|
||||
|
||||
const externalDocumentRewrites = {
|
||||
"README.md": [
|
||||
['href="./LICENSE"', 'href="https://github.com/agentscope-ai/ReMe/blob/main/LICENSE"'],
|
||||
['href="./README.md"', 'href="/en/overview"'],
|
||||
['href="./README_ZH.md"', 'href="/zh/overview"'],
|
||||
['src="docs/figure/', 'src="../figure/'],
|
||||
["(docs/en/", "(./"],
|
||||
],
|
||||
"README_ZH.md": [
|
||||
['href="./LICENSE"', 'href="https://github.com/agentscope-ai/ReMe/blob/main/LICENSE"'],
|
||||
['href="./README.md"', 'href="/en/overview"'],
|
||||
['href="./README_ZH.md"', 'href="/zh/overview"'],
|
||||
['src="docs/figure/', 'src="../figure/'],
|
||||
["(docs/zh/", "(./"],
|
||||
],
|
||||
"typescript/README.md": [
|
||||
["(./README_ZH.md)", "(/zh/integrations/typescript)"],
|
||||
["(./docs/dsh.md)", "(/en/integrations/dsh)"],
|
||||
|
|
@ -69,6 +85,11 @@ const externalDocumentRewrites = {
|
|||
],
|
||||
};
|
||||
|
||||
const externalDocumentPreambles = {
|
||||
"README.md": "---\ntitle: ReMe Overview\ndescription: A local-first, self-evolving personal knowledge base for AI agents.\n---\n\n# ReMe Overview\n\n",
|
||||
"README_ZH.md": "---\ntitle: ReMe 项目介绍\ndescription: 面向 AI Agent 的 local-first 自进化个人知识库。\n---\n\n# ReMe 项目介绍\n\n",
|
||||
};
|
||||
|
||||
const groupNames = {
|
||||
zh: {
|
||||
system: "系统与诊断",
|
||||
|
|
@ -210,6 +231,7 @@ for (const [destination, source] of externalDocuments) {
|
|||
await mkdir(path.dirname(destinationPath), { recursive: true });
|
||||
let content = await readFile(path.join(repoDir, source), "utf8");
|
||||
for (const [from, to] of externalDocumentRewrites[source] || []) content = content.replaceAll(from, to);
|
||||
content = `${externalDocumentPreambles[source] || ""}${content}`;
|
||||
await writeFile(destinationPath, content);
|
||||
sourceMap[destination] = source;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ const requiredFiles = [
|
|||
"llms-full.txt",
|
||||
"zh/index.html",
|
||||
"en/index.html",
|
||||
"zh/overview.html",
|
||||
"en/overview.html",
|
||||
"zh/traffic.html",
|
||||
"en/traffic.html",
|
||||
"zh/configuration.html",
|
||||
"en/configuration.html",
|
||||
"zh/services.html",
|
||||
|
|
@ -60,6 +64,15 @@ assert.ok(homepage.includes('href="/en/"'), "root language switch must link to /
|
|||
assert.ok(!homepage.includes('href="/en/ex"'), "root language switch must not produce /en/ex");
|
||||
assert.ok(homepage.includes('"studio-en":"/en/workspace/studio"'), "legacy redirects must be embedded");
|
||||
|
||||
const ChineseHomepage = await readFile(path.join(outputDir, "zh/index.html"), "utf8");
|
||||
assert.match(ChineseHomepage, /8cafe9df-d883-4046-b5e9-36dfd21a4884/);
|
||||
assert.match(ChineseHomepage, /用真实评测/);
|
||||
assert.match(ChineseHomepage, /89\.4%/);
|
||||
assert.match(ChineseHomepage, /公开、透明的访问趋势/);
|
||||
|
||||
const ChineseTraffic = await readFile(path.join(outputDir, "zh/traffic.html"), "utf8");
|
||||
assert.match(ChineseTraffic, /S1OZK1PSDLEpyiU5/);
|
||||
|
||||
const sitemap = await readFile(path.join(outputDir, "sitemap.xml"), "utf8");
|
||||
assert.ok(sitemap.includes("<lastmod>"), "sitemap must include canonical-source update times");
|
||||
assert.ok(!sitemap.includes("<loc>https://reme.agentscope.io/</loc>"), "root redirect must not be indexed");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const generatedDir = path.join(siteDir, ".generated", "site");
|
|||
|
||||
test("generates every required bilingual guide", async () => {
|
||||
const names = [
|
||||
"overview.md",
|
||||
"configuration.md",
|
||||
"services.md",
|
||||
"operations.md",
|
||||
|
|
@ -37,6 +38,8 @@ test("generates every required bilingual guide", async () => {
|
|||
|
||||
test("maps mirrored pages back to their canonical repository sources", async () => {
|
||||
const sourceMap = JSON.parse(await readFile(path.join(generatedDir, ".source-map.json"), "utf8"));
|
||||
assert.equal(sourceMap["zh/overview.md"], "README_ZH.md");
|
||||
assert.equal(sourceMap["en/overview.md"], "README.md");
|
||||
assert.equal(sourceMap["zh/integrations/typescript.md"], "typescript/README_ZH.md");
|
||||
assert.equal(sourceMap["en/integrations/dsh.md"], "typescript/docs/dsh.md");
|
||||
assert.equal(sourceMap["zh/integrations/openclaw.md"], "typescript/docs/openclaw.zh-CN.md");
|
||||
|
|
@ -47,6 +50,17 @@ test("maps mirrored pages back to their canonical repository sources", async ()
|
|||
assert.equal(sourceMap["en/reference/jobs.md"], "reme/config/default.yaml");
|
||||
});
|
||||
|
||||
test("publishes the root READMEs as localized project overviews", async () => {
|
||||
const english = await readFile(path.join(generatedDir, "en/overview.md"), "utf8");
|
||||
const chinese = await readFile(path.join(generatedDir, "zh/overview.md"), "utf8");
|
||||
assert.match(english, /^---\ntitle: ReMe Overview/m);
|
||||
assert.match(chinese, /^---\ntitle: ReMe 项目介绍/m);
|
||||
assert.match(english, /href="\/zh\/overview"/);
|
||||
assert.match(chinese, /href="\/en\/overview"/);
|
||||
assert.match(english, /src="\.\.\/figure\/design-philosophy\.svg"/);
|
||||
assert.match(chinese, /\(\.\/memory_search\.md\)/);
|
||||
});
|
||||
|
||||
test("publishes portable and accurate DSH instructions", async () => {
|
||||
const english = await readFile(path.join(generatedDir, "en/integrations/dsh.md"), "utf8");
|
||||
const chinese = await readFile(path.join(generatedDir, "zh/integrations/dsh.md"), "utf8");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue