summaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/plans')
-rw-r--r--docs/superpowers/plans/2026-06-26-slackware-projects-section.md778
1 files changed, 778 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-06-26-slackware-projects-section.md b/docs/superpowers/plans/2026-06-26-slackware-projects-section.md
new file mode 100644
index 0000000..8213367
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-26-slackware-projects-section.md
@@ -0,0 +1,778 @@
+# Slackware Projects Section Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Add a `slackware` Hugo section with a clickable hub page that aggregates per-project deep-dive pages (styled rows), restructure the main menu (rename two entries, add nested "Slackware" parent with desktop hover + mobile indented submenu), reuse the shared `tags` taxonomy for project tech, and index projects in site search.
+
+**Architecture:** New Hugo section `content/{en,it}/slackware/` with `_index.md` (hub) and `<project>/index.md` pages. Hub list layout loops project pages into full-width alternating rows (option #3 shape, #2 styling). Project single layout reuses the `repository/single.html` shell plus a project-header partial. Menu nesting via `parent =` in `hugo.toml`; desktop submenu is CSS-only (`group-hover` + `group-focus-within`), mobile shows indented children. Tech tags use the existing `tags` taxonomy.
+
+**Tech Stack:** Hugo (extended), Tailwind CSS (npm build → `main.min.css`), Alpine.js (existing, unchanged here), Hugo i18n YAML.
+
+**Verification model:** No unit-test runner exists for templates. Each task verifies with `hugo` build/render checks (build succeeds, expected HTML/text present in output) and ends with a commit. Theme files commit inside the `themes/danix-xyz-hacker/` submodule; content/config/i18n commit in the content repo, per CLAUDE.md Git workflow.
+
+**Pre-flight (run once before Task 1):**
+- Content repo root: `/home/danix/Programming/GIT/danix.xyz-hacker-theme`
+- Confirm theme submodule is on master: `cd themes/danix-xyz-hacker && git checkout master && cd ../..`
+- All `hugo` build checks below run from the content repo root.
+
+---
+
+### Task 1: Scaffold the slackware section content (EN + IT)
+
+Creates the section so later layout work has real pages to render. Includes one sample project used by every later render check.
+
+**Files:**
+- Create: `content/en/slackware/_index.md`
+- Create: `content/it/slackware/_index.md`
+- Create: `content/en/slackware/sample-project/index.md`
+- Create: `content/it/slackware/sample-project/index.md`
+
+- [ ] **Step 1: Create EN hub index**
+
+`content/en/slackware/_index.md`:
+```toml
++++
+title = "Slackware"
+date = 2026-06-26T00:00:00Z
++++
+
+I build and run everything on **Slackware**. This page collects the projects
+I maintain around it, and the reasons I keep choosing it: simplicity,
+transparency, and staying out of my way.
+```
+
+- [ ] **Step 2: Create IT hub index**
+
+`content/it/slackware/_index.md`:
+```toml
++++
+title = "Slackware"
+date = 2026-06-26T00:00:00Z
++++
+
+Costruisco e uso tutto su **Slackware**. Questa pagina raccoglie i progetti
+che mantengo intorno ad essa, e i motivi per cui continuo a sceglierla:
+semplicità, trasparenza, e non mettersi in mezzo.
+```
+
+- [ ] **Step 3: Create EN sample project**
+
+`content/en/slackware/sample-project/index.md`:
+```toml
++++
+title = "Sample Project"
+tagline = "A placeholder project to validate the section layout."
+status = "active"
+repo_url = "https://git.danix.xyz/sample-project"
+tags = ["bash", "slackbuild", "python"]
++++
+
+## What it is
+
+Freeform body content for the sample project.
+
+## How it works
+
+Details here.
+
+## Rationale
+
+Why it exists.
+```
+
+- [ ] **Step 4: Create IT sample project**
+
+`content/it/slackware/sample-project/index.md`:
+```toml
++++
+title = "Progetto di Esempio"
+tagline = "Un progetto segnaposto per validare il layout della sezione."
+status = "active"
+repo_url = "https://git.danix.xyz/sample-project"
+tags = ["bash", "slackbuild", "python"]
++++
+
+## Cos'è
+
+Contenuto libero per il progetto di esempio.
+
+## Come funziona
+
+Dettagli qui.
+
+## Motivazione
+
+Perché esiste.
+```
+
+- [ ] **Step 5: Verify build succeeds and pages exist**
+
+Run: `hugo --quiet && ls public/en/slackware/sample-project/index.html public/it/slackware/sample-project/index.html`
+Expected: build completes with no errors; both files listed. (Pages render with Hugo's default `_default` layouts for now — that's fine; dedicated layouts come in Tasks 5–6.)
+
+- [ ] **Step 6: Commit (content repo)**
+
+```bash
+git add content/en/slackware content/it/slackware
+git commit -m "feat: scaffold slackware projects section (EN/IT) with sample project"
+```
+
+---
+
+### Task 2: Add i18n keys and rename menu labels
+
+Renames "Git Repository"→Projects and "Repo"→Packages via i18n values (menu labels render through `i18n .Name`), and adds all new keys the later layouts need.
+
+**Files:**
+- Modify: `i18n/en.yaml`
+- Modify: `i18n/it.yaml`
+
+- [ ] **Step 1: Rename + add EN keys**
+
+In `i18n/en.yaml`, change the existing values:
+```yaml
+gitrepo: "Projects"
+repo: "Packages"
+```
+Then add these new keys (anywhere in the file):
+```yaml
+slackware: "Slackware"
+slackwareTitle: "Slackware"
+slackwareSubtitle: "Projects I build and maintain on Slackware."
+projectStatus: "Status"
+viewRepo: "View repository"
+status-active: "active"
+status-maintained: "maintained"
+status-wip: "wip"
+status-archived: "archived"
+```
+
+- [ ] **Step 2: Rename + add IT keys**
+
+In `i18n/it.yaml`, change the existing values:
+```yaml
+gitrepo: "Progetti"
+repo: "Pacchetti"
+```
+Then add:
+```yaml
+slackware: "Slackware"
+slackwareTitle: "Slackware"
+slackwareSubtitle: "Progetti che costruisco e mantengo su Slackware."
+projectStatus: "Stato"
+viewRepo: "Vedi repository"
+status-active: "attivo"
+status-maintained: "mantenuto"
+status-wip: "in corso"
+status-archived: "archiviato"
+```
+
+- [ ] **Step 3: Verify build + label rendering**
+
+Run: `hugo --quiet && grep -o "Projects\|Packages" public/en/index.html | sort -u`
+Expected: build succeeds; output contains both `Projects` and `Packages` (the renamed desktop menu labels).
+
+- [ ] **Step 4: Commit (content repo)**
+
+```bash
+git add i18n/en.yaml i18n/it.yaml
+git commit -m "feat: rename menu labels (Projects/Packages) and add slackware i18n keys"
+```
+
+---
+
+### Task 3: Restructure menu config (nest Packages + Slackware hub)
+
+Adds the Slackware parent (→ hub) and nests Packages under it, in both language menus. Keeps Projects external.
+
+**Files:**
+- Modify: `hugo.toml` (Italian menu block ~lines 76–94; English menu block ~lines 122–140)
+
+- [ ] **Step 1: Add Slackware parent + nest repository (IT)**
+
+In `hugo.toml`, in the `languages.it.menus.main` block: leave the `gitrepo` (external) entry as-is. Replace the existing `repository` entry with a new Slackware parent plus the nested Packages entry:
+
+```toml
+ [[languages.it.menus.main]]
+ identifier = "slackware"
+ pageRef = "/slackware"
+ name = "slackware"
+ weight = 5
+
+ [[languages.it.menus.main]]
+ identifier = "repository"
+ pageRef = "/repository"
+ name = "repo"
+ parent = "slackware"
+ weight = 1
+```
+(Leave the `legal` entry at weight 6.)
+
+- [ ] **Step 2: Add Slackware parent + nest repository (EN)**
+
+In the `languages.en.menus.main` block, make the identical change:
+
+```toml
+ [[languages.en.menus.main]]
+ identifier = "slackware"
+ pageRef = "/slackware"
+ name = "slackware"
+ weight = 5
+
+ [[languages.en.menus.main]]
+ identifier = "repository"
+ pageRef = "/repository"
+ name = "repo"
+ parent = "slackware"
+ weight = 1
+```
+
+- [ ] **Step 2b: Add project pages into the submenu (both languages)**
+
+Hugo does not auto-add section pages to a menu. To make project pages appear in the Slackware submenu, add `menu` front-matter to each project. Update both sample project files from Task 1 by adding to their front-matter:
+
+`content/en/slackware/sample-project/index.md` and `content/it/slackware/sample-project/index.md`, add inside the `+++`:
+```toml
+[menus.main]
+ parent = "slackware"
+ weight = 10
+```
+
+- [ ] **Step 3: Verify menu nesting**
+
+Run: `hugo --quiet && hugo list all >/dev/null 2>&1; echo "build ok"`
+Then confirm the parent renders without breaking the existing top-level menu: `grep -c "Slackware" public/en/index.html`
+Expected: build ok; count >= 1. (Submenu HTML wiring is added in Tasks 4 & 7; here we only assert config builds and the parent label appears.)
+
+- [ ] **Step 4: Commit (content repo)**
+
+```bash
+git add hugo.toml content/en/slackware/sample-project/index.md content/it/slackware/sample-project/index.md
+git commit -m "feat: nest Packages under new Slackware menu parent (both languages)"
+```
+
+---
+
+### Task 4: Desktop header submenu (CSS-only hover + focus-within)
+
+Makes the desktop nav render children as a centered row below the bar on hover/focus, for any menu item that has children. Items without children are unchanged.
+
+**Files:**
+- Modify: `themes/danix-xyz-hacker/layouts/partials/header.html:13-27`
+
+- [ ] **Step 1: Replace the desktop menu loop**
+
+In `header.html`, replace the desktop menu block (the `<div class="hidden md:flex items-center gap-8">` … `</div>` containing the `range .Site.Menus.main`) with a parent-aware version:
+
+```html
+ <!-- Desktop menu (hidden on mobile) -->
+ <div class="hidden md:flex items-center gap-8">
+ {{ $currentPath := strings.TrimSuffix "/" .RelPermalink }}
+ {{ range .Site.Menus.main }}
+ {{ $menuPath := strings.TrimSuffix "/" .URL }}
+ {{ $isActive := eq $menuPath $currentPath }}
+ {{ $isExternal := .Params.external }}
+ {{ if .HasChildren }}
+ <div class="relative group">
+ <a
+ href="{{ .URL }}"
+ class="text-sm transition-colors inline-flex items-center gap-1 {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}"
+ aria-haspopup="true"
+ {{ if $isActive }}aria-current="page"{{ end }}
+ >
+ {{ i18n .Name }}
+ <i data-feather="chevron-down" class="w-3 h-3" aria-hidden="true"></i>
+ </a>
+ <!-- Submenu: padding-top bridges the hover gap -->
+ <div class="absolute left-1/2 -translate-x-1/2 top-full pt-3 hidden group-hover:flex group-focus-within:flex">
+ <ul class="frosted-bar border border-border rounded-lg px-4 py-3 flex flex-col gap-2 min-w-max shadow-lg" role="menu">
+ {{ range .Children }}
+ {{ $childExternal := .Params.external }}
+ <li role="none">
+ <a
+ href="{{ .URL }}"
+ role="menuitem"
+ class="block text-sm whitespace-nowrap hover:text-accent transition-colors"
+ {{ if $childExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
+ >
+ {{ if $childExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
+ </a>
+ </li>
+ {{ end }}
+ </ul>
+ </div>
+ </div>
+ {{ else }}
+ <a
+ href="{{ .URL }}"
+ class="text-sm transition-colors {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}"
+ {{ if $isActive }}aria-current="page"{{ end }}
+ {{ if $isExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
+ >
+ {{ if $isExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
+ </a>
+ {{ end }}
+ {{ end }}
+ </div>
+```
+
+Note: this also fixes the pre-existing bug where external top-level items (Projects) rendered `i18n .Name` and lacked `target="_blank"` in the desktop bar. Now external items use `.Name` + new tab, matching the overlay.
+
+- [ ] **Step 2: Verify submenu HTML renders**
+
+Run: `hugo --quiet && grep -o "group-hover:flex" public/en/index.html | head -1`
+Expected: build succeeds; `group-hover:flex` present (submenu wrapper emitted). Also confirm Packages link is inside: `grep -A30 "aria-haspopup" public/en/index.html | grep -c "/en/repository/"` → >= 1.
+
+- [ ] **Step 3: Commit (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/partials/header.html
+git commit -m "feat: desktop nav submenu for nested menu items (CSS hover + focus-within)"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 5: Project header partial
+
+Renders the light-schema header (tagline, status badge, repo link, optional image, tech pills) above project body. Used by the single layout (Task 6).
+
+**Files:**
+- Create: `themes/danix-xyz-hacker/layouts/partials/project-header.html`
+
+- [ ] **Step 1: Write the partial**
+
+`themes/danix-xyz-hacker/layouts/partials/project-header.html`:
+```html
+{{ $status := .Params.status | default "active" }}
+{{ $statusColor := "var(--color-accent, #a855f7)" }}
+{{ if eq $status "maintained" }}{{ $statusColor = .Site.Params.secondaryAccent }}{{ end }}
+{{ if eq $status "wip" }}{{ $statusColor = "#f59e0b" }}{{ end }}
+{{ if eq $status "archived" }}{{ $statusColor = "#9ca3af" }}{{ end }}
+
+{{ $imageURL := "" }}
+{{ if .Params.image }}
+ {{ $res := .Resources.GetMatch .Params.image }}
+ {{ if $res }}{{ $imageURL = $res.RelPermalink }}{{ else }}{{ $imageURL = .Params.image }}{{ end }}
+{{ end }}
+
+<header class="mb-10">
+ {{ if $imageURL }}
+ <img src="{{ $imageURL }}" alt="{{ .Title }}" class="w-24 h-24 object-contain rounded-lg mb-4 bg-surface/50" loading="lazy" />
+ {{ end }}
+
+ <div class="flex flex-wrap items-center gap-3 mb-2">
+ <h1 class="text-4xl md:text-5xl font-bold text-accent font-oxanium">{{ .Title }}</h1>
+ <span class="px-3 py-1 rounded-full text-xs font-semibold" style="background-color: {{ $statusColor }}; color: #0b0b0b;">
+ {{ i18n (printf "status-%s" $status) }}
+ </span>
+ </div>
+
+ {{ with .Params.tagline }}
+ <p class="text-xl text-text-dim mb-4">{{ . }}</p>
+ {{ end }}
+
+ <div class="flex flex-wrap items-center gap-3">
+ {{ with .Params.repo_url }}
+ <a href="{{ . }}" target="_blank" rel="noopener noreferrer" class="btn btn-sm inline-flex items-center gap-2">
+ {{ i18n "viewRepo" }}
+ <i data-feather="external-link" class="w-4 h-4" aria-hidden="true"></i>
+ </a>
+ {{ end }}
+ {{ with .Params.tags }}
+ <ul class="flex flex-wrap gap-2">
+ {{ range . }}
+ <li><a href="/tags/{{ . | urlize }}/" class="px-2 py-1 rounded text-xs bg-surface text-text-dim hover:text-accent transition-colors">{{ . }}</a></li>
+ {{ end }}
+ </ul>
+ {{ end }}
+ </div>
+</header>
+```
+
+- [ ] **Step 2: Commit (theme submodule)**
+
+(Partial is rendered by Task 6's layout; verification happens there. Commit now to keep tasks atomic.)
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/partials/project-header.html
+git commit -m "feat: add project-header partial (status badge, repo link, tech pills)"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 6: Project single layout
+
+Wires `project-header.html` above the freeform body, reusing the `repository/single.html` shell idiom (breadcrumb, content-grid, prose, social-share).
+
+**Files:**
+- Create: `themes/danix-xyz-hacker/layouts/slackware/single.html`
+
+- [ ] **Step 1: Write the single layout**
+
+`themes/danix-xyz-hacker/layouts/slackware/single.html`:
+```html
+{{ define "main" }}
+<article class="mx-auto px-4 py-12 max-w-4xl">
+ <div class="content-grid">
+ {{ partial "breadcrumb.html" . }}
+
+ {{ partial "project-header.html" . }}
+
+ <div class="prose dark:prose-invert max-w-none mb-12">
+ {{ .Content }}
+ </div>
+
+ <div class="mb-12">
+ {{ partial "social-share.html" (dict "page" . "mode" "inline") }}
+ </div>
+ </div>
+</article>
+{{ end }}
+```
+
+- [ ] **Step 2: Verify project page renders header + body**
+
+Run: `hugo --quiet && grep -o "status-active\|active" public/en/slackware/sample-project/index.html | head -1 && grep -c "View repository" public/en/slackware/sample-project/index.html`
+Expected: build succeeds; the status badge text (`active`) present; `View repository` count >= 1. Also `grep -c "What it is" public/en/slackware/sample-project/index.html` → >= 1 (freeform body rendered).
+
+- [ ] **Step 3: Commit (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/slackware/single.html
+git commit -m "feat: slackware project single layout with project header"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 7: Mobile overlay indented children
+
+Renders child links indented under their parent in the hamburger overlay. Items without children unchanged.
+
+**Files:**
+- Modify: `themes/danix-xyz-hacker/layouts/partials/hamburger-menu.html:30-45`
+
+- [ ] **Step 1: Replace the overlay menu loop**
+
+In `hamburger-menu.html`, replace the `{{ range .Site.Menus.main }}…{{ end }}` block inside `<nav class="p-6" …>` with:
+
+```html
+ {{ $currentPath := strings.TrimSuffix "/" .RelPermalink }}
+ {{ range .Site.Menus.main }}
+ {{ $menuPath := strings.TrimSuffix "/" .URL }}
+ {{ $isActive := eq $menuPath $currentPath }}
+ {{ $isExternal := .Params.external }}
+ <a
+ href="{{ .URL }}"
+ @click="menuOpen = false"
+ class="block py-4 text-lg font-medium transition-colors border-b border-border/30 {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}"
+ {{ if $isActive }}aria-current="page"{{ end }}
+ {{ if $isExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
+ >
+ {{ if $isExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
+ {{ if $isExternal }}<span class="sr-only">{{ i18n "opensInNewTab" }}</span>{{ end }}
+ </a>
+ {{ if .HasChildren }}
+ <div class="pl-4 border-l-2 border-accent/40 ml-2">
+ {{ range .Children }}
+ {{ $childExternal := .Params.external }}
+ <a
+ href="{{ .URL }}"
+ @click="menuOpen = false"
+ class="block py-3 text-base text-text-dim hover:text-accent transition-colors"
+ {{ if $childExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
+ >
+ {{ if $childExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
+ </a>
+ {{ end }}
+ </div>
+ {{ end }}
+ {{ end }}
+```
+
+- [ ] **Step 2: Verify indented children render**
+
+Run: `hugo --quiet && grep -c "border-accent/40" public/en/index.html`
+Expected: build succeeds; count >= 1 (the indented child container is emitted because Slackware has children).
+
+- [ ] **Step 3: Commit (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/partials/hamburger-menu.html
+git commit -m "feat: indented submenu children in mobile overlay"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 8: Project row partial
+
+One full-width hub row: option #3 shape (alternating image side), option #2 styling (accent stripe, oxanium title, status badge, tagline, tech pills, hover lift). Mono-glyph fallback when no image.
+
+**Files:**
+- Create: `themes/danix-xyz-hacker/layouts/partials/project-row.html`
+
+- [ ] **Step 1: Write the row partial**
+
+Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left; odd → image right.
+
+`themes/danix-xyz-hacker/layouts/partials/project-row.html`:
+```html
+{{ $p := .page }}
+{{ $reverse := eq (mod .index 2) 1 }}
+
+{{ $status := $p.Params.status | default "active" }}
+{{ $statusColor := "var(--color-accent, #a855f7)" }}
+{{ if eq $status "maintained" }}{{ $statusColor = $p.Site.Params.secondaryAccent }}{{ end }}
+{{ if eq $status "wip" }}{{ $statusColor = "#f59e0b" }}{{ end }}
+{{ if eq $status "archived" }}{{ $statusColor = "#9ca3af" }}{{ end }}
+
+{{ $imageURL := "" }}
+{{ if $p.Params.image }}
+ {{ $res := $p.Resources.GetMatch $p.Params.image }}
+ {{ if $res }}{{ $imageURL = $res.RelPermalink }}{{ else }}{{ $imageURL = $p.Params.image }}{{ end }}
+{{ end }}
+{{ $glyph := substr (upper $p.Title) 0 2 }}
+
+<article class="group flex flex-col md:flex-row {{ if $reverse }}md:flex-row-reverse{{ end }} gap-6 items-stretch border-l-4 border-accent bg-surface/30 rounded-lg overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg hover:bg-surface/50">
+ <!-- Visual -->
+ <a href="{{ $p.RelPermalink }}" tabindex="-1" class="md:w-1/3 flex-shrink-0 flex items-center justify-center bg-bg/40 min-h-[10rem]">
+ {{ if $imageURL }}
+ <img src="{{ $imageURL }}" alt="{{ $p.Title }}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200" loading="lazy" />
+ {{ else }}
+ <span class="text-5xl font-bold font-oxanium text-accent/80 select-none">{{ $glyph }}</span>
+ {{ end }}
+ </a>
+
+ <!-- Body -->
+ <div class="flex-1 p-6 flex flex-col gap-3">
+ <div class="flex items-start justify-between gap-3">
+ <h3 class="text-2xl font-bold font-oxanium">
+ <a href="{{ $p.RelPermalink }}" class="group-hover:text-accent transition-colors">{{ $p.Title }}</a>
+ </h3>
+ <span class="flex-shrink-0 px-3 py-1 rounded-full text-xs font-semibold" style="background-color: {{ $statusColor }}; color: #0b0b0b;">
+ {{ i18n (printf "status-%s" $status) }}
+ </span>
+ </div>
+
+ {{ with $p.Params.tagline }}
+ <p class="text-text-dim">{{ . }}</p>
+ {{ end }}
+
+ {{ with $p.Params.tags }}
+ <ul class="flex flex-wrap gap-2 mt-1">
+ {{ range . }}
+ <li class="px-2 py-1 rounded text-xs bg-bg/60 text-text-dim">{{ . }}</li>
+ {{ end }}
+ </ul>
+ {{ end }}
+
+ <div class="flex flex-wrap items-center gap-3 mt-auto pt-2">
+ <a href="{{ $p.RelPermalink }}" class="btn btn-sm inline-flex items-center gap-2">
+ {{ i18n "readMore" }}
+ <i data-feather="arrow-right" class="w-4 h-4" aria-hidden="true"></i>
+ </a>
+ {{ with $p.Params.repo_url }}
+ <a href="{{ . }}" target="_blank" rel="noopener noreferrer" class="text-sm text-text-dim hover:text-accent inline-flex items-center gap-1 transition-colors">
+ {{ i18n "viewRepo" }}
+ <i data-feather="external-link" class="w-3 h-3" aria-hidden="true"></i>
+ </a>
+ {{ end }}
+ </div>
+ </div>
+</article>
+```
+
+- [ ] **Step 2: Commit (theme submodule)**
+
+(Rendered by Task 9's list layout; verify there.)
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/partials/project-row.html
+git commit -m "feat: add project-row partial (alternating rows, status, tech pills)"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 9: Slackware hub list layout
+
+Renders hero (i18n title/subtitle), the `_index.md` freeform body, then the project rows. Links to Packages.
+
+**Files:**
+- Create: `themes/danix-xyz-hacker/layouts/slackware/list.html`
+
+- [ ] **Step 1: Write the list layout**
+
+`themes/danix-xyz-hacker/layouts/slackware/list.html`:
+```html
+{{ define "main" }}
+<section class="mx-auto px-4 py-12 max-w-5xl">
+ <div class="content-grid">
+ {{ partial "breadcrumb.html" . }}
+
+ <div class="mb-10">
+ <h1 class="text-5xl md:text-6xl font-bold mb-4 text-accent font-oxanium animate-fade-in">
+ {{ i18n "slackwareTitle" }}
+ </h1>
+ <p class="text-xl text-text-dim animate-fade-in-delay">
+ {{ i18n "slackwareSubtitle" }}
+ </p>
+ </div>
+
+ {{ with .Content }}
+ <div class="prose dark:prose-invert max-w-none mb-12">
+ {{ . }}
+ </div>
+ {{ end }}
+
+ <div class="flex flex-col gap-8">
+ {{ range $index, $p := .Pages }}
+ {{ partial "project-row.html" (dict "page" $p "index" $index) }}
+ {{ end }}
+ </div>
+ </div>
+</section>
+{{ end }}
+```
+
+- [ ] **Step 2: Verify hub renders rows**
+
+Run: `hugo --quiet && grep -c "Sample Project" public/en/slackware/index.html && grep -c "border-l-4 border-accent" public/en/slackware/index.html`
+Expected: build succeeds; `Sample Project` count >= 1 (row rendered); accent stripe class present. Confirm IT too: `grep -c "Progetto di Esempio" public/it/slackware/index.html` → >= 1.
+
+- [ ] **Step 3: Commit (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/slackware/list.html
+git commit -m "feat: slackware hub list layout with project rows"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 10: Index projects in site search
+
+Adds the `slackware` section to the JSON search index so the search box returns projects.
+
+**Files:**
+- Modify: `themes/danix-xyz-hacker/layouts/index.json`
+
+- [ ] **Step 1: Union articles + slackware pages**
+
+Replace the first two lines of `index.json`:
+```
+{{- $articles := where .Site.RegularPages "Section" "articles" -}}
+{{- $articles = $articles.ByDate.Reverse -}}
+```
+with:
+```
+{{- $articles := where .Site.RegularPages "Section" "articles" -}}
+{{- $projects := where .Site.RegularPages "Section" "slackware" -}}
+{{- $articles = ($articles | append $projects).ByDate.Reverse -}}
+```
+(The rest of the template is unchanged; project pages expose `.Title`, `.Permalink`, `.Date`, `.Summary` like articles.)
+
+- [ ] **Step 2: Verify project is in the index**
+
+Run: `hugo --quiet && grep -c "Sample Project" public/index.json`
+Expected: build succeeds; count >= 1 (sample project present in EN search index). Confirm IT: `grep -c "Progetto di Esempio" public/it/index.json` → >= 1.
+
+- [ ] **Step 3: Commit (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add layouts/index.json
+git commit -m "feat: include slackware projects in search index"
+git push origin master
+cd ../..
+```
+
+---
+
+### Task 11: Build CSS and verify full integration
+
+Recompiles Tailwind (new classes from the new partials/layouts) and runs the cross-cutting checks from the spec.
+
+**Files:**
+- Modify: `themes/danix-xyz-hacker/assets/css/main.min.css` (generated)
+
+- [ ] **Step 1: Rebuild CSS**
+
+Run (from content repo root): `npm run build`
+Expected: completes, writes `themes/danix-xyz-hacker/assets/css/main.min.css`.
+
+- [ ] **Step 2: Full render verification**
+
+Run: `hugo --quiet`
+Then confirm each spec requirement:
+- Hub EN/IT: `test -f public/en/slackware/index.html && test -f public/it/slackware/index.html && echo hub-ok`
+- Project page: `grep -c "View repository" public/en/slackware/sample-project/index.html` → >= 1
+- Taxonomy unification: `grep -c "Sample Project" public/tags/python/index.html` → >= 1 (project appears on the shared tag term page)
+- Search: `grep -c "Sample Project" public/index.json` → >= 1
+- Menu labels: `grep -o "Projects\|Packages\|Slackware" public/en/index.html | sort -u` → all three
+- Desktop submenu: `grep -c "group-hover:flex" public/en/index.html` → >= 1
+- Mobile children: `grep -c "border-accent/40" public/en/index.html` → >= 1
+
+Expected: every check passes.
+
+- [ ] **Step 3: Commit compiled CSS (theme submodule)**
+
+```bash
+cd themes/danix-xyz-hacker
+git add assets/css/main.min.css
+git commit -m "build: recompile CSS for slackware section"
+git push origin master
+cd ../..
+```
+
+- [ ] **Step 4: Bump submodule pointer (content repo)**
+
+```bash
+git add themes/danix-xyz-hacker
+git commit -m "chore: bump theme submodule (slackware projects section)"
+```
+
+---
+
+### Task 12: Manual browser check (user)
+
+Automated grep checks can't see hover/layout. The user verifies interactively before deploy.
+
+- [ ] **Step 1: Run dev server**
+
+Run: `hugo server`
+Open `http://localhost:1313/en/slackware/` and `/it/slackware/`.
+
+- [ ] **Step 2: Confirm visually**
+
+- Desktop: hover "Slackware" → centered submenu row appears with Packages (+ sample project); Tab key also reveals it; "Projects" opens git.danix.xyz in a new tab with external glyph.
+- Mobile (narrow window): hamburger → "Slackware" shows indented children beneath it.
+- Hub rows alternate image side L/R; status badge top-right; hover lifts the row; mono-glyph fallback shows for the imageless sample project.
+- Switch EN/IT; everything symmetric, no raw i18n keys visible.
+
+- [ ] **Step 3: Deploy when satisfied**
+
+Per CLAUDE.md: `git checkout production && git merge master && git push origin production` (content repo), after which the post-receive hook clones the theme master tip and builds. Then `git checkout master`.
+
+---
+
+## Self-Review Notes
+
+- **Spec coverage:** menu restructure (T2/T3/T4/T7), section + sample (T1), light schema header (T5/T6), hub rows #3+#2 (T8/T9), shared `tags` taxonomy (T1 front-matter, verified T11), search indexing (T10), status badge string not git-fetch (T5/T8), CSS-only submenu + focus-within (T4), i18n EN/IT (T2), CSS build + submodule workflow (T11), deploy (T12). All covered.
+- **No placeholders:** every code step shows full content; no TBD/TODO.
+- **Type/name consistency:** status color logic and `status-<x>` i18n keys identical in project-header (T5) and project-row (T8); `dict "page" … "index" …` produced in T9 matches `.page`/`.index` consumed in T8; `slackwareTitle`/`slackwareSubtitle`/`viewRepo`/`status-*` defined in T2 and used in T5/T6/T8/T9.
+- **Discovered simplification:** menu rename is i18n-value-only (labels render via `i18n .Name`); no `name=` churn needed. Captured in T2.
+- **Bonus fix:** T4 corrects a pre-existing desktop-bar bug where external items lacked `target="_blank"` and wrongly ran `i18n .Name`.