openvibers/openvibe.games Commits
Games: the game page says what it is without JavaScript (both games, what they need, links) (#63)
Changes
@@@ -72,6 +72,30 @@folds away and a small floating button brings it back — see frame.js.--><div id="navbar-mount"></div>++ <noscript>++ <!-- What the page is, for a visitor without JavaScript and for crawlers: the games themselves need it. -->++ <main style="max-width: 46rem; margin: 2rem auto; padding: 0 1rem; color: #e6edf7; font: 16px/1.6 system-ui, sans-serif">++ <h1>Scraplandia and Salvage Rush</h1>++ <p>++ <strong>Scraplandia</strong> is scrappy multiplayer survival-building in and around Scrap City: physgun++ anything, weld it to anything else, cook at a burn barrel, chase supply drops in the wilds and haul your++ salvage home before another scrapper takes it. Every valuable you extract scores haul points on the week's++ board.++ </p>++ <p>++ <strong>Salvage Rush</strong> is its quick cousin: collect scrap around a compact arena in 90-second rounds,++ scored by the server, with a public leaderboard.++ </p>++ <p>++ Both run in your browser with no download, as a guest or with your OpenVibe account. They need JavaScript and++ WebGL: turn JavaScript on to play.++ </p>++ <p>++ <a href="https://openvibe.games/" style="color: #8ab4ff">All games</a> ·++ <a href="https://openvibe.games/leaderboard.html" style="color: #8ab4ff">Leaderboards</a>++ </p>++ </main>++ </noscript><div id="stage"><canvas id="game"></canvas><div id="ui"></div>nnew file mode 100644@@@ -0,0 +1,24 @@++/**++ * The game page says what it is without JavaScript. Its body is a canvas the client draws into, so a visitor with++ * JavaScript off, and a crawler, read nothing but the title (the all-sites link sweep, 2026-10-14): the <noscript>++ * block names both games, says what they need and links the network's game pages.++ */++import { readFileSync } from 'node:fs'++import { fileURLToPath } from 'node:url'++import { describe, expect, it } from 'vitest'++++const html = readFileSync(fileURLToPath(new URL('../../play.html', import.meta.url)), 'utf8')++const noscript = html.slice(html.indexOf('<noscript>'), html.indexOf('</noscript>'))++++describe('play.html without JavaScript', () => {++ it('describes both games and what they need', () => {++ expect(noscript).toContain('<h1>Scraplandia and Salvage Rush</h1>')++ expect(noscript).toMatch(/need JavaScript and\s+WebGL/)++ expect(noscript).toContain('href="https://openvibe.games/leaderboard.html"')++ })++++ it('sits before the stage, inside the body', () => {++ expect(html.indexOf('<noscript>')).toBeGreaterThan(html.indexOf('<body>'))++ expect(html.indexOf('<noscript>')).toBeLessThan(html.indexOf('<div id="stage">'))++ })++})nnew file mode 100644@@@ -0,0 +1,3 @@++// file: 'apps/client/src/pages/playNoscript.test.ts'++// covers: 'apps/client/src/pages'++// Generated by node test/run.js --index; do not edit.
@@ -72,6 +72,30 @@
@@ -72,6 +72,30 @@
folds away and a small floating button brings it back — see frame.js.
folds away and a small floating button brings it back — see frame.js.
-->
-->
<div id="navbar-mount"></div>
<div id="navbar-mount"></div>
+ <noscript>
+ <!-- What the page is, for a visitor without JavaScript and for crawlers: the games themselves need it. -->
+ <main style="max-width: 46rem; margin: 2rem auto; padding: 0 1rem; color: #e6edf7; font: 16px/1.6 system-ui, sans-serif">
+ <h1>Scraplandia and Salvage Rush</h1>
+ <p>
+ <strong>Scraplandia</strong> is scrappy multiplayer survival-building in and around Scrap City: physgun
+ anything, weld it to anything else, cook at a burn barrel, chase supply drops in the wilds and haul your
+ salvage home before another scrapper takes it. Every valuable you extract scores haul points on the week's
+ board.
+ </p>
+ <p>
+ <strong>Salvage Rush</strong> is its quick cousin: collect scrap around a compact arena in 90-second rounds,
+ scored by the server, with a public leaderboard.
+ </p>
+ <p>
+ Both run in your browser with no download, as a guest or with your OpenVibe account. They need JavaScript and
+ WebGL: turn JavaScript on to play.
+ </p>
+ <p>
+ <a href="https://openvibe.games/" style="color: #8ab4ff">All games</a> ·
+ <a href="https://openvibe.games/leaderboard.html" style="color: #8ab4ff">Leaderboards</a>
+ </p>
+ </main>
+ </noscript>
<div id="stage">
<div id="stage">
<canvas id="game"></canvas>
<canvas id="game"></canvas>
<div id="ui"></div>
<div id="ui"></div>
new file mode 100644
new file mode 100644
@@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
+/**
+ * The game page says what it is without JavaScript. Its body is a canvas the client draws into, so a visitor with
+ * JavaScript off, and a crawler, read nothing but the title (the all-sites link sweep, 2026-10-14): the <noscript>
+ * block names both games, says what they need and links the network's game pages.
+ */
+import { readFileSync } from 'node:fs'
+import { fileURLToPath } from 'node:url'
+import { describe, expect, it } from 'vitest'
+
+const html = readFileSync(fileURLToPath(new URL('../../play.html', import.meta.url)), 'utf8')
+const noscript = html.slice(html.indexOf('<noscript>'), html.indexOf('</noscript>'))
+
+describe('play.html without JavaScript', () => {
+ it('describes both games and what they need', () => {
+ expect(noscript).toContain('<h1>Scraplandia and Salvage Rush</h1>')
+ expect(noscript).toMatch(/need JavaScript and\s+WebGL/)
+ expect(noscript).toContain('href="https://openvibe.games/leaderboard.html"')
+ })
+
+ it('sits before the stage, inside the body', () => {
+ expect(html.indexOf('<noscript>')).toBeGreaterThan(html.indexOf('<body>'))
+ expect(html.indexOf('<noscript>')).toBeLessThan(html.indexOf('<div id="stage">'))
+ })
+})
new file mode 100644
new file mode 100644
@@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
+// file: 'apps/client/src/pages/playNoscript.test.ts'
+// covers: 'apps/client/src/pages'
+// Generated by node test/run.js --index; do not edit.