You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Link calendar entries back to their user group - #526
themes/powershell-community/layouts/
├── _default/calendar.html # upcoming card: <a> → <div>, title/arrow become their own links,
│ # badge slotted into the meta row on both upcoming + past cards
└── partials/
+ ├── calendar-matched-user-group.html # match externalUrl's Meetup host → user-group page+ └── calendar-user-group-badge.html # render logo/icon + name link to /user-groups/<slug>/
content/calendar/ohio-powershell-user-group.md # drop now-redundant hand-written group link
docs/adr/0006-calendar-user-group-linking.md # why: runtime URL match, not a stored field
flowchart LR
A[calendar entry<br/>Params.externalUrl] -->|meetup.com host| B[calendar-matched-user-group.html]
B -->|scans| C[/user-groups/*.md<br/>Params.links/]
C -->|slug match| D[matched Page]
D --> E[calendar-user-group-badge.html]
E -->|renders| F[logo/icon + name<br/>→ /user-groups/slug/]
Loading
Matching happens at render time against the Meetup slug embedded in both
the calendar entry's externalUrl and the user group's links[].url — no
new frontmatter field, no resync of existing entries. Rationale and
rejected alternatives (explicit userGroup field, hybrid) are in ADR 0006.
Evidence
Before: calendar cards were visually identical regardless of source
group; the whole card was one <a> to the external event, with no path
back to the group's page (Ohio's one manual entry had a hand-written
prose link as the only exception).
After: built the site with hugo --gc and inspected public/calendar/index.html:
15/15 Meetup-linked entries (13 synced + 2 hand-authored, including one
I'd initially miscategorized as a plain conference until its externalUrl turned out to be a Meetup link) render a badge to the
correct /user-groups/<slug>/ page.
Groups with a logo (Ohio, Swiss, Inn-Salzach) render their image;
groups without one (Hamburg, Research Triangle) fall back to the same fa-people-group icon the user-groups list page already uses.
Genuine non-group conferences (PSConfEU, Summit, SQL Saturday, Day of
Data) confirmed to render with no badge — unchanged.
Blast Radius:/calendar/ page only. Upcoming-event cards change
structure (no longer one whole-card link; title and the arrow icon are now
separate click targets), which is a layout/interaction change worth a
visual check but not a breaking one — no other templates or content
schemas are touched.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved issues include stale badge styles, incorrect Meetup URL matching, accessibility problems, and missing user-group links on individual event pages.
Adds links from calendar entries to their user-group pages by matching Meetup group slugs at Hugo build time, without adding front matter fields or resyncing events.
Changes:
Adds reusable group-matching and logo/name badge partials.
Displays badges on upcoming and past events, with separate event links on upcoming cards.
Documents the approach and removes Ohio’s hand-written group link.
Fixed oversized user-group logo badges reported in the field. Added native width="20" height="20" attributes to the badge <img> so sizing is pinned at the HTML level, not solely by Tailwind classes — verified locally that the image stays 20×20 even with the stylesheet disabled entirely. Pushed in 9b2d502.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
A date-dependent CSS purge can fail CI when no upcoming events exist, while group matching, event-page navigation, and accessibility defects remain unresolved.
The logo and adjacent group title are both included in the link's accessible name, so screen readers announce the group name twice. Since the text already identifies the destination, please mark the logo as decorative.
Calendar entries whose externalUrl is a Meetup link now render a small
logo/icon + name badge linking back to the owning user group's page,
matched at render time by Meetup URL host rather than a stored field
(see docs/adr/0006). Upcoming cards are restructured from a single
whole-card anchor to separate title and arrow links so the badge can
be its own link without nesting anchors. Removes the now-redundant
hand-written group link in the Ohio calendar entry.
The logo rendered oversized in the field (user report w/ screenshot);
Tailwind sizing classes alone weren't enough to constrain it in that
environment. Adding native width/height HTML attributes makes the
sizing robust independent of CSS load order/purge state — verified
locally that the image stays pinned at 20x20 even with Tailwind CSS
disabled entirely.
- Anchor Meetup host match to scheme+host (case-insensitive), no
longer false-matches lookalike hosts like notmeetup.com
- Swap Tailwind v3-only classes (shrink-0, text-[10px]) for v2
equivalents (flex-shrink-0, text-xs) actually supported by the
pinned Tailwind 2.2.19 build
- Safelist group-hover:text-purple-600 in purgecss config since it
only renders inside the upcoming-events loop and would otherwise be
purged on a build with zero upcoming events
- Mark the badge logo as decorative (empty alt) since the adjacent
group name already supplies the link's accessible name
- Give each upcoming-card arrow link a unique aria-label including
the event title
- Drop opacity-75 from past-event cards so the badge (and all past
card text) keeps sufficient contrast; existing gray tones already
distinguish past from upcoming
- Render the group badge on individual calendar event pages too, so
removing Ohio's hand-written prose link doesn't orphan that page
Meetup host matching — anchored the regex to ^https?://(?:www\.)?meetup\.com/, case-insensitive. Verified with go run against lookalikes (notmeetup.com, meetup.com.evil.com) and an uppercase-host URL — all behave correctly now.
Tailwind v2 compatibility — swapped shrink-0/text-[10px] (Tailwind v3-only syntax, silently absent from the pinned v2.2.19 build) for flex-shrink-0/text-xs.
Safelisted group-hover:text-purple-600 in purgecss.config.cjs since it only appears in the built HTML when an upcoming event exists — a CI run with zero upcoming events would otherwise purge it.
Decorative badge logo — alt="" on the <img>; the link's accessible name now comes once from the adjacent group-name text instead of twice.
Unique arrow aria-labels — now View details for {{ .Title }} per event instead of one repeated label.
Past-card contrast — dropped the card-wide opacity-75; the existing gray palette (bg/border/text) already reads as "past" without alpha-blending the new blue badge below 4.5:1.
Individual event pages — the calendar-matched-user-group partial now also renders on _default/single.html for the calendar section, so Ohio's event page (and every other group-linked event's own page) still links back to its group now that the hand-written prose link is gone.
All verified live: rebuilt assets/css/tailwind.css/icons (byte-identical, confirming nothing was missing), ran a local Hugo dev server, and checked in a real browser — decorative alt present, 3 unique arrow labels, past cards have no opacity-75, and the Ohio single event page now renders the group badge. Also rebased onto latest origin/main.
- Add a persistent underline to the event-title link (previously only
color-coded on hover, with the external-link icon hidden below md
— no visible indicator at all on touch devices)
- Add a persistent underline to the group badge link for the same
reason (blue-on-gray color alone is an insufficient indicator)
- Skip an optional locale prefix (e.g. /de-DE/) before the group slug
when parsing Meetup URLs, so localized links don't parse 'de-DE' as
the slug
- Compare extracted slugs case-insensitively, since group submissions
preserve URL casing as entered while synced event URLs come from
Meetup's own (lowercase) feed
Addressed the 4th-round findings and resolved all review threads (11/11):
Persistent link indicators (non-color) — added underline to both the event-title link and the group badge link. Previously the title had no visible affordance until hover (and the external-link icon is hidden below md, so touch devices had zero indication it was tappable), and the badge's blue-on-gray was color-only.
Locale-prefixed Meetup URLs — the slug regex now skips an optional /xx-XX/ locale segment before capturing the group slug, so meetup.com/de-DE/powershell-usergroup-inn-salzach/ resolves to powershell-usergroup-inn-salzach, not de-DE. Verified with go run against a locale-prefixed, a plain, and a non-Meetup URL.
Case-insensitive slug comparison — group URLs preserve submitter casing while synced event URLs come from Meetup's own feed; slugs are now lowercased before comparing.
Also manually resolved the 5 threads that were still open from the prior round even though the fixes had already landed (Ohio's event page badge, Tailwind v2 class swap, the group-hover safelist, and past-card opacity) — GitHub's bot had auto-resolved some equivalent threads but not these, so I confirmed each fix against the pushed branch content before resolving.
The previous locale-prefix regex used (?i) across the whole pattern,
so the lowercase-language/lowercase-region shape it was matching
(e.g. [a-z]{2}-[a-z]{2}) also matched legitimate two-letter-pair group
slugs like 'ps-ug': the group's own URL (.../ps-ug/) still resolved
correctly by regex backtracking, but its event URLs
(.../ps-ug/events/123/) misfired, consuming 'ps-ug' as a locale and
capturing 'events' as the slug instead.
Scope (?i) to the scheme+host only via Go's (?flags:re) syntax, and
require Meetup's actual locale convention — lowercase language,
UPPERCASE region (de-DE, en-US) — to recognize a locale prefix. Real
Meetup group slugs are always lowercase, so this cleanly disambiguates
without needing to inspect path depth. Verified with go run against
both the locale and two-letter-slug cases; confirmed no regression
against the 4 real synced groups (still 15/15 badges).
Fixed the locale-detection regression (ps-ug style two-letter-pair group slugs misidentified as locale prefixes):
Scoped (?i) to scheme+host only (via Go's (?flags:re) syntax) and tightened the locale sub-pattern to require Meetup's actual convention — lowercase language, uppercase region (de-DE, en-US) — rather than any lowercase xx-xx shape. Real Meetup group slugs are always lowercase, so this cleanly distinguishes a locale prefix from a slug without needing to inspect path depth, and without the case-insensitive flag accidentally folding the region code to lowercase and making every two-letter-pair slug look like a locale.
Verified with go run against both cases (de-DE/groupslug/ and bare ps-ug/events/123/), and confirmed no regression against the live site: still 15/15 badges across all 4 real synced groups after rebuilding and checking in a browser.
Pushed as 0298ba5ad. All 12/12 review threads now resolved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Matching happens at render time against the Meetup slug embedded in both
the calendar entry's
externalUrland the user group'slinks[].url— nonew frontmatter field, no resync of existing entries. Rationale and
rejected alternatives (explicit
userGroupfield, hybrid) are inADR 0006.
Evidence
group; the whole card was one
<a>to the external event, with no pathback to the group's page (Ohio's one manual entry had a hand-written
prose link as the only exception).
hugo --gcand inspectedpublic/calendar/index.html:I'd initially miscategorized as a plain conference until its
externalUrlturned out to be a Meetup link) render a badge to thecorrect
/user-groups/<slug>/page.logo(Ohio, Swiss, Inn-Salzach) render their image;groups without one (Hamburg, Research Triangle) fall back to the same
fa-people-groupicon the user-groups list page already uses.Data) confirmed to render with no badge — unchanged.
Merge Danger
Door: Two-way — template/partial change only, trivially revertable.
Blast Radius:
/calendar/page only. Upcoming-event cards changestructure (no longer one whole-card link; title and the arrow icon are now
separate click targets), which is a layout/interaction change worth a
visual check but not a breaking one — no other templates or content
schemas are touched.