From 66c81c319fc2307c3b39508aa6bb2bf2e099a741 Mon Sep 17 00:00:00 2001 From: nanzhaogang <42226610+nanzhaogang@users.noreply.github.com> Date: Fri, 30 Oct 2026 14:22:02 +0800 Subject: [PATCH] feat(docs): widen the reader column and consolidate the navigation The article column was squeezed between two rails, so it now takes the freed width. Advanced setup and reference become one group, developer docs leave the reader navigation, and sample files linked from the walkthrough are served from the site instead of GitHub. --- site/build.mjs | 34 ++++++++++++++++++++++++++-------- site/src/site.css | 8 +++++--- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/site/build.mjs b/site/build.mjs index 2e68ccd..061e079 100644 --- a/site/build.mjs +++ b/site/build.mjs @@ -139,7 +139,7 @@ const T = { docs: { title: 'Documentation', menu: 'Menu', on: 'On this page', prev: 'Previous', next: 'Next', onlyOther: 'This page is only available in Chinese so far.', homeIntro: 'Start here, then dive into the features you need.', - sections: { 'getting-started': 'Getting Started', core: 'Core Capabilities', domains: 'Domain Guides', 'advanced-setup': 'Advanced Setup', reference: 'Reference', 'developer-docs': 'Developer Documentation' } + sections: { 'getting-started': 'Getting Started', core: 'Core Capabilities', domains: 'Domain Guides', 'setup-reference': 'More Features and Configuration' } } }, zh: { @@ -240,22 +240,27 @@ const T = { docs: { title: '文档', menu: '目录', on: '本页内容', prev: '上一篇', next: '下一篇', onlyOther: '本页暂时只有英文版。', homeIntro: '从这里开始,再深入你需要的功能。', - sections: { 'getting-started': '快速开始', core: '核心功能', domains: '领域教程', 'advanced-setup': '高级配置', reference: '参考', 'developer-docs': '开发者文档' } + sections: { 'getting-started': '快速开始', core: '核心功能', domains: '领域教程', 'setup-reference': '更多功能与配置' } } } }; -// The product documentation owns these six reader-facing groups. Listed pages keep +// The product documentation owns these reader-facing groups. Listed pages keep // a useful reading order; new pages in the same directory are appended automatically. const DOC_GROUPS = [ ['getting-started', ['getting-started/deployment', 'getting-started/quick-start']], ['core', ['core/README', 'core/evolve', 'core/execution-workspaces', 'core/idea-tree']], ['domains', ['domains/README', 'domains/evolve-a-solution', 'domains/run-an-evolution-search', 'domains/literature-research']], - ['advanced-setup', ['advanced-setup/README', 'advanced-setup/configure-custom-mcp', 'advanced-setup/configure-network-proxy', 'advanced-setup/science-memory-setup']], - ['reference', ['reference/README', 'reference/configuration', 'reference/rest-api', 'reference/runtime-behavior', 'reference/builtin-tools', 'reference/web-tools', 'reference/jiuwenswarm-migration-status']], - ['developer-docs', ['developer-docs/README', 'developer-docs/architecture', 'developer-docs/control-plane', 'developer-docs/agent', 'developer-docs/runner', 'developer-docs/sandbox-execution', 'developer-docs/science-memory', 'developer-docs/subagent-orchestration', 'developer-docs/skill-progressive-disclosure', 'developer-docs/science-connectors', 'developer-docs/web-frontend']] + ['setup-reference', [ + 'advanced-setup/README', 'advanced-setup/configure-custom-mcp', 'advanced-setup/configure-network-proxy', 'advanced-setup/science-memory-setup', + 'reference/README', 'reference/configuration', 'reference/rest-api', 'reference/runtime-behavior', 'reference/builtin-tools', 'reference/web-tools', 'reference/jiuwenswarm-migration-status' + ]] ]; +// Implementation notes are still built and linked from the core pages, but they are no longer a +// reader-facing group, so neither the sidebar nor the documentation index lists them. +const DOC_HIDDEN_GROUPS = ['developer-docs']; + // A panel that shows a screenshot is sized from the picture itself: the stylesheet multiplies the // height left for the image by this ratio, so the dialog hugs the image instead of sitting in a // wide empty box. Read straight from the PNG header (IHDR), so replacing the file is enough. @@ -310,9 +315,13 @@ for (const lang of LANGS) { } const keyFor = (k) => (k === 'README' ? 'index' : k.replace(/\/README$/, '/index')); const outPath = (k) => keyFor(k) + '.html'; +// A group normally maps to one documentation directory; setup-reference folds two of them into a +// single rail entry, so it needs both prefixes to discover the pages that are not listed by name. +const GROUP_PREFIXES = { 'setup-reference': ['advanced-setup', 'reference'] }; +const prefixesOf = (group) => GROUP_PREFIXES[group] || [group]; function groupItems(group) { const listed = DOC_GROUPS.find(([name]) => name === group)?.[1] || []; - const available = Object.keys(sources).filter((k) => k.startsWith(group + '/')); + const available = Object.keys(sources).filter((k) => prefixesOf(group).some((p) => k.startsWith(p + '/'))); return [...listed.filter((k) => sources[k]), ...available.filter((k) => !listed.includes(k)).sort()]; } @@ -399,6 +408,10 @@ function renderDoc(md, srcFile, lang, pagePath) { } const r = relative(ROOT, abs).split(sep).join('/'); if (r.startsWith('..')) return href; + // Sample data and screenshots are published with the site, so a link to them must not send + // the reader to GitHub for a file that is already served from this origin. + const inDocs = relative(DOCS, abs).split(sep).join('/'); + if (!inDocs.startsWith('..') && /^(examples|images)\//.test(inDocs)) return rel(pagePath, 'docs/' + inDocs) + frag; const isDir = existsSync(abs) && statSync(abs).isDirectory(); return `${GH}/${isDir ? 'tree' : 'blob'}/${BRANCH}/${r}${frag}`; }, @@ -630,7 +643,7 @@ function indexDoc(lang, k, title, html) { function docNav(lang, activeKey) { const t = T[lang], S = t.docs.sections; - const groupIcons = { 'getting-started': 'book', core: 'tree', domains: 'flask', 'advanced-setup': 'plug', reference: 'task', 'developer-docs': 'graph' }; + const groupIcons = { 'getting-started': 'book', core: 'tree', domains: 'flask', 'setup-reference': 'plug' }; const linkFor = (k, text, fromPath) => `${esc(text)}`; return (fromPath) => { return DOC_GROUPS.map(([group]) => { @@ -721,11 +734,15 @@ cpSync(join(HERE, 'src', 'media'), join(DIST, 'media'), { recursive: true }); mkdirSync(join(DIST, 'vendor', 'molstar'), { recursive: true }); for (const f of ['molstar.css', 'molstar.js']) cpSync(join(ROOT, 'node_modules', 'molstar', 'build', 'viewer', f), join(DIST, 'vendor', 'molstar', f)); cpSync(join(DOCS, 'images'), join(DIST, 'docs', 'images'), { recursive: true }); +// The walkthrough links the sample data it asks readers to upload, so it has to ship with the page. +if (existsSync(join(DOCS, 'examples'))) cpSync(join(DOCS, 'examples'), join(DIST, 'docs', 'examples'), { recursive: true }); write('favicon.svg', `${IC.brand}`); write('.nojekyll', ''); write('404.html', 'ScienceDiscovery'); const order = DOC_GROUPS.flatMap(([group]) => groupItems(group)); +// Each hidden group pages only against itself, so no pager link sends a reader into it. +const hiddenOrder = DOC_HIDDEN_GROUPS.flatMap((group) => groupItems(group)); let pages = 0; for (const lang of LANGS) { @@ -734,6 +751,7 @@ for (const lang of LANGS) { write(pathOf(lang, 'download/index.html'), legacyRedirect(lang, 'download/index.html', 'index.html', 'home'), false); write(pathOf(lang, 'docs/index.html'), docsHome(lang, order)); for (const k of order) { write(pathOf(lang, 'docs/' + outPath(k)), docPage(k, lang, order)); pages++; } + for (const k of hiddenOrder) { write(pathOf(lang, 'docs/' + outPath(k)), docPage(k, lang, hiddenOrder), false); pages++; } write(pathOf(lang, 'search-index.json'), JSON.stringify(INDEX[lang])); } diff --git a/site/src/site.css b/site/src/site.css index beb3c8f..58d402d 100644 --- a/site/src/site.css +++ b/site/src/site.css @@ -370,7 +370,9 @@ a.file:hover { border-color: var(--accent-border-soft); background: var(--accent .hidden { display: none !important; } /* ---------- docs ---------- */ -.docs { display: grid; grid-template-columns: 280px minmax(0, 1fr) 210px; max-width: 1400px; margin: 0 auto; align-items: start; } +/* The reader column is the point of this page, so the shell is wider than the marketing ones and + the two rails stay fixed: on a 1440px screen the article gets about 950px instead of 800px. */ +.docs { display: grid; grid-template-columns: 268px minmax(0, 1fr) 200px; max-width: 1680px; margin: 0 auto; align-items: start; } .docs-nav { position: sticky; top: var(--nav-h); height: calc(100vh - var(--nav-h)); overflow-y: auto; padding: 18px 12px 32px; border-right: 1px solid var(--border); background: var(--surface-subtle); } .docs-nav-group { margin: 4px 0; border: 1px solid transparent; border-radius: 12px; } .docs-nav-group[open] { border-color: var(--border); background: var(--surface); box-shadow: var(--shadow-1); } @@ -390,14 +392,14 @@ a.file:hover { border-color: var(--accent-border-soft); background: var(--accent .docs-nav-links a:hover { background: var(--surface-hover); color: var(--text-strong); text-decoration: none; } .docs-nav-links a.active { background: var(--accent-softer); color: var(--accent-deep); font-weight: 650; } .docs-nav-links a.active::before { position: absolute; top: 6px; bottom: 6px; left: -14px; width: 2px; border-radius: 2px; background: var(--accent); content: ''; } -.article { min-width: 0; padding: 48px 52px 24px; font-family: var(--serif); } +.article { min-width: 0; padding: 46px 44px 24px; font-family: var(--serif); } .article > *:first-child { margin-top: 0; } .article h1 { margin: 0 0 24px; color: var(--text-strong); font-size: clamp(32px, 3.1vw, 40px); line-height: 1.18; letter-spacing: -.045em; } .article h2 { margin: 48px 0 16px; padding-top: 16px; border-top: 1px solid var(--border); color: var(--text-strong); font-size: 25px; letter-spacing: -.035em; } .article h3 { margin: 32px 0 10px; color: var(--text-strong); font-size: 19px; letter-spacing: -.02em; } .article h4 { margin: 22px 0 6px; color: var(--text-heading); font-size: 15px; } .article p, .article li { color: var(--text); font-size: 16px; line-height: 1.78; } -.article > p, .article > ul, .article > ol, .article > blockquote { max-width: 76ch; } +.article > p, .article > ul, .article > ol, .article > blockquote { max-width: 96ch; } .article li { margin: 4px 0; } .article a { text-decoration: underline; text-decoration-color: var(--accent-border-soft); text-underline-offset: 2px; } .article a:hover { text-decoration-color: var(--accent-strong); }