# Design: packages.danix.xyz Shortcodes **Date:** 2026-05-14 **Status:** Approved ## Overview Two Alpine.js shortcodes for the repository page that fetch live data from `packages.danix.xyz` and render it in the browser. Data updates on every page load without a site rebuild. ## Prerequisites ### CORS (manual step — not in theme) Add to Apache config on `packages.danix.xyz`: ```apache Header set Access-Control-Allow-Origin "https://danix.xyz" ``` Without this header, browser fetch from `danix.xyz` will be blocked by CORS policy. --- ## Shortcode 1: `pkg-list` ### Usage ``` {{< pkg-list >}} ``` No parameters. Fetches from hardcoded `https://packages.danix.xyz/PACKAGES.TXT`. ### File `themes/danix-xyz-hacker/layouts/shortcodes/pkg-list.html` ### Behavior - On mount, Alpine fetches `PACKAGES.TXT` via `fetch()` - Parses repeating blocks: extracts `PACKAGE NAME` and `PACKAGE LOCATION` lines - Parses filename to extract short name and version: - Input: `waybar-0.14.0-x86_64-2_danix.txz` - Output: name=`waybar`, version=`0.14.0` - Derives category and folder link from `PACKAGE LOCATION` (e.g. `./desktop/waybar` → `https://packages.danix.xyz/desktop/waybar/`) - Renders a filterable table ### Table columns | Name | Version | Link | |------|---------|------| | waybar | 0.14.0 | → packages.danix.xyz/desktop/waybar/ | - **Name**: parsed short name (before first version segment) - **Version**: first version segment from filename - **Link**: anchor pointing to folder on packages.danix.xyz, label is `category/name` ### Filter Text input above table. Filters by name, client-side, no server round-trips. ### States 1. **Loading**: spinner + i18n loading string 2. **Loaded**: filter input + table 3. **Error**: styled error block + fallback link to `https://packages.danix.xyz` ### i18n keys (new) ```yaml pkg_list_loading: "Loading packages..." # it: "Caricamento pacchetti..." pkg_list_error: "Could not load packages." # it: "Impossibile caricare i pacchetti." pkg_list_filter: "Filter packages..." # it: "Filtra pacchetti..." pkg_list_link_label: "View" # it: "Visualizza" ``` --- ## Shortcode 2: `pkg-changelog` ### Usage ``` {{< pkg-changelog count="10" >}} ``` `count`: number of entries to display. Default: `10`. ### File `themes/danix-xyz-hacker/layouts/shortcodes/pkg-changelog.html` ### Behavior - On mount, Alpine fetches `https://packages.danix.xyz/ChangeLog.txt` via `fetch()` - Splits on `+--------------------------+` delimiter to get individual entries - Discards empty chunks; takes first N (from `count` param rendered into `x-data`) - Each chunk: first non-empty line = timestamp, remaining lines = change description ### Timeline rendering Vertical timeline with purple accent dots (theme `primaryAccent` color `#a855f7`): ``` │ ◉ Thu May 14 17:17:42 UTC 2026 │ personal/python3-platformdirs/...: Updated for git 7836e58 │ ◉ Thu May 14 17:02:54 UTC 2026 │ personal/nvchecker/...: Added version 2.20. ``` - Dot: `◉` or CSS circle marker, purple accent color - Timestamp: bold, readable date - Change text: monospace, preserves whitespace/line breaks from source ### States 1. **Loading**: spinner + i18n loading string 2. **Loaded**: timeline 3. **Error**: styled error block + fallback link to `https://packages.danix.xyz/ChangeLog.txt` ### i18n keys (new) ```yaml pkg_changelog_loading: "Loading changelog..." # it: "Caricamento changelog..." pkg_changelog_error: "Could not load changelog." # it: "Impossibile caricare il changelog." ``` --- ## File Checklist | File | Action | |------|--------| | `themes/danix-xyz-hacker/layouts/shortcodes/pkg-list.html` | Create | | `themes/danix-xyz-hacker/layouts/shortcodes/pkg-changelog.html` | Create | | `themes/danix-xyz-hacker/i18n/en.yaml` | Add i18n keys | | `themes/danix-xyz-hacker/i18n/it.yaml` | Add i18n keys | | `packages.danix.xyz` Apache config | Add CORS header (manual) | | `content/en/repository/index.md` | Add shortcode calls | | `content/it/repository/index.md` | Add shortcode calls | ## Out of Scope - CSS rebuild (`npm run build`) required if shortcodes introduce Tailwind classes not already in `main.min.css`; use existing utility classes where possible to avoid this - No new JS files — logic lives inline in shortcode templates - No sorting (filter only for pkg-list) - No pagination (count param caps changelog entries)