diff --git a/README.md b/README.md
index b0935da0..22449c3e 100644
--- a/README.md
+++ b/README.md
@@ -142,7 +142,7 @@ Additionally, as of May 2026, Nubenetes has reached the **Platinum Operational T
| :--- | :--- |
| **Total Technical Resources (Links)** | **18647+** |
| **Specialized MD Pages** | **162** |
-| **Total Commits** | **6397+** |
+| **Total Commits** | **6402+** |
| **Primary AI Engine** | **Google Gemini (Agentic)** |
@@ -180,7 +180,7 @@ The growth of Nubenetes reflects the acceleration of the Cloud Native ecosystem.
| 6 | 2023 | 30 | 123 | Maintenance & Refinement |
| 7 | 2024 | 53 | 218 | Curation Strategy Pivot |
| 8 | 2025 | 5 | 20 | Stability & Research Phase |
-| 9 | 2026 | 2838 | 11,720 | **Agentic AI Surge** (May 2026 Inception) |
+| 9 | 2026 | 2843 | 11,741 | **Agentic AI Surge** (May 2026 Inception) |
@@ -196,8 +196,8 @@ xychart-beta
title "Nubenetes Annual Growth Metrics (2018–2026)"
x-axis ["2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026"]
y-axis "Volume (Commits / Estimated New Refs)" 0 --> 12000
- bar [1445, 586, 8449, 2193, 1660, 123, 218, 20, 11720]
- bar [350, 142, 2046, 531, 402, 30, 53, 5, 2838]
+ bar [1445, 586, 8449, 2193, 1660, 123, 218, 20, 11741]
+ bar [350, 142, 2046, 531, 402, 30, 53, 5, 2843]
```
@@ -207,7 +207,7 @@ xychart-beta
| :--- | :---: | :---: | :--- |
| 2026-04 | 25 | 103 | Active Curation |
| 2026-05 | 2101 | 8,677 | **Agentic Inception (Gemini Era)** |
-| 2026-06 | 712 | 2,940 | Active Curation |
+| 2026-06 | 717 | 2,961 | Active Curation |
### 2.4. Content Distribution and Semantic Clustering
diff --git a/data/news_digest.json b/data/news_digest.json
index cd525b18..a880a52d 100644
--- a/data/news_digest.json
+++ b/data/news_digest.json
@@ -7440,6 +7440,6 @@
"method": "fallback_small"
}
},
- "last_updated": "2026-06-20T19:22:20.010536+02:00"
+ "last_updated": "2026-06-20T19:40:49.213297+02:00"
}
}
\ No newline at end of file
diff --git a/src/v2_optimizer.py b/src/v2_optimizer.py
index b2fcc77b..72f79ead 100644
--- a/src/v2_optimizer.py
+++ b/src/v2_optimizer.py
@@ -1142,6 +1142,18 @@ class V2VisionEngine:
" - **Status**: The system is incrementally processing pending resources to complete the knowledge graph.\n"
)
+ # Label Heatmap for the index: identical tag aggregation to the Tags page
+ # (deterministic slugs), but each label deep-links across to /tags/#slug.
+ heat_sorted, heat_meta, _ = self._aggregate_tags(data)
+ index_heatmap = self._render_tag_heatmap(
+ heat_sorted, heat_meta, href_base="/tags/",
+ intro=(
+ "Every technical label across Nubenetes, sized by how many "
+ "resources carry it. Click any label to open it on the "
+ "[Technical Tags](/tags/) page."
+ ),
+ )
+
index_md = (
"# Nubenetes Elite Portal (V2) | Awesome Kubernetes & Cloud [](https://github.com/sindresorhus/awesome)\n\n"
"!!! tip \"Nubenetes V2 Elite Portal: AI-Curated & High-Density\"\n"
@@ -1220,6 +1232,9 @@ class V2VisionEngine:
f"{pulse_md}\n\n"
"## The Cloud Native Universe We Track\n\n"
f"
\n{mosaic_html}\n\n\n"
+ # Label Heatmap: full tag cloud sized by resource count, deep-linking
+ # to the matching section on the Technical Tags page (cross-page).
+ f"{index_heatmap}"
"---\n\n"
"**Reference:** [🗺️ Full Topic Map](./topic-map/) · "
"[📐 Methodology & Maturity Taxonomy](./methodology/) · "
@@ -1535,7 +1550,16 @@ class V2VisionEngine:
if md != existing_content:
with open(target_path, "w") as f: f.write(md)
- async def _generate_global_tag_index(self, v2_structure: Dict[str, Dict]):
+ def _aggregate_tags(self, v2_structure: Dict[str, Dict]):
+ """Collect every active resource's tags into deterministic, slug-stable
+ metadata shared by the Technical Tags page and the index Label Heatmap.
+
+ Returns (sorted_tags, tag_meta, by_tag) where tag_meta[tag] holds
+ ``display``, ``slug``, ``count`` and ``kind`` (maturity | language |
+ domain). The slug logic is identical to (and deterministic with) what the
+ Tags page renders, so the heatmap on the index can deep-link to the right
+ ``/tags/#slug`` section even though it is generated in a separate pass.
+ """
active_links = {}
def collect_links(node):
if "__links__" in node:
@@ -1579,23 +1603,10 @@ class V2VisionEngine:
"[LEGACY]",
"[SPANISH CONTENT]"
]
-
- sorted_tags = []
- for st in standard_order:
- if st in by_tag:
- sorted_tags.append(st)
-
- custom_tags = sorted([t for t in by_tag.keys() if t not in standard_order])
- sorted_tags.extend(custom_tags)
- md = (
- "# Technical Tags Index\n\n"
- "!!! tip \"Nubenetes V2 Elite Portal\"\n"
- " You are browsing the AI-Curated V2 Elite Edition. Looking for the exhaustive list of references? Check out the [**V1 Historical Archive**](/v1/).\n\n"
- "!!! info \"Universal Tag Index\"\n"
- " Browse all V2 resources grouped by maturity levels and technical domains.\n\n"
- )
-
+ sorted_tags = [st for st in standard_order if st in by_tag]
+ sorted_tags.extend(sorted(t for t in by_tag.keys() if t not in standard_order))
+
# Precompute display name + UNIQUE slug for every tag, shared by both the
# grouped TOC and the section headers so anchors always match. This fixes
# collisions where C / C# / C++ all slugged to "c-content" (broken links).
@@ -1618,59 +1629,91 @@ class V2VisionEngine:
_seen_slugs.add(s)
return s
+ def _tag_kind(tag):
+ if tag in standard_order:
+ return "maturity"
+ if tag.endswith("CONTENT]"):
+ return "language"
+ return "domain"
+
tag_meta = {
- tag: {"display": _tag_display(tag), "slug": _tag_slug(tag), "count": len(by_tag[tag])}
+ tag: {
+ "display": _tag_display(tag),
+ "slug": _tag_slug(tag),
+ "count": len(by_tag[tag]),
+ "kind": _tag_kind(tag),
+ }
for tag in sorted_tags
}
+ return sorted_tags, tag_meta, by_tag
+
+ def _render_tag_heatmap(self, sorted_tags, tag_meta, href_base: str = "", intro: str = None) -> str:
+ """Confluence-style "popular labels" Label Heatmap: every label is listed
+ alphabetically and sized/coloured by how many resources carry it, so the
+ most-used tags read biggest/warmest. Sizing uses a LOG scale because counts
+ span ~1..2800; a linear scale would collapse everything except the few giant
+ maturity tags into the smallest bucket. Six levels map onto .v2-heat-1..6.
+
+ ``href_base`` is prefixed before each ``#slug`` so the same cloud can live on
+ the Tags page (same-page anchors, "") or the index (cross-page, "/tags/").
+ """
+ counts = [tag_meta[t]["count"] for t in sorted_tags]
+ if not counts:
+ return ""
+ lmin, lmax = math.log(min(counts)), math.log(max(counts))
+
+ def _heat_level(count):
+ if lmax == lmin:
+ return 3
+ return 1 + round((math.log(count) - lmin) / (lmax - lmin) * 5) # 1..6
+
+ if intro is None:
+ intro = (
+ "Bigger, warmer labels cover more resources. "
+ "Click any label to jump to its section below."
+ )
+ md = f"## Label Heatmap\n\n{intro}\n\n"
+ md += '\n'
+ for t in sorted(sorted_tags, key=lambda x: tag_meta[x]["display"].lower()):
+ m = tag_meta[t]
+ disp = m["display"].replace(" Content", "")
+ lvl = _heat_level(m["count"])
+ md += (
+ f'
{disp}'
+ f'{m["count"]}\n'
+ )
+ md += "
\n\n"
+ return md
+
+ async def _generate_global_tag_index(self, v2_structure: Dict[str, Dict]):
+ sorted_tags, tag_meta, by_tag = self._aggregate_tags(v2_structure)
+
+ md = (
+ "# Technical Tags Index\n\n"
+ "!!! tip \"Nubenetes V2 Elite Portal\"\n"
+ " You are browsing the AI-Curated V2 Elite Edition. Looking for the exhaustive list of references? Check out the [**V1 Historical Archive**](/v1/).\n\n"
+ "!!! info \"Universal Tag Index\"\n"
+ " Browse all V2 resources grouped by maturity levels and technical domains.\n\n"
+ )
def _count_label(n):
return f"{n} resource" + ("" if n == 1 else "s")
# Partition custom tags: language/format ("X CONTENT") vs technical domains,
# so the long, low-signal language tail does not bury the maturity tags.
- maturity_tags = [t for t in sorted_tags if t in standard_order]
+ maturity_tags = [t for t in sorted_tags if tag_meta[t]["kind"] == "maturity"]
lang_tags = sorted(
- [t for t in sorted_tags if t not in standard_order and t.endswith("CONTENT]")],
+ [t for t in sorted_tags if tag_meta[t]["kind"] == "language"],
key=lambda t: -tag_meta[t]["count"],
)
other_tags = sorted(
- [t for t in sorted_tags if t not in standard_order and not t.endswith("CONTENT]")],
+ [t for t in sorted_tags if tag_meta[t]["kind"] == "domain"],
key=lambda t: -tag_meta[t]["count"],
)
- # Label Heatmap (Confluence-style "popular labels" cloud): every label is
- # listed alphabetically and sized/coloured by how many resources carry it,
- # so the most-used tags read biggest/warmest. Clicking jumps to the section.
- # Sizing uses a LOG scale because counts span ~1..2800; a linear scale would
- # collapse everything except the few giant maturity tags into the smallest
- # bucket. Six levels map onto the .v2-heat-1..6 CSS ramp.
- _heat_counts = [tag_meta[t]["count"] for t in sorted_tags]
- if _heat_counts:
- _cmin, _cmax = min(_heat_counts), max(_heat_counts)
- _lmin, _lmax = math.log(_cmin), math.log(_cmax)
-
- def _heat_level(count):
- if _lmax == _lmin:
- return 3
- frac = (math.log(count) - _lmin) / (_lmax - _lmin)
- return 1 + round(frac * 5) # 1..6
-
- md += "## Label Heatmap\n\n"
- md += (
- "Bigger, warmer labels cover more resources. "
- "Click any label to jump to its section below.\n\n"
- )
- md += '\n'
- for t in sorted(sorted_tags, key=lambda x: tag_meta[x]["display"].lower()):
- m = tag_meta[t]
- disp = m["display"].replace(" Content", "")
- lvl = _heat_level(m["count"])
- md += (
- f'
{disp}'
- f'{m["count"]}\n'
- )
- md += "
\n\n"
+ # Label Heatmap at the top of the Tags page (same-page anchors).
+ md += self._render_tag_heatmap(sorted_tags, tag_meta, href_base="")
# Build a grouped TOC: maturity as a clean numbered list; domains and the
# language/format tail as compact, count-sorted inline pill rows.
diff --git a/v2-docs/index.md b/v2-docs/index.md
index 375d8e85..27d0e0bd 100644
--- a/v2-docs/index.md
+++ b/v2-docs/index.md
@@ -203,6 +203,88 @@
+## Label Heatmap
+
+Every technical label across Nubenetes, sized by how many resources carry it. Click any label to open it on the [Technical Tags](/tags/) page.
+
+
+
---
**Reference:** [🗺️ Full Topic Map](./topic-map/) · [📐 Methodology & Maturity Taxonomy](./methodology/) · [🎥 Agentic Video Hub](./videos/index.md)
diff --git a/v2-mkdocs.yml b/v2-mkdocs.yml
index 66a9d395..5d2612e4 100644
--- a/v2-mkdocs.yml
+++ b/v2-mkdocs.yml
@@ -29,9 +29,12 @@ theme:
icon: material/shield-moon-outline
name: Switch to dark mode
features:
- # navigation.tabs / .sticky disabled: 18 top-level sections overflowed
- # the tab bar (horizontal scroll). The left sidebar handles them as a
- # standard vertical list and stays populated on every page incl. home.
+ # navigation.tabs: top-level sections render as a top tab bar AND the left
+ # sidebar stays, scoped to the active tab. With ~16 top-level sections the
+ # bar can overflow on narrow viewports; Material handles that with a
+ # horizontal scroll, and .sticky keeps the bar pinned while scrolling.
+ - navigation.tabs
+ - navigation.tabs.sticky
- navigation.top
- navigation.tracking
# navigation.sections disabled: render top-level as COLLAPSIBLE nested