openvibers/openvibe.chat Commits

SEO-19: a server page canonicals to the URL served and listed in the sitemap (#243)

OP OpenVibers committed 16 days ago · 83b32d4054 · 2 files, +10 −2

The page at /s/<server> named the channel it defaults to (/s/openvibe/general) as its canonical, while the sitemap lists /s/<server>. An explicit channel URL stays canonical to itself.

Changes

ddiff --git a/server/web/server-pages.js b/server/web/server-pages.js
iindex fa9d84a..6bcd379 100644
---- a/server/web/server-pages.js
++++ b/server/web/server-pages.js
@@@ -136,8 +136,12 @@ ${create}`,
can.member && can.role !== 'owner' ? `<form class="oc-inline" method="post" action="/s/${esc(server.slug)}/leave"><button type="submit" class="oc-link">Leave server</button></form>` : '',
].filter(Boolean).join(' · ');
const canInvite = can.manage || (can.moderate && server.visibility === 'public');
++ // The canonical URL is the one served and listed in the sitemap: /s/<server> without a channel in the
++ // request, and the channel's own URL when the request named it. `back` stays the channel URL the composer
++ // and the sign-in link post to (POST /s/:slug/:channel).
++ const canonicalPath = req.params.channel ? back : `/s/${server.slug}`;
await page(req, res, 200, {
-- actor, wide: true, footer: 'compact', title: `${isVoice ? '' : '#'}${room.name} · ${server.name}`, path: back, active: 'servers',
++ actor, wide: true, footer: 'compact', title: `${isVoice ? '' : '#'}${room.name} · ${server.name}`, path: canonicalPath, active: 'servers',
robots: server.visibility === 'public' ? 'index, follow' : 'noindex, nofollow', script: true, callScript: callReady,
description: server.description || `${server.name}, a server on OpenVibe.Chat with ${server.member_count} member${Number(server.member_count) === 1 ? '' : 's'}.`,
page: {
ddiff --git a/test/servers.test.js b/test/servers.test.js
iindex e1772de..34b2b7f 100644
---- a/test/servers.test.js
++++ b/test/servers.test.js
@@@ -231,7 +231,11 @@ t('the official server: only chat staff take /s/openvibe; it is marked official
assert.ok(list.slice(1).every((x) => x.official === false), 'no other server is official');
assert.strictEqual((await api('POST', '/', staff, { name: 'Explore', slug: 'explore' })).status, 422, 'the other reserved words stay reserved, even for staff');
assert.match((await page('/servers', null)).text, /<strong>OpenVibe<\/strong><span class="oc-badge oc-badge-official">official<\/span>/);
-- assert.match((await page('/s/openvibe', null)).text, /oc-srv-name">OpenVibe<\/h1><span class="oc-badge oc-badge-official">official<\/span>/);
++ const official = (await page('/s/openvibe', null)).text;
++ assert.match(official, /oc-srv-name">OpenVibe<\/h1><span class="oc-badge oc-badge-official">official<\/span>/);
++ const canonical = (/<link rel="canonical" href="([^"]*)"/.exec(official) || [])[1] || '';
++ assert.match(canonical, /\/s\/openvibe$/, 'canonical is the URL served and listed in the sitemap, not the default channel');
++ assert.ok(!canonical.includes('/s/openvibe/general'), 'no canonical to the channel the server happens to default to');
});
t.run(async () => { if (h && h.close) await h.close(); });