{"slug": "hugo-tag-based-post-connections", "title": "hugo: tag-based post connections", "summary": "Perrotta's blog now displays tag-based post connections, adding a second edge type that links up to two posts sharing the most tags, excluding direct links, with shared-tag edges rendered as dashed and muted lines. The pre-computation function and CSS styles were updated, and tests pass, enhancing the blog's graph visualization.", "body_md": "♠ [Previously](https://perrotta.dev/2026/08/llm-devise-a-plan/).\n\n**Problem statement**: post connections showed only direct links, while posts\nwith the same tags remained disconnected in the graph of this blog.\n\nI added a second kind of edge. The pre-computation picks up to two posts with\nthe **most shared tags**, breaks ties by date, and excludes direct links:\n\n``` python\ndef compute_tag_related_posts(\n    post: dict,\n    all_posts: list[dict],\n    outlinks_set: set[str],\n    backlinks_set: set[str],\n    limit: int = 2,\n) -> list[str]:\n    \"\"\"Compute tag connections, excluding posts with direct links.\"\"\"\n    post_tags = set(post[\"tags\"])\n    if not post_tags:\n        return []\n\n    direct_ids = outlinks_set | backlinks_set\n    scored = []\n    for other in all_posts:\n        other_id = other[\"id\"]\n        if other_id == post[\"id\"] or other_id in direct_ids:\n            continue\n\n        shared_tags = post_tags & set(other[\"tags\"])\n        if shared_tags:\n            scored.append((other_id, len(shared_tags), other[\"date\"]))\n\n    scored.sort(key=lambda item: (item[1], item[2], item[0]), reverse=True)\n    return [item[0] for item in scored[:limit]]\n```\n\nDirect links remain directional, solid, and prominent. Shared-tag links are symmetric, dashed, and muted:\n\n```\n.mini-graph .mini-graph-direct-edge {\n  fill: none;\n  stroke: var(--link-color);\n  stroke-width: 2.25;\n  stroke-opacity: 0.9;\n}\n\n.mini-graph .mini-graph-tag-edge {\n  fill: none;\n  stroke: var(--color-gray);\n  stroke-width: 1;\n  stroke-dasharray: 4 4;\n  stroke-opacity: 0.65;\n}\n```\n\nThe original [Anki post](https://perrotta.dev/2026/07/anki-archive-a-deck/) now gets\none direct link and two tag connections:\n\n```\n{\n  \"outlinks\": [\"2024-12-23-anki-workflow\"],\n  \"tag_related\": [\n    \"2026-04-15-anki-flashcards-with-claude-code\",\n    \"2026-04-13-anki-api-access\"\n  ]\n}\n% python3 ci/test_precompute_links.py\n..\n----------------------------------------------------------------------\nRan 2 tests in 0.000s\n\nOK\n```\n\nThere’s a limit of 2 shared tag post edges for the sake of not visually polluting the presentation.\n\nI’ve been loving how this little blog is evolving into my beloved (public) digital garden.\n\n🤖 *Drafted with * ∎\n\n`/bloggify`\n\n.— § —\n\nReply via [email](mailto:serendipity@perrotta.dev?subject=Reply to: hugo: tag-based post connections)", "url": "https://wpnews.pro/news/hugo-tag-based-post-connections", "canonical_source": "https://perrotta.dev/2026/08/hugo-tag-based-post-connections/", "published_at": "2026-08-22 11:29:06+00:00", "updated_at": "2026-08-22 11:44:03.515359+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Perrotta", "Hugo", "Anki"], "alternates": {"html": "https://wpnews.pro/news/hugo-tag-based-post-connections", "markdown": "https://wpnews.pro/news/hugo-tag-based-post-connections.md", "text": "https://wpnews.pro/news/hugo-tag-based-post-connections.txt", "jsonld": "https://wpnews.pro/news/hugo-tag-based-post-connections.jsonld"}}