-
v0.9.0 Stable
released this
2026-08-30 21:03:40 +02:00 | 3 commits to dev since this releaseThe admin is rebuilt: shared UI primitives, the brand palette and type, an
editorial index in place of the data grid, and song editing at its own URL. The
release also repairs an admin that had been unable to write anything for nine
months, and closes the path traversal that repair would otherwise have made
reachable.Added
- Song editing has its own URL —
/admin/songs/<slug>renders the edit form and a files section, so an edit can be reloaded, shared and reached with the browser Back button. A row'sFileslink deep-links to#files, which keeps uploading one click from the list now that the file dialog is gone - Shared UI primitives —
Modal,Button(variants plus a pending state),Field/TextareaField(label, error and description wiring) and aSongFormextracted from the add and edit dialogs. Each admin surface previously carried its own copy - The design language is enforced by tests —
admin-palettefails the build on any off-palette Tailwind hue, on a colour class with nodark:sibling, and on classes that cannot work in both themes;token-contrastrecomputes WCAG ratios from the real hexes inglobals.css. Two acceptance criteria that a reviewer used to have to remember to grep
Changed
- The admin wears the brand palette and type — Anton uppercase chrome, warm near-monochrome, and red reserved for hover, focus, active state and destructive actions. The Logout button is no longer red
- The songs table is an index list — hairline-divided rows mirroring the public index, with the title as the link to its edit page. A list of songs with per-row actions, not a data grid: nothing sorted or compared across columns, and dropping the table dropped the horizontal scroll wrapper five columns needed
- The dashboard reads top-down — header, then messages, then SONGS with a live count and the Add/Import pair, then the rows, then SETTINGS. The
All Songsheading previously sat immediately above the Settings card with the songs list forty lines below it, so a screen-reader user landing on that heading reached a suggestions toggle and a theme picker - Featured state is written out — each row reads
FeaturedorNot featuredwith a contrast step, rather than a single static word whose only state signal was a red checkbox fill. Colour is now redundant reinforcement, not the sole channel - The edit and file dialogs are retired — both opened over the list; the page behind them is reachable by link
- Heading rules are visible in light theme —
PageHeadingandSectionHeadingdrewborder-neutral-200, which is the light page ground, so their underline rendered at 1.000:1. Identical, not faint
Fixed
- Every admin write route returned 500 —
withValidationconsumed the request body to validate it, and each handler then read it again; a FetchRequestbody is a one-shot stream, so the second read threw and the error surfaced as an internal error. Adding, importing, editing, deleting and featuring a song were all broken, indevsince 2025-11-12. The middleware now validates a clone. Its own JSDoc example had been demonstrating the double read, which is how the pattern reached every route - The file input was unreachable by keyboard — the upload control used
display: none, which removes an element from the tab order, so there was no keyboard path to choosing a file at all (WCAG 2.1.1, level A) - The song row hover band was flush against its text — the band's edges landed on the glyphs, reading as a tight box rather than a row. It now reaches the page gutter while the text keeps its column
Security
- Path traversal in three admin routes —
slugwent into a filesystem path undercontent/guarded only by an existence check.delete-songwould recursively delete any directory given../x,delete-filewould unlink any file through eitherslugorfilename, andedit-songwould overwrite any pre-existinglyrics.md. Post-authentication, and unreachable while the routes were failing, but live the moment they worked. Containment now lives in one place,resolveWithin - The write routes had no authorization of their own — they trusted the middleware alone, while three sibling routes each carried an explicit check. All four now match
- 500 responses leaked absolute server paths — the raw error message was returned to the client, and Node filesystem errors embed paths. Unknown errors now return a constant
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Song editing has its own URL —
-
v0.8.0 Stable
released this
2026-08-25 20:37:02 +02:00 | 29 commits to dev since this releaseAdded
- Version number in the footer — the running release is shown after the copyright line (
· V0.8.0), inlined at build time frompackage.json, so it is possible to tell at a glance which build production is serving
Changed
- Brand assets page is a flat 3×3 grid — the Facebook background image and the three section headings (Logo, Paleta barw, Social media) are gone, leaving nine tiles that fill a three-column grid exactly. The grouped asset model existed only to drive per-section column spans, so it flattened to a plain list. A visually hidden heading keeps the route reachable for screen readers navigating by heading list
- Logo tiles are tighter and the images are clickable — the tile background and padding are gone (every asset already carries its own ground, so the second layer put a white square inside a beige one), the grid and section spacing are pulled in, and clicking a thumbnail opens the full-size PNG in a new tab. The
PNG/PDFlinks still download. The one genuinely transparent asset keeps a light ground, and its caption now says so - En dashes in Polish copy — user-visible strings now use the spaced półpauza (–) instead of the em dash (—), which is the correct Polish convention: logo captions, the search no-results message, the reading-settings hint and the header's home link. Song lyrics are untouched — their dashes are the lyricist's
Fixed
- Duplicate
mainlandmark on the home and logo pages — the locale layout already wraps every route in<main id="main-content">, and both pages nested a second<main>inside it. Two landmarks on one page break landmark navigation and blunt the skip link, which targets the outer one
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Version number in the footer — the running release is shown after the copyright line (
-
v0.7.0 Stable
released this
2026-08-25 19:06:36 +02:00 | 36 commits to dev since this releaseAdded
- Logo page —
/logo(linked from the header next to Pieśni) presents the choir's brand assets as thumbnails grouped into Logo, Paleta barw and Social media, each with a PNG download and, where one exists, the print-quality PDF. The files previously lived only indocs/LOGO/, which is not served, so there was no way to get the logo for a poster or a Facebook event
Fixed
- Admin login was impossible —
ADMIN_PASSWORD_HASHis read from.env, where Next.js expands$as a variable reference; a bcrypt hash starts$2b$12$, so the app received a truncated 47-character fragment and rejected every password as a mismatch. Broken since the 2026-06-04 security hardening introduced the hashed password.verifyPasswordnow validates the hash shape and reports the misconfiguration by name instead of blaming the password - PDF files under
public/returned 404 — the locale middleware redirected any unprefixed path, and its static-asset skip-list covered images and fonts but not.pdf, so every PDF resolved to301 → /en/…pdf → 404. The skip rule now lives in one tested place rather than inline in the middleware - Download links were indistinguishable to screen readers — every logo tile's links were named just "PNG" and "PDF", so browsing by links list gave twenty identically-named entries (WCAG 2.4.4). Each now carries its asset caption
Changed
- Slop gate is now enforced — a calibrated
slopgate.config.jsonmakes/commit,/pushand/shipblock on an over-budget diff and scores introduced duplication, which was previously never measured in this repo
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Logo page —
-
v0.5.3 — Header files menu Stable
released this
2026-07-18 16:05:11 +02:00 | 54 commits to dev since this releaseAdded
- Header files menu on the song page — a compact
Plikidropdown beside the reading settings surfaces the song's sheets/audio/video from the top of the page, so a rehearsing musician reaches them without scrolling past the lyrics; the lyric surface stays the hero (dropdown, not an expanded list)
Changed
- The bottom resources section is replaced by the header files menu (renders nothing when a song has no files)
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Header files menu on the song page — a compact
-
released this
2026-07-18 15:33:31 +02:00 | 56 commits to dev since this releaseChanged
- Constructivist parity on the song page — the reading page now shares the home's editorial language: a hero title led by the red-tick accent (still natural-case Geist),
NUTY/AUDIOas Anton headers with red ticks matchingPOLECANE, and the footer restyled in the uppercase-tracked editorial voice - Tighter reading measure (
max-w-2xl) so short lyric lines read as a composed column instead of swimming in empty space
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Constructivist parity on the song page — the reading page now shares the home's editorial language: a hero title led by the red-tick accent (still natural-case Geist),
-
v0.5.1 — Footer ground fix Stable
released this
2026-07-18 15:18:37 +02:00 | 58 commits to dev since this releaseFixed
- Footer shade — the footer sat on
neutral-50(a lighter, cooler near-white) instead of the warm paper ground; it now matches the header's ground tokens (neutral-200/neutral-950) with a matching hairline, so chrome sits on the body ground top and bottom
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Footer shade — the footer sat on
-
released this
2026-07-18 15:05:37 +02:00 | 60 commits to dev since this releaseDefiant editorial direction (from an
/impeccable:critique, 26 → 31/40):
constructivist weight returns to the chrome while the reading surface
stays calm — bold in the chrome, restrained in the content.Added
- Constructivist chrome —
Antonsection headers (POLECANE/SZUKAJ PIEŚNI) with a sparse red-tick accent, and an Anton wordmark beside the logo (desktop; mark-only on mobile); song titles stay natural-case Geist for pl/de diacritics - Search-first find cluster — search leads the home page, with the language filter and list bound beneath it (DOM order = focus order, WCAG 2.4.3)
Changed
- Reading controls de-orphaned into the song-page title header instead of floating in an empty row
- Quieter chorus marker — the recurring refrain is now a red left rule + italic (no red fill/box), so pages with several choruses no longer read as a red band
- Weightier, touch-friendly index rows — larger titles,
py-5targets, and a persistent (non-hover) arrow that slides on hover - Design direction recorded —
.impeccable.mdnow documents the "defiant chrome" pivot so it isn't reverted
Fixed
- 44px touch targets on the theme toggle and language selector (adaptive
min-hon touch, compact on desktop); the resource download arrow is now persistently visible - No "Unknown" filler — a missing/placeholder credit drops out of featured rows via the canonical
songMetaPartsgrammar, matching the index - Long-metadata overflow — long authors truncate (
max-w+ ellipsis) instead of breaking the row prefers-reduced-motionnow honored globally for every CSS transition, not just the opt-inmotion-safeones
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Constructivist chrome —
-
v0.4.0 Stable
released this
2026-07-12 18:47:54 +02:00 | 65 commits to main since this releaseReading-surface typesetting and an editorial resources section, on the
minimal-index direction (#304 lineage).Added
- Editorial resources section on the song page — NUTY / AUDIO / WIDEO file groups as index rows (no tabs, counters, or rainbow icons); nothing renders when a song has no files
- Labeled, separated credits — the song header now credits lyricist and composer distinctly, with localized language names, via a new
song-meta.tsSSOT (songMetaLine/songMetaParts)
Changed
- Stanza rhythm on the reading page — verses now read as verses; a
.lyrics-content pgap restores stanza spacing that Tailwind preflight had zeroed - Chorus markers activated — the brand-red chorus rule now fires on the recurring refrains in warszawianka, di szwue, czerwony sztandar, and Międzynarodówka; Bella ciao and Barāye split from single blocks into stanzas
- Localized chrome — typography controls, search suggestion labels, the skip link, and error fallbacks now flow through the i18n catalog (new
typographycatalog)
Fixed
- Junk-proof index metadata —
n/a/unknown/ malformed years dropped from index rows via thesongMetaPartsgrammar; language names localized (Jidysz, notyi) - Search input — long queries no longer slide under the magnifier icon (
pl-4 pr-12) - Metadata
·separators legible in light mode; featured author hint restored on mobile - Content: warszawianka year
187 → 1879; removed a stray source-URL line from the-day-the-nazi-died
Removed
- Unreachable legacy
/songsroute chain (SheetMusicList,Breadcrumb), the@headlessui/reactdependency, the suggestions APImatchedOnfield, and ~40 dead catalog keys
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
released this
2026-07-11 15:08:15 +02:00 | 73 commits to dev since this releaseFixed
- Language filter names now localize with the active UI language (Polski / Polnisch / Polish) instead of always showing English — the home filter read a static English map instead of the existing per-locale i18n catalog
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
released this
2026-07-06 20:56:36 +02:00 | 75 commits to dev since this releaseBrand identity & design overhaul (#304) — public surfaces moved to a minimal
editorial index, near-monochrome warm palette with red as a single sparse accent.Added
- Brand palette as live
@themetokens — red#BF2E2E, warm ink#232321, paper#EAE5E4, maroon#1B0E0D— plus a warm neutral ramp (replaces the hueless default) - Logo mark (
LogoMark) in the site header, replacing the text-only masthead - Editorial index homepage & search results — natural-case Geist titles, muted
author · year · languagemetadata, hairline dividers, hover arrows, no cards
Changed
- Reading surface branded — comfortable ~1.5 default leading, brand-red chorus marker + differentiated verse/chorus/bridge sections
- Reading page harmonized to the editorial index — natural-case Geist title, no card, muted metadata line
- One red+charcoal search-match system — matched text highlighted in place via
<mark>(weight + tint +aria-label), no amber/blue/purple/green rainbow - Header sits on the body ground (no white bar); theme/language controls ghosted
- Onboarding cue + empty-state "clear filters" recovery; clearer copy (named languages, deduped loading)
Accessibility
- WCAG 2.1 AA across public pages — every red-on-ground pairing verified ≥4.5:1, 44px touch targets, meaning never conveyed by colour alone
- AA-safe muted text — retuned
neutral-600(2.41:1 → 5.05:1 on paper)
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Brand palette as live