openvibers/openvibe.report Commits
/design and /rundown have Markdown twins; llms.txt links them (#95)
Changes
@@@ -5,7 +5,8 @@// marks the pages that advertise a twin.const { normaliseDays } = require('./data/source');--const twinPath = (path) => /^\/(?:|stats|developers|ai|ai\/[^/]+|ai\/models\/[^/]+)$/.test(String(path || '/'));++// /design and /rundown since 11-03: llms.txt listed them as HTML pages with no twin.++const twinPath = (path) => /^\/(?:|stats|developers|design|rundown|ai|ai\/[^/]+|ai\/models\/[^/]+)$/.test(String(path || '/'));function createAgentPages({ publicPages, bench }) {async function renderPublicPage(path, { query } = {}) {@@@ -14,6 +15,8 @@ function createAgentPages({ publicPages, bench }) {const kind = /^\/ai\/([^/]+)$/.exec(path);if (path === '/') page = await publicPages.home();else if (path === '/developers') page = publicPages.developers();++ else if (path === '/design') page = publicPages.design();++ else if (path === '/rundown') page = await publicPages.rundown();else if (path === '/stats') page = await publicPages.stats(normaliseDays(query && query.get('days')));else if (path === '/ai') page = await publicPages.aiIndex();else if (model) page = await publicPages.aiModel(decodeURIComponent(model[1]));@@@ -79,8 +79,8 @@ function createDiscoveryRoutes({ config, live, bench }) {{ title: 'Start here', links: [{ title: 'OpenVibe.Report', url: abs('/'), note: 'the Report room' },{ title: 'Open numbers', url: abs('/stats'), note: 'page views, accounts and traffic for every OpenVibe site' },-- { title: 'Design health', url: abs('/design'), html: true, note: 'how closely each site follows the shared design kit, read from its code; per site at /design/<site>' },-- { title: 'The Rundown', url: abs('/rundown'), html: true, note: 'what streamers talked about, topic by topic' },++ { title: 'Design health', url: abs('/design'), note: 'how closely each site follows the shared design kit, read from its code; per site at /design/<site>' },++ { title: 'The Rundown', url: abs('/rundown'), note: 'what streamers talked about, topic by topic' },{ title: 'AI boards', url: abs('/ai'), note: 'Bench ratings, quality and cost across rooms' },] },// A JSON API is what an agent came for, not something to skip (AGT-5 review).@@@ -68,7 +68,14 @@ function createPublicPages({ network, live, bench, analytics = null }) {return { html: views.aiModel({ model, summary: await bench.modelSummary(model) }) };}-- return { home, stats, developers, aiIndex, aiBoard, aiModel };++ function design() { return { html: designViews.designHealth(designHealth.all()) }; }++++ async function rundown() {++ const [r, topics] = await Promise.all([live.rundown(), live.topics()]);++ return { html: views.rundown({ rundown: r, topics }) };++ }++++ return { home, stats, developers, design, rundown, aiIndex, aiBoard, aiModel };}function createPageRoutes(ctx) {@@@ -49,11 +49,19 @@ const STATUS_UPDATED = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'STfor (const link of ['https://openvibe.report/index.md','https://openvibe.report/stats.md',-- 'https://openvibe.report/rundown',++ 'https://openvibe.report/rundown.md',++ 'https://openvibe.report/design.md','https://openvibe.report/api/v1/stats?days=7','https://openvibe.report/sitemap.xml',]) assert.ok(r.text.includes(`(${link})`), `missing link ${link}`);assert.ok(r.text.includes('\n## Optional\n'), 'llms.txt has an Optional section');++ // 11-03: /design and /rundown have the twins llms.txt links, and their pages name them.++ for (const p of ['/design', '/rundown']) {++ const twin = await t.get(`${p}.md`);++ assert.strictEqual(twin.status, 200, `${p}.md`);++ assert.match(twin.headers.get('content-type') || '', /^text\/markdown/);++ assert.match((await t.get(p)).headers.get('link') || '', /text\/markdown/, `${p} names its twin`);++ }});await check('llms-full.txt (SEO-33): the site in full, every page llms.txt lists with what it holds', async () => {
@@ -5,7 +5,8 @@
@@ -5,7 +5,8 @@
// marks the pages that advertise a twin.
// marks the pages that advertise a twin.
const { normaliseDays } = require('./data/source');
const { normaliseDays } = require('./data/source');
-const twinPath = (path) => /^\/(?:|stats|developers|ai|ai\/[^/]+|ai\/models\/[^/]+)$/.test(String(path || '/'));
+// /design and /rundown since 11-03: llms.txt listed them as HTML pages with no twin.
+const twinPath = (path) => /^\/(?:|stats|developers|design|rundown|ai|ai\/[^/]+|ai\/models\/[^/]+)$/.test(String(path || '/'));
function createAgentPages({ publicPages, bench }) {
function createAgentPages({ publicPages, bench }) {
async function renderPublicPage(path, { query } = {}) {
async function renderPublicPage(path, { query } = {}) {
@@ -14,6 +15,8 @@ function createAgentPages({ publicPages, bench }) {
@@ -14,6 +15,8 @@ function createAgentPages({ publicPages, bench }) {
const kind = /^\/ai\/([^/]+)$/.exec(path);
const kind = /^\/ai\/([^/]+)$/.exec(path);
if (path === '/') page = await publicPages.home();
if (path === '/') page = await publicPages.home();
else if (path === '/developers') page = publicPages.developers();
else if (path === '/developers') page = publicPages.developers();
+ else if (path === '/design') page = publicPages.design();
+ else if (path === '/rundown') page = await publicPages.rundown();
else if (path === '/stats') page = await publicPages.stats(normaliseDays(query && query.get('days')));
else if (path === '/stats') page = await publicPages.stats(normaliseDays(query && query.get('days')));
else if (path === '/ai') page = await publicPages.aiIndex();
else if (path === '/ai') page = await publicPages.aiIndex();
else if (model) page = await publicPages.aiModel(decodeURIComponent(model[1]));
else if (model) page = await publicPages.aiModel(decodeURIComponent(model[1]));
@@ -79,8 +79,8 @@ function createDiscoveryRoutes({ config, live, bench }) {
@@ -79,8 +79,8 @@ function createDiscoveryRoutes({ config, live, bench }) {
{ title: 'Start here', links: [
{ title: 'Start here', links: [
{ title: 'OpenVibe.Report', url: abs('/'), note: 'the Report room' },
{ title: 'OpenVibe.Report', url: abs('/'), note: 'the Report room' },
{ title: 'Open numbers', url: abs('/stats'), note: 'page views, accounts and traffic for every OpenVibe site' },
{ title: 'Open numbers', url: abs('/stats'), note: 'page views, accounts and traffic for every OpenVibe site' },
- { title: 'Design health', url: abs('/design'), html: true, note: 'how closely each site follows the shared design kit, read from its code; per site at /design/<site>' },
- { title: 'The Rundown', url: abs('/rundown'), html: true, note: 'what streamers talked about, topic by topic' },
+ { title: 'Design health', url: abs('/design'), note: 'how closely each site follows the shared design kit, read from its code; per site at /design/<site>' },
+ { title: 'The Rundown', url: abs('/rundown'), note: 'what streamers talked about, topic by topic' },
{ title: 'AI boards', url: abs('/ai'), note: 'Bench ratings, quality and cost across rooms' },
{ title: 'AI boards', url: abs('/ai'), note: 'Bench ratings, quality and cost across rooms' },
] },
] },
// A JSON API is what an agent came for, not something to skip (AGT-5 review).
// A JSON API is what an agent came for, not something to skip (AGT-5 review).
@@ -68,7 +68,14 @@ function createPublicPages({ network, live, bench, analytics = null }) {
@@ -68,7 +68,14 @@ function createPublicPages({ network, live, bench, analytics = null }) {
return { html: views.aiModel({ model, summary: await bench.modelSummary(model) }) };
return { html: views.aiModel({ model, summary: await bench.modelSummary(model) }) };
}
}
- return { home, stats, developers, aiIndex, aiBoard, aiModel };
+ function design() { return { html: designViews.designHealth(designHealth.all()) }; }
+
+ async function rundown() {
+ const [r, topics] = await Promise.all([live.rundown(), live.topics()]);
+ return { html: views.rundown({ rundown: r, topics }) };
+ }
+
+ return { home, stats, developers, design, rundown, aiIndex, aiBoard, aiModel };
}
}
function createPageRoutes(ctx) {
function createPageRoutes(ctx) {
@@ -49,11 +49,19 @@ const STATUS_UPDATED = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ST
@@ -49,11 +49,19 @@ const STATUS_UPDATED = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ST
for (const link of [
for (const link of [
'https://openvibe.report/index.md',
'https://openvibe.report/index.md',
'https://openvibe.report/stats.md',
'https://openvibe.report/stats.md',
- 'https://openvibe.report/rundown',
+ 'https://openvibe.report/rundown.md',
+ 'https://openvibe.report/design.md',
'https://openvibe.report/api/v1/stats?days=7',
'https://openvibe.report/api/v1/stats?days=7',
'https://openvibe.report/sitemap.xml',
'https://openvibe.report/sitemap.xml',
]) assert.ok(r.text.includes(`(${link})`), `missing link ${link}`);
]) assert.ok(r.text.includes(`(${link})`), `missing link ${link}`);
assert.ok(r.text.includes('\n## Optional\n'), 'llms.txt has an Optional section');
assert.ok(r.text.includes('\n## Optional\n'), 'llms.txt has an Optional section');
+ // 11-03: /design and /rundown have the twins llms.txt links, and their pages name them.
+ for (const p of ['/design', '/rundown']) {
+ const twin = await t.get(`${p}.md`);
+ assert.strictEqual(twin.status, 200, `${p}.md`);
+ assert.match(twin.headers.get('content-type') || '', /^text\/markdown/);
+ assert.match((await t.get(p)).headers.get('link') || '', /text\/markdown/, `${p} names its twin`);
+ }
});
});
await check('llms-full.txt (SEO-33): the site in full, every page llms.txt lists with what it holds', async () => {
await check('llms-full.txt (SEO-33): the site in full, every page llms.txt lists with what it holds', async () => {