feat(blog): taxonomies and client-side filter UI#499
Conversation
Introduce two blog-specific taxonomies that drive the new filter UI: - article_types: release, case, how-to, tech-article, news - topics: platform, postgresql, kubernetes, cilium, talos, opensearch, kubevirt, networking, storage, security, events, community, gpu Hugo's built-in tags and categories taxonomies are kept explicitly so they still work if used later. No template changes in this commit; tagging posts and wiring the filter UI follow in separate commits. Signed-off-by: tym83 <6355522@gmail.com>
Populate the two new taxonomies on every existing blog post so the upcoming filter UI has real data to work with: - article_types: release | case | how-to | tech-article | news - topics: platform, postgresql, kubernetes, cilium, talos, opensearch, kubevirt, networking, storage, security, events, community, gpu Topics are assigned only when they are a main subject of the post, not for incidental mentions. Most release posts get 'platform' plus any headline features that were clearly the reason for the release. Signed-off-by: tym83 <6355522@gmail.com>
Override the blog list layout to render two parallel filter dimensions at the top of /blog/: - Article type (release, how-to, case, tech-article, news) — ordered by editorial lifecycle, not alphabetical. - Topic (platform, postgresql, kubernetes, cilium, talos, opensearch, kubevirt, networking, storage, security, events, community, gpu, ...) — auto-sorted. Filtering is client-side only: - Multiple chips within a dimension combine with OR. - The two dimensions combine with AND. - State is mirrored into the URL query string (?types=...&topics=...) so filtered views are shareable. - Empty year groups collapse when no post in them matches. - Pagination is dropped so the full archive is filterable in one pass; for ~70 posts this is well under 100 KB and keeps the UX honest. Signed-off-by: tym83 <6355522@gmail.com>
✅ Deploy Preview for cozystack ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (70)
📝 WalkthroughWalkthroughThis PR adds metadata taxonomy support to the blog by introducing Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a dynamic filtering system for the blog, utilizing new Hugo taxonomies for article types and topics. The implementation includes a filter UI in the blog list layout with corresponding CSS and JavaScript for client-side interactivity. Feedback suggests ensuring the alphabetical sorting of topics, enhancing accessibility by adding ARIA live regions to the post counter, and improving browser history support by utilizing pushState instead of replaceState.
| {{ range $slug, $_ := .Site.Taxonomies.topics }} | ||
| <button type="button" class="blog-filter__chip" | ||
| data-filter-kind="topic" data-filter-value="{{ $slug }}" | ||
| aria-pressed="false">{{ $slug | humanize }}</button> | ||
| {{ end }} |
There was a problem hiding this comment.
The PR description mentions that topics are "auto-sorted", but ranging over the .Site.Taxonomies.topics map in Hugo does not guarantee alphabetical order. To ensure the topics are consistently sorted by name as intended, you should use the .Alphabetical method.
| {{ range $slug, $_ := .Site.Taxonomies.topics }} | |
| <button type="button" class="blog-filter__chip" | |
| data-filter-kind="topic" data-filter-value="{{ $slug }}" | |
| aria-pressed="false">{{ $slug | humanize }}</button> | |
| {{ end }} | |
| {{ range .Site.Taxonomies.topics.Alphabetical }} | |
| <button type="button" class="blog-filter__chip" | |
| data-filter-kind="topic" data-filter-value="{{ .Term }}" | |
| aria-pressed="false">{{ .Term | humanize }}</button> | |
| {{ end }} |
| {{ end }} | ||
| </div> | ||
| <div class="blog-filter__footer"> | ||
| <p class="blog-filter__count" id="blog-filter-count"></p> |
There was a problem hiding this comment.
The post counter is updated dynamically via JavaScript. To ensure that screen reader users are notified when the count changes after applying a filter, the element should be marked as an ARIA live region.
| <p class="blog-filter__count" id="blog-filter-count"></p> | |
| <p class="blog-filter__count" id="blog-filter-count" aria-live="polite"></p> |
| if (topics.length) p.set('topics', topics.join(',')); else p.delete('topics'); | ||
| var q = p.toString(); | ||
| var next = window.location.pathname + (q ? '?' + q : '') + window.location.hash; | ||
| window.history.replaceState(null, '', next); |
There was a problem hiding this comment.
The PR description states that "back/forward works" for the filter UI, but the implementation uses history.replaceState, which does not create history entries. To support back/forward navigation through filter states, history.pushState should be used instead. Note that if you switch to pushState, you should also add a popstate event listener to re-apply filters when the user navigates through their history.
| window.history.replaceState(null, '', next); | |
| window.history.pushState(null, '', next); |
Replace the chip-based multi-select filter with two plain <select> dropdowns, one for article type and one for topic. Only one dropdown can be active at a time: selecting a value in either clears the other. Selection is single-value within each dropdown, no multi-select. URL state simplified to a single query param: ?type=... or ?topic=... (never both). Reflects the new interaction model one-to-one. Signed-off-by: tym83 <6355522@gmail.com>
Signed-off-by: tym83 <6355522@gmail.com>
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, reopen this pull request to trigger a review.
Summary
Adds two blog-specific taxonomies (
article_types,topics) and a client-side filter UI on the blog index so readers can narrow/blog/by article type and/or subject area.What
Data model —
hugo.yamlarticle_type/article_typesandtopic/topics.tagandcategorytaxonomies so nothing breaks if they are used later.Tagging — every existing post
content/en/blog/with a combination of:article_types:release | how-to | case | tech-article | news(usually one).topics:platform, postgresql, kubernetes, cilium, talos, opensearch, kubevirt, networking, storage, security, events, community, gpu(zero to three, only when the subject is a main theme of the post — not incidental mentions).platformby default, plus any headline features that were clearly the reason for the release (e.g. OpenSearch, GPU passthrough).Filter UI —
layouts/blog/list.html/blog/?types=how-to&topics=postgresql,kubernetes. Shareable, back/forward works.Why
Until now, the blog has been strictly chronological with no way to narrow down. Readers coming in from a community share ("how-to posts only", "anything about OpenSearch", "Cozystack release history") had to scroll the full archive.
This change takes advantage of existing structure — most posts already fall cleanly into one of the five editorial types and a small set of topics — without introducing new maintenance burden: adding tags to new posts is a two-line frontmatter change.
Preview
Netlify deploy preview will render the full filter UI on
/blog/. Things worth checking:/blog/?types=release&topics=platformdirectly and the chips should arrive pre-selected.Follow-ups (not in this PR)
/article-types/<slug>/and/topics/<slug>/, which still work but are separate URLs).Summary by CodeRabbit
New Features
Chores