Skip to content

Refactor blog section (/blog/)#253

Open
Gijsreyn wants to merge 3 commits into
dsccommunity:masterfrom
Gijsreyn:refactor-blog-section
Open

Refactor blog section (/blog/)#253
Gijsreyn wants to merge 3 commits into
dsccommunity:masterfrom
Gijsreyn:refactor-blog-section

Conversation

@Gijsreyn
Copy link
Copy Markdown
Contributor

@Gijsreyn Gijsreyn commented May 17, 2026

This pull request redesigns the /blog/ listing page and individual blog post layout by reducing clutter, adding structure (PSDSC, Microsoft DSC, and Community), and improving readability (TOC).

Each section now has a distinct icon, title, and description header seen at local runtime:

image

The blog post is more narrow with a TOC added:

image

With the new frontmatter (dsc_family), it gets controlled on which section posts are added. Lastly, there was a small template fix as this was from older Hugo versions (type: "post") e.g. Hugo's template lookup uses the type field to pick a layouts subfolder — with type: "post"it searchedlayouts/post/(non-existent), skipped blog, and fell back tosingle.html` (which rendered the "all blog posts" sidebar). Without an explicit type, Hugo defaults to the section name (blog) and correctly resolves to single.html.


This change is Reviewable

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Review Change Stack

Warning

Rate limit exceeded

@Gijsreyn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 51 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 859842e3-31bd-4d80-a69e-60b738ae62cc

📥 Commits

Reviewing files that changed from the base of the PR and between c707f93 and 6df2bf1.

📒 Files selected for processing (1)
  • layouts/community/maintainers.html

Walkthrough

The PR reorganizes how blog posts are discovered and displayed by introducing a dsc_family metadata field to categorize posts, then refactoring templates and adding interactivity to support table-of-contents sidebars and category-based grouping throughout the site.

Changes

Blog categorization and TOC enhancement for article discovery

Layer / File(s) Summary
Blog metadata schema migration
archetypes/blog.md, content/blog/...
Blog archetype and 14 blog posts updated: type: "post" field removed and dsc_family field added with values assigned to "Microsoft DSC", "PowerShell DSC", or "Community".
TOC infrastructure setup
config.toml, assets/css/futuristic.css
Hugo table-of-contents configuration added (startLevel: 2, endLevel: 3, ordered: false). CSS custom properties reformatted and new styles added for .article-with-toc two-column grid, sticky .article-toc sidebar, .toc-nav link states with .toc-active highlighting, and .blog-section-header section title styles.
Single article layout with TOC sidebar
layouts/blog/single.html
Article header redesigned with hero gradient background and updated typography; category badge logic switched to prefer .Params.dsc_family with fallback to .Params.categories. Main content refactored to max-width 1100px with conditional right-side TOC sidebar when .TableOfContents is present; previous/next navigation removed.
TOC scroll tracking and active highlighting
assets/js/main.js
New initTocHighlight() function added to track scroll position (with 80px offset) and toggle toc-active class on TOC links matching the currently-visible article heading. Function called on DOMContentLoaded. Minor formatting adjustments in existing scroll event handlers and search result templates.
Blog list template grouping by dsc_family
layouts/blog/list.html
Blog listing refactored from single all-posts grid to three conditional sections grouped by dsc_family value. Each section (Microsoft DSC, PowerShell DSC, Community+uncategorized) iterates over grouped pages and renders card UI with date, title, summary, and optional reading time. Generic tag-filter UI removed.
GitHub API error handling improvement
layouts/community/maintainers.html
GitHub user data fetch now explicitly checks remote resource .Err and logs detailed warning with API URL and error details; JSON unmarshaling only occurs on success, leaving $data unchanged on fetch failure.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dsccommunity/dsccommunity.org#248: Introduces the foundational site layout redesign and CSS/JavaScript base that this PR extends with TOC-specific styling and active-link tracking functionality.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor blog section (/blog/)' accurately describes the main change—restructuring the blog listing and post layout with new organization and styling.
Description check ✅ Passed The description is directly related to the changeset, clearly explaining the blog section redesign, new dsc_family frontmatter field, and the Hugo template fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
layouts/blog/list.html (1)

10-15: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Localize the new list-page UI copy via i18n keys.

The new section titles, descriptions, CTA text, and action labels are hardcoded. Please move these literals to localization keys and update translation files alongside this template change.

As per coding guidelines, "Localize all strings using string keys; remove any orphaned string keys."

Also applies to: 38-40, 77-79, 98-99, 117-119, 138-139, 152-154, 164-171

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layouts/blog/list.html` around lines 10 - 15, The template hardcodes UI copy
(e.g., "Knowledge Base", the .hero-title "Blog Posts", .hero-description
paragraph and other CTA/action labels referenced at lines 38-40, 77-79, 98-99,
117-119, 138-139, 152-154, 164-171); replace each literal with an i18n key
lookup using the project's template translation helper (same pattern as other
localized templates), add corresponding keys to the translation files for all
supported locales, and remove/rename any orphaned string keys so keys and
template usage remain synchronized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/js/main.js`:
- Around line 368-370: initTocHighlight currently resolves TOC targets with
document.querySelector(link.getAttribute("href")) and then assumes headings[0]
and current.id exist; fix by robustly resolving hrefs: for hash-only hrefs use
the id lookup path (extract href.slice(1), decodeURIComponent and call
document.getElementById) to avoid CSS selector escaping issues, and for other
hrefs fall back to querySelector inside a try/catch to ignore invalid selectors;
then filter out falsy results into headings and guard uses of headings[0] and
current (e.g., check headings.length > 0 and current != null before accessing
current.id) so no throws occur when headings is empty or selectors are invalid
(referencing initTocHighlight, tocLinks, headings, and current.id).

In `@content/blog/create-an-article.en.md`:
- Line 6: Add a new entry to CHANGELOG.md under the "Unreleased" section
documenting the blog metadata change (dsc_family: "Community") and the updated
TOC behavior introduced by this PR; mention the affected file
content/blog/create-an-article.en.md and briefly summarize the change (metadata
addition and TOC behavior change) so the Unreleased section records the PR
impact.

In `@layouts/blog/list.html`:
- Around line 109-123: Merged collection $generalPages (created by append
$communityPages $uncategorized) is not re-sorted so posts from both sources
aren’t in global chronological order; after you create $generalPages, run Hugo’s
sort on the Date (e.g., sort $generalPages "Date" "desc") and use that sorted
value in the subsequent range. Locate the $generalPages assignment and the range
that iterates it, replace the range source with the sorted collection (or
reassign $generalPages to the sorted result) so items are globally ordered by
Date descending.

In `@layouts/blog/single.html`:
- Around line 8-11: The "Back to Blog" anchor and other hardcoded UI texts
(e.g., the anchor with class "btn btn-ghost" containing the literal "Back to
Blog" and the other literals noted at the same template) must be replaced with
Hugo i18n string keys and the corresponding translations added to the site's
i18n files; update the template to call the i18n helper (use a key like
"back_to_blog") instead of the literal, and add that key and translations to
your i18n JSON/TOML/YAML so the UI is translatable and consistent with the repo
policy.

In `@layouts/community/maintainers.html`:
- Around line 70-78: Wrap the resources.GetRemote call in try and check the
returned error object instead of relying on .Err on the raw call: call try
resources.GetRemote with $path and $opts, capture the result (e.g., assign to a
variable), then test that variable's .Err before proceeding to
transform.Unmarshal and set $data; ensure you still use transform.Unmarshal and
assign to $data only when the try result has no error and contains Content.

---

Outside diff comments:
In `@layouts/blog/list.html`:
- Around line 10-15: The template hardcodes UI copy (e.g., "Knowledge Base", the
.hero-title "Blog Posts", .hero-description paragraph and other CTA/action
labels referenced at lines 38-40, 77-79, 98-99, 117-119, 138-139, 152-154,
164-171); replace each literal with an i18n key lookup using the project's
template translation helper (same pattern as other localized templates), add
corresponding keys to the translation files for all supported locales, and
remove/rename any orphaned string keys so keys and template usage remain
synchronized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8ec9e247-f6b3-4ccc-a3c3-f24018fe0a32

📥 Commits

Reviewing files that changed from the base of the PR and between 6229ee8 and c707f93.

📒 Files selected for processing (21)
  • archetypes/blog.md
  • assets/css/futuristic.css
  • assets/js/main.js
  • config.toml
  • content/blog/DSC-is-dead-long-live-dsc.en.md
  • content/blog/add-codecov-support-to-repository.md
  • content/blog/class-based-dsc-resources.md
  • content/blog/convert-a-module-for-continuous-delivery.en.md
  • content/blog/convert-master-to-main.en.md
  • content/blog/convert-tests-to-pester5-for-dsc-community-repository.md
  • content/blog/converting-tests-to-pester5.md
  • content/blog/create-an-article.en.md
  • content/blog/dsc-maintenance-windows.en.md
  • content/blog/how-to-use-dsc-logging.en.md
  • content/blog/updating-sampler-github-tasks.md
  • content/blog/use-dscresource-common-functions-in-module.en.md
  • content/blog/what-is-microsoft-dscv3.md
  • content/blog/your-first-class-based-microsoft-dsc-v3-resource.md
  • layouts/blog/list.html
  • layouts/blog/single.html
  • layouts/community/maintainers.html

Comment thread assets/js/main.js
Comment on lines +368 to +370
const headings = tocLinks
.map((link) => document.querySelector(link.getAttribute("href")))
.filter(Boolean);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant region around the referenced lines
nl -ba assets/js/main.js | sed -n '330,430p'

# Also locate initTocHighlight definition and any reference to "current.id"
rg -n "function initTocHighlight|initTocHighlight|current\\.id|tocLinks|headings" assets/js/main.js

Repository: dsccommunity/dsccommunity.org

Length of output: 116


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba assets/js/main.js | sed -n '330,430p'
rg -n "function initTocHighlight|initTocHighlight|current\\.id|tocLinks|headings" assets/js/main.js

Repository: dsccommunity/dsccommunity.org

Length of output: 116


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba assets/js/main.js | sed -n '330,430p'
rg -n "function initTocHighlight|initTocHighlight|current\\.id|tocLinks|headings" assets/js/main.js

Repository: dsccommunity/dsccommunity.org

Length of output: 116


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== initTocHighlight + related identifiers ==="
rg -n "function initTocHighlight|initTocHighlight|current\\.id|tocLinks|headings" assets/js/main.js || true

echo
echo "=== Lines 340-420 ==="
sed -n '340,420p' assets/js/main.js

Repository: dsccommunity/dsccommunity.org

Length of output: 2554


Harden TOC highlighting against invalid hash selectors and empty headings

initTocHighlight() resolves TOC targets with document.querySelector(link.getAttribute("href")), treating the hash as a raw CSS selector (can throw for valid HTML ids needing escaping). It also assumes headings[0] exists; when headings is empty, current.id will throw.

Proposed fix
-  const headings = tocLinks
-    .map((link) => document.querySelector(link.getAttribute("href")))
-    .filter(Boolean);
+  const headings = tocLinks
+    .map((link) => decodeURIComponent(link.getAttribute("href").slice(1)))
+    .map((id) => document.getElementById(id))
+    .filter(Boolean);
+  if (headings.length === 0) return;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const headings = tocLinks
.map((link) => document.querySelector(link.getAttribute("href")))
.filter(Boolean);
const headings = tocLinks
.map((link) => decodeURIComponent(link.getAttribute("href").slice(1)))
.map((id) => document.getElementById(id))
.filter(Boolean);
if (headings.length === 0) return;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/js/main.js` around lines 368 - 370, initTocHighlight currently
resolves TOC targets with document.querySelector(link.getAttribute("href")) and
then assumes headings[0] and current.id exist; fix by robustly resolving hrefs:
for hash-only hrefs use the id lookup path (extract href.slice(1),
decodeURIComponent and call document.getElementById) to avoid CSS selector
escaping issues, and for other hrefs fall back to querySelector inside a
try/catch to ignore invalid selectors; then filter out falsy results into
headings and guard uses of headings[0] and current (e.g., check headings.length
> 0 and current != null before accessing current.id) so no throws occur when
headings is empty or selectors are invalid (referencing initTocHighlight,
tocLinks, headings, and current.id).

type: "post"
weight: 1
draft: false
dsc_family: "Community"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing required CHANGELOG update for this PR.

Please add an entry to CHANGELOG.md under the Unreleased section to document the
blog metadata and TOC behavior changes.

As per coding guidelines, "Always update CHANGELOG.md Unreleased section".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@content/blog/create-an-article.en.md` at line 6, Add a new entry to
CHANGELOG.md under the "Unreleased" section documenting the blog metadata change
(dsc_family: "Community") and the updated TOC behavior introduced by this PR;
mention the affected file content/blog/create-an-article.en.md and briefly
summarize the change (metadata addition and TOC behavior change) so the
Unreleased section records the PR impact.

Comment thread layouts/blog/list.html
Comment on lines +109 to +123
{{ $generalPages := $communityPages | append $uncategorized }}
{{ if gt (len $generalPages) 0 }}
<div class="blog-section" style="margin-bottom: var(--space-16);">
<div class="blog-section-header">
<span class="blog-section-icon" style="background: linear-gradient(135deg, #7c3aed 0%, #a78bfa 100%);">
<i class="ri-community-line"></i>
</span>
<div>
<h2 class="blog-section-title">Community</h2>
<p class="blog-section-description">News, guides, and how-tos from the DSC Community</p>
</div>
</a>
{{ end }}
</div>
<div class="grid-auto stagger">
{{ range $generalPages }}
<a href="{{ .Permalink }}" class="card blog-card card-link">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Re-sort merged Community + uncategorized posts by Date

$generalPages is built by append-ing $communityPages and $uncategorized, but the merged collection is never re-sorted—so dates won’t be globally chronological across both groups.

Proposed fix
-    {{ $generalPages := $communityPages | append $uncategorized }}
+    {{ $generalPages := sort ($communityPages | append $uncategorized) "Date" "desc" }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{ $generalPages := $communityPages | append $uncategorized }}
{{ if gt (len $generalPages) 0 }}
<div class="blog-section" style="margin-bottom: var(--space-16);">
<div class="blog-section-header">
<span class="blog-section-icon" style="background: linear-gradient(135deg, #7c3aed 0%, #a78bfa 100%);">
<i class="ri-community-line"></i>
</span>
<div>
<h2 class="blog-section-title">Community</h2>
<p class="blog-section-description">News, guides, and how-tos from the DSC Community</p>
</div>
</a>
{{ end }}
</div>
<div class="grid-auto stagger">
{{ range $generalPages }}
<a href="{{ .Permalink }}" class="card blog-card card-link">
{{ $generalPages := sort ($communityPages | append $uncategorized) "Date" "desc" }}
{{ if gt (len $generalPages) 0 }}
<div class="blog-section" style="margin-bottom: var(--space-16);">
<div class="blog-section-header">
<span class="blog-section-icon" style="background: linear-gradient(135deg, `#7c3aed` 0%, `#a78bfa` 100%);">
<i class="ri-community-line"></i>
</span>
<div>
<h2 class="blog-section-title">Community</h2>
<p class="blog-section-description">News, guides, and how-tos from the DSC Community</p>
</div>
</div>
<div class="grid-auto stagger">
{{ range $generalPages }}
<a href="{{ .Permalink }}" class="card blog-card card-link">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layouts/blog/list.html` around lines 109 - 123, Merged collection
$generalPages (created by append $communityPages $uncategorized) is not
re-sorted so posts from both sources aren’t in global chronological order; after
you create $generalPages, run Hugo’s sort on the Date (e.g., sort $generalPages
"Date" "desc") and use that sorted value in the subsequent range. Locate the
$generalPages assignment and the range that iterates it, replace the range
source with the sorted collection (or reassign $generalPages to the sorted
result) so items are globally ordered by Date descending.

Comment thread layouts/blog/single.html
Comment on lines +8 to 11
<a href="/blog" class="btn btn-ghost" style="margin-bottom: var(--space-6); color: rgba(255,255,255,0.75); border-color: rgba(255,255,255,0.2);">
<i class="ri-arrow-left-line"></i>
Back to Blog
</a>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Localize newly added UI strings instead of hardcoded literals.

This template introduces new user-facing text directly in markup. Please move these to localization keys (for example via Hugo i18n) so the blog UI stays translatable and consistent with repo policy.

Suggested direction
- Back to Blog
+ {{ i18n "blogBackToBlog" }}

- <div style="font-size: var(--text-xs); color: rgba(255,255,255,0.5);">Author</div>
+ <div style="font-size: var(--text-xs); color: rgba(255,255,255,0.5);">{{ i18n "authorLabel" }}</div>

- <h4 class="toc-heading"> ... On this page ... </h4>
+ <h4 class="toc-heading"> ... {{ i18n "onThisPage" }} ... </h4>

As per coding guidelines, "Localize all strings using string keys; remove any orphaned string keys."

Also applies to: 41-42, 74-75, 89-90, 113-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layouts/blog/single.html` around lines 8 - 11, The "Back to Blog" anchor and
other hardcoded UI texts (e.g., the anchor with class "btn btn-ghost" containing
the literal "Back to Blog" and the other literals noted at the same template)
must be replaced with Hugo i18n string keys and the corresponding translations
added to the site's i18n files; update the template to call the i18n helper (use
a key like "back_to_blog") instead of the literal, and add that key and
translations to your i18n JSON/TOML/YAML so the UI is translatable and
consistent with the repo policy.

Comment thread layouts/community/maintainers.html Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant