Skip to content

SEO, structured data, accessibility and custom domain - #11

Merged
LucaGerlich merged 1 commit into
mainfrom
feat/seo
Aug 18, 2026
Merged

SEO, structured data, accessibility and custom domain#11
LucaGerlich merged 1 commit into
mainfrom
feat/seo

Conversation

@LucaGerlich

Copy link
Copy Markdown
Owner

Applies the technical SEO audit, fixes two real accessibility defects, and moves the site to inputpilot.lucagerlich.dev.

⚠️ Merge order matters

This PR contains docs/CNAME. GitHub Pages switches to the custom domain the moment it deploys, and redirects the old github.io URL there. Add the DNS record before merging, or the site is unreachable in the gap:

Type Host Value
CNAME inputpilot lucagerlich.github.io.

There is a wildcard *.lucagerlich.dev → 46.62.169.116 (Hetzner) today, so the subdomain currently resolves to your server; an explicit CNAME takes precedence over the wildcard.

Search

Title and description now contain the terms people search — the page never previously said "automatically" or "external" about itself. Adds canonical, robots directives, sitemap.xml, .nojekyll, and JSON-LD (SoftwareApplication, SoftwareSourceCode, Person, WebSite, FAQPage). No aggregateRating: there are no reviews, and fabricating them risks a manual action. The 7 FAQ entries in schema match the 7 visible on the page verbatim, as Google requires.

Two new FAQ answers target queries a landing page cannot otherwise reach: the German-keyboard-on-a-US-MacBook case, and how this differs from autokbisw and Input Source Pro — comparison searches convert far better than generic ones.

Accessibility — two genuine defects

  • Both ASCII boards carried aria-label on a bare <pre>. ARIA prohibits labelling a roleless element, so the label was silently dropped and screen readers read ~2,600 punctuation characters aloud. role="img" makes the label authoritative and replaces the subtree.
  • Decorative CSS content (# , [+], ) was being announced as "number sign", "left bracket plus". Now paired with empty alt text.
  • The h1's text content read keyboard.Not the app with no space.

Verified

JSON-LD parses and validates; schema FAQ count matches visible count; no stale github.io URLs remain.

One audit finding I rejected

The audit reported that appcast.xml still advertises 1.0.0, which would mean 1.0.0 users never get updates. I checked the live feed and the local file: both correctly say 1.0.1, build 2. The agent read a stale copy — no change made.

Search:
- title and description now carry the words people actually search
  ('automatic keyboard layout switching for macOS'); the page previously
  never said 'automatically' or 'external' about itself
- canonical link, robots directives, sitemap.xml, .nojekyll
- JSON-LD: SoftwareApplication, SoftwareSourceCode, Person, WebSite and
  FAQPage. No aggregateRating - there are no reviews yet and inventing them
  is a manual-action risk. The 7 schema FAQ entries match the 7 visible on
  the page verbatim, which Google requires
- two new FAQ answers targeting the queries a landing page cannot otherwise
  reach: the German-keyboard-on-a-US-MacBook case, and how this differs from
  autokbisw and Input Source Pro

Accessibility (real defects, not nits):
- both ASCII boards had aria-label on a bare <pre>. ARIA prohibits labelling
  a roleless element, so the label was dropped and screen readers read ~2600
  punctuation characters aloud instead. Adding role='img' makes the label
  authoritative and replaces the subtree
- decorative CSS content ('# ', '[+]', '>') was being announced; now paired
  with empty alt text
- the h1 rendered as 'keyboard.Not the app' with no space in its text content
- header and main landmarks

Housekeeping: the art generators were being served as web content from
docs/; moved to Scripts/ alongside release.sh.

Custom domain inputpilot.lucagerlich.dev: CNAME file plus all 14 absolute
URLs rewritten across index.html, sitemap.xml and robots.txt.
Copilot AI lite review requested due to automatic review settings August 18, 2026 21:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the GitHub Pages landing site for InputPilot to improve technical SEO and accessibility, and switches the Pages deployment to a custom domain (inputpilot.lucagerlich.dev).

Changes:

  • Adds SEO essentials (canonical URL, robots directives, sitemap.xml) and JSON-LD structured data to docs/index.html.
  • Fixes accessibility issues around the keyboard ASCII art labeling and decorative generated content.
  • Moves GitHub Pages to a custom domain via docs/CNAME (and adds .nojekyll).

Reviewed changes

Copilot reviewed 10 out of 20 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Scripts/generate-keyboard-html.py Generates HTML-wrapped keyboard ASCII art segments and emits JSON for the site.
Scripts/generate-keyboard-art.py Renders ANSI/ISO keyboard art into a sampled ASCII grid and ownership map.
docs/sitemap.xml Adds a sitemap pointing to the new canonical domain.
docs/robots.txt Adds a robots file referencing the sitemap on the new domain.
docs/index.html Updates SEO meta, adds JSON-LD, and adjusts accessibility + page copy/structure.
docs/CNAME Configures GitHub Pages to serve from inputpilot.lucagerlich.dev.
docs/.nojekyll Disables Jekyll processing on GitHub Pages.
.playwright-mcp/page-2026-08-18T20-59-20-768Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/page-2026-08-18T20-58-00-900Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/page-2026-08-18T20-57-37-579Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/page-2026-08-18T20-57-26-140Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/page-2026-08-18T20-57-10-025Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/page-2026-08-18T20-57-00-353Z.yml Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-58-35-992Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-57-58-830Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-57-36-725Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-57-25-970Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-57-04-795Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
.playwright-mcp/console-2026-08-18T20-57-00-122Z.log Playwright artifact (appears unrelated to InputPilot) committed into the repo.
Suppressed comments (2)

docs/index.html:154

  • Same issue here: content:"›" / "" can be parsed as invalid on browsers without support for the alt-text form, which would drop the visible marker. Add a plain content: fallback first.
	ul.checks li::before { content:"›" / ""; position:absolute; left:.3rem; color:var(--green); }

docs/index.html:161

  • content:"[+]" / "" and content:"[-]" / "" have the same compatibility risk as other generated-content markers: if the alt-text syntax isn’t supported, the whole declaration can be ignored and the disclosure affordance disappears. Add a plain content: fallback before the alt-text form.
	summary::after { content:"[+]" / ""; color:var(--faint); }
	details[open] summary::after { content:"[-]" / ""; }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/index.html
section { padding:3.5rem 0; border-top:1px solid var(--line); }
h2 { font-size:1.15rem; margin:0 0 .4rem; letter-spacing:-0.01em; }
h2::before { content:"# "; color:var(--faint); }
h2::before { content:"# " / ""; color:var(--faint); }
Comment on lines +1 to +5
- generic [active] [ref=f15e1]:
- banner [ref=f15e3]:
- link "jump to content" [ref=f15e4] [cursor=pointer]:
- /url: "#content"
- generic [ref=f15e6]:
Comment on lines +1 to +5
[ 34616ms] [ERROR] Client Error: "TypeError: Cannot read properties of null (reading 'match')" thrown at L14:31141 in https://web.archive.org/web/20260618201204js_/https://www.redditstatic.com/reddit-init.en.BddHLmUiRRw.js Message: "Uncaught TypeError: Cannot read properties of null (reading 'match')" {tag: unknown} @ https://web-static.archive.org/_static/js/wombat.js?v=o9P2E1FK:20
[ 34623ms] TypeError: Cannot read properties of null (reading 'match')
at Object.parseTrackingCookie (https://web.archive.org/web/20260618201204js_/https://www.redditstatic.com/reddit-init.en.BddHLmUiRRw.js:14:31141)
at Object.getLoIdData (https://web.archive.org/web/20260618201204js_/https://www.redditstatic.com/reddit-init.en.BddHLmUiRRw.js:14:30919)
at Object.getTrackingData (https://web.archive.org/web/20260618201204js_/https://www.redditstatic.com/reddit-init.en.BddHLmUiRRw.js:14:30772)
@LucaGerlich
LucaGerlich merged commit e847d21 into main Aug 18, 2026
2 checks passed
@LucaGerlich
LucaGerlich deleted the feat/seo branch August 18, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants