ommp.git

ommp

~ Oh My Music Player — a standalone terminal music player built with Rust and ratatui
git clone https://github.com/debuman/ommp.git
commit 3ce49f6d15fd49e599e790ec60f9c541fd5e956f
parent 0a5cb58b1ddb3da82913743d863277534d2d6949
Author: sqzer <sqzer-x@users.noreply.github.com>
Date: Sat, 1 Aug 2026 20:42:56 +0900

Correct two false claims on the page, and fix keyboard copy, the card and the icon

An audit of the live site turned up two sentences that describe software this
is not.

The Artists card said tracks are grouped by album artist where tagged and track
artist where not. Index::build keys by_artist on the track artist alone;
album_artist_of() is called once, for the by_album key. A compilation tagged
album_artist=Various Artists, artist=Yorushika files under Yorushika in the
Artists tab. The sentence was true, but about the Albums tab — so it has moved
there, and Artists now says what it does.

The lede promised it picks up where you left off. SavedState holds volume,
shuffle, repeat, pane widths, playlists, info view and right split; no queue, no
current track, no position. Startup calls ReplaceQueue over the whole library.
The claim is now the one the program can keep.

The install commands were click-only, which left the page's primary call to
action unreachable by keyboard. They take a tab stop, a button role and
Enter/Space now. The role is assigned from the script rather than the markup:
copying only works once the script has run, so without it they are plain text
and should not claim otherwise.

og:image was a raw 4K screenshot scaled to a card — at the size a feed renders
it, nothing was legible and the name appeared nowhere. It is now composed: the
wordmark, the headline, and the app's own progress bar. Legible at 240px.

The favicon was the same 723x421 wordmark, which is a smear in a tab, and
/favicon.ico had nothing behind it. Both are answered by one square mark cut
from the wordmark's own 'O', carrying the logo's pink-to-cyan, shipped as an
.ico at the site root.

Diffstat:
Msite/content/_index.md | 6+++---
Asite/static/favicon.ico | 0binary
Msite/static/img/og.png | 0binary
Msite/static/js/status.js | 19+++++++++++++++++--
Msite/templates/landing.html | 5++++-
5 files changed, 24 insertion(+), 6 deletion(-)

diff --git a/site/content/_index.md b/site/content/_index.md
@@ -7,7 +7,7 @@ template = "landing.html"
 kicker    = "Terminal music player"
 headline  = "Point it at ~/Music."
 headline2 = "Press play."
-lede = "No MPD. No daemon. No config file. One binary that reads your tags, draws your album art in the terminal, and picks up where you left off."
+lede = "No MPD. No daemon. No config file. One binary that reads your tags, draws your album art in the terminal, and keeps your playlists and layout between sessions."
 
 install_primary_label = "Arch Linux"
 install_primary       = "yay -S ommp"
@@ -29,12 +29,12 @@ body  = "Browse the folders you actually organised, not a database's idea of the
 [[extra.features]]
 name  = "Artists"
 color = "#FFB464"
-body  = "Grouped by album artist where it is tagged, track artist where it is not. Untagged files land under one heading instead of vanishing."
+body  = "Grouped by the track artist, exactly as the file is tagged. Untagged files land under one heading instead of vanishing."
 
 [[extra.features]]
 name  = "Albums"
 color = "#C882FF"
-body  = "Paired with their artist, so two records called <em>Greatest Hits</em> stay two records."
+body  = "Paired with the album artist where it is tagged, the track artist where it is not — so two records called <em>Greatest Hits</em> stay two records."
 
 [[extra.features]]
 name  = "Genre"
diff --git a/site/static/favicon.ico b/site/static/favicon.ico
Binary files differ.
diff --git a/site/static/img/og.png b/site/static/img/og.png
Binary files differ.
diff --git a/site/static/js/status.js b/site/static/js/status.js
@@ -48,14 +48,29 @@
   addEventListener("resize", onScroll);
   update();
 
-  // Click a command to copy it — the page is mostly commands.
+  // Click a command to copy it — the page is mostly commands. The button role
+  // and the tab stop are set here rather than in the markup: copying is only
+  // possible once this file has run, so without it these are plain text and
+  // should not claim to be anything else.
   document.querySelectorAll("[data-copy]").forEach(function (el) {
-    el.addEventListener("click", function () {
+    el.tabIndex = 0;
+    el.setAttribute("role", "button");
+
+    function copy() {
       if (!navigator.clipboard) return;
       navigator.clipboard.writeText(el.textContent.trim()).then(function () {
         el.classList.add("is-copied");
         setTimeout(function () { el.classList.remove("is-copied"); }, 1400);
       });
+    }
+
+    el.addEventListener("click", copy);
+    el.addEventListener("keydown", function (e) {
+      // What a real button answers to.
+      if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
+        e.preventDefault();
+        copy();
+      }
     });
   });
 })();
diff --git a/site/templates/landing.html b/site/templates/landing.html
@@ -16,7 +16,10 @@
 <meta property="og:image" content="{{ site.origin }}{{ asset('img/og.png') }}">
 <meta name="twitter:card" content="summary_large_image">
 
-<link rel="icon" href="{{ asset('img/logo.png') }}">
+{#- The wordmark is 723x421; at 16px it is a smear. This is the same 'O' block
+    glyph lifted out of it, squared up, carrying the logo's two colours. It also
+    sits at the site root so a bare /favicon.ico request resolves. -#}
+<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
 <link rel="preload" as="font" type="font/woff2" href="{{ asset('fonts/jetbrains-mono-400.woff2') }}" crossorigin>
 <link rel="preload" as="font" type="font/woff2" href="{{ asset('fonts/bricolage-grotesque-var.woff2') }}" crossorigin>
 <link rel="stylesheet" href="{{ asset('css/main.css') }}">