A way back out, and the tags a crawler reads

Two things a game served from a subdirectory of somebody's site ought to have
and this did not: a way back up to the site, and enough in its head for that
relationship to be legible to something that is not a person.

The way back sits leftmost in the footer, next to SOURCE, because that row is
already where the chrome lives and leftmost is where a way back belongs. The
arrow is a pseudo-element rather than part of the label so it can be the right
arrow for the machine you are looking at: a chevron under the lamp, and the two
ASCII characters a Teletype could actually strike on the paper skin.

It is an absolute URL rather than "/". This game is served from a subdirectory
in production and from the root in development, so the relative answer is right
in one of those and points at the game itself in the other. The source link
beside it has always worked this way for the same reason.

The head gains the usual set -- canonical, Open Graph, Twitter, robots -- plus
two pieces of structured data. VideoGame says what this is, that it is free,
and that one to four people can play it. BreadcrumbList says the same three
steps the footer link offers: this game sits under the games site, which sits
under jcoffey.dev.

Canonical earns its place rather than being boilerplate. The container serving
this falls back to index.html for any path under /wumpus/, which is right for
the app and wrong for a crawler -- without it, /wumpus/anything-at-all is a
separate indexable page with identical content.

The preview image is served by the site rather than carried here. There is no
artwork file in this repository and there is not going to be one; a social card
is not part of the game, and it sits with the deployment, which is where the
canonical URL points anyway.

A noscript block describes the game and offers the way onwards, so a reader
without scripts and a crawler that does not run them get something better than
an empty div.

38 tests. Build clean.
This commit is contained in:
2026-09-08 22:51:57 -07:00
parent 6485f9b161
commit 2b5649ffa5
3 changed files with 162 additions and 4 deletions
+14
View File
@@ -635,6 +635,20 @@ html[data-skin='modern'] .btn:active:not(:disabled) {
font-size: 12px;
}
/*
* The way back. The arrow is a pseudo-element rather than part of the label so
* that it can be the right arrow for the machine you are looking at: a chevron
* under the lamp, and the two ASCII characters a Teletype could actually
* strike on the paper skin.
*/
.controls .back::before {
content: '\2039\00a0';
}
:root:not([data-skin='modern']) .controls .back::before {
content: '<-\00a0';
}
.seed {
margin-left: auto;
opacity: 0.7;
+19
View File
@@ -35,6 +35,17 @@ import './App.css'
*/
const SOURCE_URL = 'https://github.com/Coffey-Labs/wumpus'
/**
* The way back out.
*
* Absolute rather than `/`, because this game is served from a subdirectory in
* production and from the root in development -- so the relative answer is
* right in one of those and points at the game itself in the other. The
* destination is a particular site, and naming it is the honest way to say so.
* The source link next to it works the same way for the same reason.
*/
const GAMES_URL = 'https://games.jcoffey.dev/'
export default function App() {
const [seed] = useState(randomSeed)
const [state, dispatch] = useReducer(reducer, seed, initialState)
@@ -224,6 +235,14 @@ export default function App() {
<Frame
footer={
<div className="controls">
{/* Leftmost, because that is where a way back belongs. */}
<a
className="btn btn-ghost back"
href={GAMES_URL}
title="The rest of the games"
>
GAMES
</a>
<Btn
kind="ghost"
onClick={() => {