Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions server/tests/public-a11y.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import assert from "node:assert/strict";
import test from "node:test";
import { createApp } from "../src/app.js";
import { fixtureDatabase, root } from "./helpers.js";

const publicPages = ["/", "/privacy", "/support", "/terms", "/apple-music-soundtrack", "/private-driving-journal"];

test("public pages expose a skip link, 24px tap targets, and contrast overlay CSS", async () => {
const fixture = fixtureDatabase();
const runtime = await createApp({ databasePath: fixture.filename, root, allowTestAuth: true, legacyUpstream: "", mode: "web" });
try {
const css = await runtime.app.inject({ method: "GET", url: "/public-a11y.css?v=2" });
assert.equal(css.statusCode, 200, css.body);
assert.match(String(css.headers["content-type"]), /text\/css/);
assert.equal(css.headers["cache-control"], "public, max-age=31536000, immutable");
assert.match(css.body, /\.skip-link/);
assert.match(css.body, /min-height: 24px/);
assert.match(css.body, /min-width: 24px/);
assert.match(css.body, /flex-wrap: nowrap/);
assert.match(css.body, /#081832cc/);
assert.match(css.body, /#081832b3/);
assert.doesNotMatch(css.body, /#081832f8|#081832f4|#081832e8/);
assert.doesNotMatch(css.body, /[\u2013\u2014]/);

for (const url of publicPages) {
const page = await runtime.app.inject({ method: "GET", url });
assert.equal(page.statusCode, 200, url);
assert.match(page.body, /class="skip-link" href="#main">Skip to content<\/a>/, url);
assert.match(page.body, /id="main"/, url);
assert.match(page.body, /href="\/public-a11y\.css\?v=2"/, url);
assert.match(String(page.headers["content-security-policy"]), /default-src 'self'/, url);
}

const missing = await runtime.app.inject({ method: "GET", url: "/missing-public-page" });
assert.equal(missing.statusCode, 404);
assert.match(missing.body, /class="skip-link" href="#main">Skip to content<\/a>/);
assert.match(missing.body, /href="\/public-a11y\.css\?v=2"/);
} finally {
await runtime.app.close();
fixture.cleanup();
}
});
4 changes: 3 additions & 1 deletion web/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=grand-tour-3">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<title>Page Not Found — JourneyDeck</title>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/#experience">The experience</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#medallions">Medallions</a><a href="/#get-started">Get started</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/#experience">The experience</a><a href="/#replay">Route replay</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#memories">Memories &amp; sharing</a><a href="/#membership">Free &amp; Plus</a><a href="/support">Support</a><a href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer">Follow @JourneyDeck on X</a></nav></details><a class="social-link" href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer" aria-label="Follow @JourneyDeck on X"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117Z"/></svg></a><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page error-page">
<main id="main" class="page error-page">
<section class="hero error-hero">
<p class="eyebrow">Route not found · 404</p>
<h1>That road isn’t on the map.</h1>
Expand Down
4 changes: 3 additions & 1 deletion web/apple-music-soundtrack.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=hero-lcp-1">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<link rel="stylesheet" href="/soundtrack-v2.css?v=1">
<link rel="preload" as="image" href="/assets/beta/grand-touring-home-800.webp?v=1" imagesrcset="/assets/beta/grand-touring-home-800.webp?v=1 800w, /assets/beta/grand-touring-home-1600.webp?v=1 1600w" imagesizes="(max-width: 620px) calc(100vw - 28px), 940px">
<title>Record iPhone drives with optional Apple Music | JourneyDeck</title>
Expand Down Expand Up @@ -64,12 +65,13 @@
<script type="module" src="/campaign.js?v=4"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/#experience">The experience</a><a href="/apple-music-soundtrack" aria-current="page">Soundtracks</a><a href="/#medallions">Medallions</a><a href="/#get-started">Get started</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/#experience">The experience</a><a href="/#replay">Route replay</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#memories">Memories &amp; sharing</a><a href="/#membership">Free &amp; Plus</a><a href="/support">Support</a><a href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer">Follow @JourneyDeck on X</a></nav></details><a class="social-link" href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer" aria-label="Follow @JourneyDeck on X"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117Z"/></svg></a><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page">
<main id="main" class="page">
<section class="hero has-photo">
<img class="hero-photo" src="/assets/beta/grand-touring-home-800.webp?v=1" srcset="/assets/beta/grand-touring-home-800.webp?v=1 800w, /assets/beta/grand-touring-home-1600.webp?v=1 1600w" sizes="(max-width: 620px) calc(100vw - 28px), 940px" width="1536" height="1024" alt="" fetchpriority="high" decoding="async">
<p class="eyebrow">Your drive, your music</p>
Expand Down
1 change: 1 addition & 0 deletions web/beta.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<link rel="stylesheet" href="/beta.css?v=grand-tour-4">
<link rel="stylesheet" href="/v2-features.css?v=1">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<link rel="preload" as="image" href="/assets/v4/01-today-400.webp?v=1" imagesrcset="/assets/v4/01-today-400.webp?v=1 400w, /assets/v4/01-today.webp?v=1 660w" imagesizes="(max-width: 800px) 228px, 237px">
<script defer src="https://cloud.umami.is/script.js" data-website-id="a5f66e11-ec7d-4133-8e1a-f8e6c08593af" data-domains="journeydeck.me"></script>
<script type="module" src="/campaign.js?v=4"></script>
Expand Down
4 changes: 3 additions & 1 deletion web/privacy.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=grand-tour-3">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<title>JourneyDeck Privacy Policy</title>
<script defer src="https://cloud.umami.is/script.js" data-website-id="a5f66e11-ec7d-4133-8e1a-f8e6c08593af" data-domains="journeydeck.me"></script>
<script type="module" src="/campaign.js?v=4"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/#experience">The experience</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#medallions">Medallions</a><a href="/#get-started">Get started</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/#experience">The experience</a><a href="/#replay">Route replay</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#memories">Memories &amp; sharing</a><a href="/#membership">Free &amp; Plus</a><a href="/support">Support</a><a href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer">Follow @JourneyDeck on X</a></nav></details><a class="social-link" href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer" aria-label="Follow @JourneyDeck on X"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117Z"/></svg></a><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page">
<main id="main" class="page">
<section class="hero">
<p class="eyebrow">Your data, your journey</p>
<h1>Privacy Policy</h1>
Expand Down
4 changes: 3 additions & 1 deletion web/private-driving-journal.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=hero-lcp-1">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<link rel="preload" as="image" href="/assets/beta/grand-touring-home-800.webp?v=1" imagesrcset="/assets/beta/grand-touring-home-800.webp?v=1 800w, /assets/beta/grand-touring-home-1600.webp?v=1 1600w" imagesizes="(max-width: 620px) calc(100vw - 28px), 940px">
<title>Private driving journal for iPhone | JourneyDeck</title>
<script type="application/ld+json">
Expand Down Expand Up @@ -71,12 +72,13 @@
<script type="module" src="/campaign.js?v=4"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/">Home</a><a href="/private-driving-journal" aria-current="page">Driving journal</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/privacy">Privacy</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/private-driving-journal" aria-current="page">Driving journal</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/privacy">Privacy</a><a href="/support">Support</a></nav></details><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page">
<main id="main" class="page">
<section class="hero has-photo">
<img class="hero-photo" src="/assets/beta/grand-touring-home-800.webp?v=1" srcset="/assets/beta/grand-touring-home-800.webp?v=1 800w, /assets/beta/grand-touring-home-1600.webp?v=1 1600w" sizes="(max-width: 620px) calc(100vw - 28px), 940px" width="1536" height="1024" alt="" fetchpriority="high" decoding="async">
<p class="eyebrow">YOUR ROADS, YOUR ARCHIVE</p>
Expand Down
36 changes: 36 additions & 0 deletions web/public-a11y.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.skip-link { position: fixed; z-index: 100; top: 8px; left: 8px; transform: translateY(-150%); min-height: 44px; padding: 12px 16px; border-radius: 7px; background: var(--ivory, #f6f0e2); color: var(--navy, #081832); font-size: 14px; font-weight: 650; text-decoration: none; }
.skip-link:focus { transform: none; }
.site-header, .header-actions { flex-wrap: nowrap; }
.site-header .brand { white-space: nowrap; }
.header-actions .button { white-space: nowrap; flex-shrink: 0; }
.desktop-nav a { display: inline-flex; align-items: center; min-height: 24px; padding: 6px 2px; }
.footer a, .footer-bottom a { display: inline-flex; align-items: center; min-height: 24px; padding: 4px 2px; }
.page-actions { gap: 16px; }
.contact, .secondary-action { min-height: 52px; }
.tour-dots button { min-width: 24px; width: 24px; }
.text-link, .hero-soundtrack-link, .feature-cta, .hero-baseline a { min-height: 24px; }
section.hero {
background: linear-gradient(90deg, #081832cc 0%, #081832cc 58%, #081832b3 78%, #08183280 100%), url("/assets/beta/grand-touring-home.webp") center 55% / cover;
Comment on lines +12 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit the overlay rule to public-page heroes

Because beta.html now imports this stylesheet and the / front cover is also a <section class="hero section-shell">, this selector unintentionally applies the forest background to the entire home-page hero. That changes the existing plain cover design and eagerly downloads the 322 KB full-size image, even though the homepage previously used responsive, lazy-loaded variants only in its later scenic section. Scope these background rules to the public-page hero variant while retaining the shared header and tap-target fixes on /.

Useful? React with 👍 / 👎.

}
section.hero:not(.has-photo)::before { content: none; }
section.hero.has-photo::before {
content: "";
position: absolute;
z-index: 1;
inset: 0;
background: linear-gradient(90deg, #081832cc 0%, #081832cc 58%, #081832b3 78%, #08183280 100%);
pointer-events: none;
}
.hero > :not(.hero-photo) { position: relative; z-index: 2; }
@media (max-width: 620px) {
section.hero {
background: linear-gradient(90deg, #081832cc, #081832c6), url("/assets/beta/grand-touring-home.webp") center / cover;
}
section.hero.has-photo::before { background: linear-gradient(90deg, #081832cc, #081832c6); }
}
@media (max-width: 390px) {
.site-header { gap: 8px; padding-inline: 12px; flex-wrap: nowrap; }
.header-actions { gap: 6px; flex-wrap: nowrap; }
.header-actions .button-small { gap: 6px; padding-inline: 10px; white-space: nowrap; }
.brand { font-size: 17px; }
}
4 changes: 3 additions & 1 deletion web/support.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=grand-tour-3">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<title>JourneyDeck Support</title>
<script type="application/ld+json">
{
Expand Down Expand Up @@ -102,12 +103,13 @@
<script type="module" src="/campaign.js?v=4"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/#experience">The experience</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#medallions">Medallions</a><a href="/#get-started">Get started</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/#experience">The experience</a><a href="/#replay">Route replay</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#memories">Memories &amp; sharing</a><a href="/#membership">Free &amp; Plus</a><a href="/support">Support</a><a href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer">Follow @JourneyDeck on X</a></nav></details><a class="social-link" href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer" aria-label="Follow @JourneyDeck on X"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117Z"/></svg></a><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page">
<main id="main" class="page">
<section class="hero">
<p class="eyebrow">Here to help</p>
<h1>JourneyDeck Support</h1>
Expand Down
4 changes: 3 additions & 1 deletion web/terms.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@
<link rel="apple-touch-icon" href="/assets/journeydeck-cinematic-180.png">
<link rel="stylesheet" href="/public-page.css?v=grand-tour-3">
<link rel="stylesheet" href="/site-mobile-nav.css?v=1">
<link rel="stylesheet" href="/public-a11y.css?v=2">
<title>JourneyDeck Terms of Use</title>
<script defer src="https://cloud.umami.is/script.js" data-website-id="a5f66e11-ec7d-4133-8e1a-f8e6c08593af" data-domains="journeydeck.me"></script>
<script type="module" src="/campaign.js?v=4"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<a class="brand" href="/" aria-label="JourneyDeck home"><img src="/assets/beta/journeydeck-pulse.svg" width="36" height="36" alt=""><span>Journey<span class="gold">Deck</span></span></a>
<nav class="desktop-nav" aria-label="Main navigation"><a href="/#experience">The experience</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#medallions">Medallions</a><a href="/#get-started">Get started</a></nav>
<div class="header-actions"><details class="mobile-menu"><summary><span aria-hidden="true">☰</span> Menu</summary><nav aria-label="Mobile navigation"><a href="/">Home</a><a href="/#experience">The experience</a><a href="/#replay">Route replay</a><a href="/apple-music-soundtrack">Soundtracks</a><a href="/#memories">Memories &amp; sharing</a><a href="/#membership">Free &amp; Plus</a><a href="/support">Support</a><a href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer">Follow @JourneyDeck on X</a></nav></details><a class="social-link" href="https://x.com/JourneyDeck" target="_blank" rel="noopener noreferrer" aria-label="Follow @JourneyDeck on X"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117Z"/></svg></a><a class="button button-small" href="https://apps.apple.com/us/app/journeydeck/id6806502526">Get the app <span aria-hidden="true">↗</span></a></div>
</header>
<main class="page">
<main id="main" class="page">
<section class="hero">
<p class="eyebrow">The rules of the road</p>
<h1>Terms of Use</h1>
Expand Down