Add category taxonomy and navigation integration
Some checks failed
CI / nightly-e2e (pull_request) Has been skipped
CI / deploy (pull_request) Has been skipped
CI / ci (pull_request) Failing after 14s
CI / pr-e2e (pull_request) Failing after 1m19s

Implements Issue #35 with category snippets, article category routing, category-aware templates, and category RSS feeds with tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mark
2026-03-03 11:20:07 +00:00
parent 49baf6a37d
commit e2f71a801c
13 changed files with 404 additions and 18 deletions

View File

@@ -13,13 +13,29 @@
<!-- Page Header -->
<div class="py-8 md:py-12 border-b border-zinc-200 dark:border-zinc-800 mb-12">
<h1 class="font-display font-black text-4xl md:text-6xl mb-6">{{ page.title }}</h1>
{% if active_category %}
<nav aria-label="Breadcrumb" class="font-mono text-xs text-zinc-500 mb-4">
<a href="/" class="hover:text-brand-cyan">Home</a> / <a href="/articles/" class="hover:text-brand-cyan">Articles</a> / <span>{{ active_category.name }}</span>
</nav>
{% endif %}
<h1 class="font-display font-black text-4xl md:text-6xl mb-3">{% if active_category %}{{ active_category.name }}{% else %}{{ page.title }}{% endif %}</h1>
{% if active_category.description %}
<p class="text-zinc-600 dark:text-zinc-400 mb-6">{{ active_category.description }}</p>
{% endif %}
<!-- Category Filters -->
<div class="flex flex-wrap gap-3 mb-4">
<a href="/articles/{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_category %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_category %}aria-current="page"{% endif %}>All Categories</a>
{% for category_link in category_links %}
<a href="{{ category_link.url }}{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_category and active_category.slug == category_link.category.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_category and active_category.slug == category_link.category.slug %}aria-current="page"{% endif %}>{{ category_link.category.name }}</a>
{% endfor %}
</div>
<!-- Tag Filters -->
<div class="flex flex-wrap gap-3">
<a href="/articles/" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_tag %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_tag %}aria-current="page"{% endif %}>All</a>
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_tag %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_tag %}aria-current="page"{% endif %}>All Tags</a>
{% for tag in available_tags %}
<a href="/articles/?tag={{ tag.slug }}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_tag == tag.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_tag == tag.slug %}aria-current="page"{% endif %}>{{ tag.name }}</a>
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}?tag={{ tag.slug }}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_tag == tag.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_tag == tag.slug %}aria-current="page"{% endif %}>{{ tag.name }}</a>
{% endfor %}
</div>
</div>

View File

@@ -140,6 +140,16 @@
{% endif %}
{% if available_tags %}
{% if available_categories %}
<div>
<h4 class="font-display font-bold mb-4 uppercase tracking-widest text-zinc-500 text-sm">Browse Categories</h4>
<div class="flex flex-wrap gap-2 mb-3">
{% for category in available_categories %}
<a href="/articles/category/{{ category.slug }}/" class="px-3 py-1.5 border border-zinc-200 dark:border-zinc-800 text-sm font-mono hover:border-brand-cyan hover:text-brand-cyan transition-colors">{{ category.name }}</a>
{% endfor %}
</div>
</div>
{% endif %}
<div>
<h4 class="font-display font-bold mb-4 uppercase tracking-widest text-zinc-500 text-sm">Explore Topics</h4>
<div class="flex flex-wrap gap-2">