openvibers/openvibe.domains Commits

/llms-full.txt (SEO-33): the site in full, from the same descriptor as llms.txt (#73)

OP OpenVibers committed 10 days ago · 04a209ccef · 2 files, +24 −2

It answered 404. The llms.txt descriptor becomes llmsSite(), and /llms-full.txt renders
it with seo.llmsFull: an About section (the summary and details), then every page
llms.txt lists with what it holds.

Changes

ddiff --git a/server/http/discovery.js b/server/http/discovery.js
iindex 39d01d0..f2c8616 100644
---- a/server/http/discovery.js
++++ b/server/http/discovery.js
@@@ -81,8 +81,8 @@ function createDiscoveryRoutes(ctx) {
res.type('application/xml').set('Cache-Control', TEXT_CACHE).send(seo.sitemapXml(urls));
});
-- r.get('/llms.txt', (_req, res) => {
-- res.type('text/plain').set('Cache-Control', TEXT_CACHE).send(seo.llmsTxt({
++ // The site as llms.txt describes it, shared by /llms.txt and /llms-full.txt (SEO-33).
++ const llmsSite = () => ({
name: SITE_NAME,
summary: 'OpenVibe.Domains is a stateless front over OpenVibe.Host\'s price catalog and OpenVibe.Tools\' public domain history: for a name, whether it is registered and every registrar\'s one-, three- and five-year totals; for an ending, every registrar\'s prices; for a domain, its public registration facts over time.',
details: 'There is no account, no database and no event stream. Every page is server-rendered and readable without JavaScript. USD is compared; other currencies are kept after it and marked. A renewal trap marks a cheap first year whose renewal is the real price.',
@@@ -106,6 +106,19 @@ function createDiscoveryRoutes(ctx) {
{ title: 'OpenVibe.Tools domain history', url: 'https://whois.openvibe.tools/', note: 'RDAP\'s public facts, kept over time' },
] },
],
++ });
++ r.get('/llms.txt', (_req, res) => {
++ res.type('text/plain').set('Cache-Control', TEXT_CACHE).send(seo.llmsTxt(llmsSite()));
++ });
++ // The same, in full (SEO-33): what the site is, then every page llms.txt lists with what it holds.
++ r.get('/llms-full.txt', (_req, res) => {
++ const d = llmsSite();
++ res.type('text/plain').set('Cache-Control', TEXT_CACHE).send(seo.llmsFull({
++ site: d.name, summary: d.summary, base: abs('/'),
++ sections: [
++ { title: 'About', pages: [{ title: d.name, url: abs('/'), text: [d.summary, d.details].filter(Boolean).join('\n\n') }] },
++ ...(d.sections || []).map((x) => ({ title: x.title, pages: (x.links || []).map((l) => ({ title: l.title, url: l.url, text: l.note || '' })) })),
++ ],
}));
});
ddiff --git a/test/routes.test.js b/test/routes.test.js
iindex cfe07e9..b5b2d46 100644
---- a/test/routes.test.js
++++ b/test/routes.test.js
@@@ -238,6 +238,15 @@ function stubs() {
assert.ok(r.text.includes('<lastmod>2026-10-28</lastmod>'));
});
++ await check('llms-full.txt (SEO-33): the site in full, from the same descriptor as llms.txt', async () => {
++ const r = await t.get('/llms-full.txt');
++ assert.strictEqual(r.status, 200);
++ assert.match(r.headers.get('content-type') || '', /^text\/plain/);
++ assert.ok(r.text.startsWith('# OpenVibe.Domains'), r.text.slice(0, 60));
++ assert.ok(r.text.length > 500, `${r.text.length} characters`);
++ assert.match(r.text, /## About\n\n### /);
++ });
++
await check('llms.txt describes the site and its API', async () => {
const r = await t.get('/llms.txt');
assert.strictEqual(r.status, 200);