openvibers/openvibe.run Commits

Web app manifest: its icons are the shared set this site serves (/shared/icons), not /assets/logo-*.png (all six install icons were 404); pages add the apple-touch-icon (#58)

OP OpenVibers committed 27 days ago · 40577a5414 · 3 files, +9 −3

Changes

ddiff --git a/server/app.js b/server/app.js
iindex c2d92d9..6d723ca 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -128,7 +128,12 @@ function createApp(opts = {}) {
app.get('/robots.txt', (req, res) => res.type('text/plain').send(['User-agent: *', 'Allow: /$', 'Disallow: /api/', 'Disallow: /internal/', `Sitemap: ${config.baseUrl}/sitemap.xml`, ''].join('\n')));
app.get('/sitemap.xml', (req, res) => res.type('application/xml').send(require('openvibe-shared/seo').sitemapXml(discovery.PAGES.map((p) => ({ loc: `${config.baseUrl}${p}` })))));
app.get('/favicon.ico', (req, res) => res.type('image/svg+xml').set('Cache-Control', 'public, max-age=86400').send(appIcon.favicon({ site: 'run' })));
-- app.get('/manifest.webmanifest', (req, res) => res.type('application/manifest+json').send(JSON.stringify(appIcon.manifest({ site: 'run', name: home.SITE_NAME, shortName: 'Run', description: home.DESCRIPTION, startUrl: '/' }))));
++ // The web app manifest. Its icons are the shared set (openvibe-shared/app-icons, under /shared/icons): it named
++ // /assets/logo-*.png, which this site never served (every install icon was a 404 until 2026-10-17).
++ app.get('/manifest.webmanifest', (req, res) => res.type('application/manifest+json').send(JSON.stringify({
++ ...appIcon.manifest({ site: 'run', name: home.SITE_NAME, shortName: 'Run', description: home.DESCRIPTION, startUrl: '/' }),
++ icons: [192, 512].flatMap((s) => [false, true].map((maskable) => ({ src: require('openvibe-shared/app-icons').url('run', s, { maskable }), sizes: `${s}x${s}`, type: 'image/png', purpose: maskable ? 'maskable' : 'any' }))),
++ })));
app.use((req, res) => {
if (req.path.startsWith('/api/') || req.path.startsWith('/internal/')) return http.sendProblem(res, 404, 'not_found', { ctx: req.ov });
ddiff --git a/server/web/home.js b/server/web/home.js
iindex 837da6f..2c15c89 100644
---- a/server/web/home.js
++++ b/server/web/home.js
@@@ -57,7 +57,7 @@ function renderHome({ config }) {
canonical: `${config.baseUrl}/`, robots: 'index, follow',
navbar: nav, footer: FOOTER, home: '/',
navLinks: nav.links,
-- head: [appIcon.headTags({ site: 'run' }), '<link rel="manifest" href="/manifest.webmanifest">', `<link rel="stylesheet" href="${ovServe.url(showcase.STYLESHEET)}">`].join('\n'),
++ head: [appIcon.headTags({ site: 'run' }), '<link rel="manifest" href="/manifest.webmanifest">', `<link rel="apple-touch-icon" href="${require('openvibe-shared/app-icons').url('run', 192)}">`, `<link rel="stylesheet" href="${ovServe.url(showcase.STYLESHEET)}">`].join('\n'),
body: `<div id="navbar-mount"></div>\n<main id="main">${body()}</main>`,
});
}
@@@ -74,7 +74,7 @@ function renderUpdates({ config }) {
canonical: `${config.baseUrl}/updates`, robots: 'index, follow',
navbar: { service: 'run', apiBase: NETWORK_URL, links, history: { type: 'page', title: SITE_NAME } },
footer: FOOTER, home: '/', navLinks: links,
-- head: [appIcon.headTags({ site: 'run' }), '<link rel="manifest" href="/manifest.webmanifest">'].join('\n'),
++ head: [appIcon.headTags({ site: 'run' }), '<link rel="manifest" href="/manifest.webmanifest">', `<link rel="apple-touch-icon" href="${require('openvibe-shared/app-icons').url('run', 192)}">`].join('\n'),
body: `<div id="navbar-mount"></div>\n<main id="main" class="page">\n${frame.updatesBody({ service: 'run', siteName: SITE_NAME })}\n</main>\n<script src="${ovServe.url('shipped.js')}" defer></script>`,
});
}
ddiff --git a/test/site.test.js b/test/site.test.js
iindex b2f725d..e672a8a 100644
---- a/test/site.test.js
++++ b/test/site.test.js
@@@ -36,6 +36,7 @@ const { boot, check, done } = require('./helpers/app');
assert.match((await t.call('GET', '/favicon.ico', { token: null })).headers.get('content-type'), /image\/svg\+xml/);
const manifest = JSON.parse((await t.call('GET', '/manifest.webmanifest', { token: null })).text);
assert.strictEqual(manifest.name, 'OpenVibe.Run');
++ assert.ok(manifest.icons.length === 4 && manifest.icons.every((i) => /^\/shared\/icons\/[a-z0-9-]+-(maskable-)?(192|512)\.png\?v=/.test(i.src)), 'the shared icon set, which the site serves');
});
await check('/updates: the shared update log in the Frame, one heading, in the sitemap', async () => {
const r = await t.call('GET', '/updates', { token: null });