Thank you for your interest in contributing to awesome-pyladies-creations! This repository collects blogs, YouTube channels, podcasts, and Python packages created by PyLadies members from around the world, as well as individual PyLadies members and local chapters. The goal is to make this work more visible and to celebrate the community's contributions.
There are four ways to contribute:
| What | Where |
|---|---|
| Blog, YouTube channel, or podcast | data/content/ |
| Python package | data/packages/ |
| Yourself as a PyLadies member | data/members/ |
| A PyLadies chapter | data/chapters/ |
Not sure where to start? Open an issue and I'll help you out!
awesome-pyladies-creations celebrates what PyLadies members create and share with the world. PyLadies is an international mentorship group focused on helping more women and people of all genders become active participants and leaders in the Python open-source community.
Entries you add may be shared by the PyLadies Mastodon bot and the PyLadies Bluesky bot, which automatically promote new blog posts and videos to the wider community. By submitting an entry you agree to this use.
Choose the path that suits you best:
Not comfortable with JSON or GitHub? Open a pre-filled issue and I'll create the file for you.
- Add a blog
- Add a YouTube channel
- Add a podcast
- Add a Python package
- Add yourself as a member
- Add a PyLadies chapter
Each entry is a single JSON file. Click a link below to open a pre-filled template on GitHub, fill it in, and open a pull request.
Create a new file in data/content/ using this template link.
{
"title": "Ada's Python Blog",
"type": "blog",
"url": "https://ada.dev/blog",
"photo_url": "https://ada.dev/avatar.png",
"language": "en",
"authors": [
{
"name": "Ada Lovelace",
"social_media": [{ "github": "adalovelace", "mastodon": "@ada@fosstodon.org" }]
}
]
}| Field | Required | Description |
|---|---|---|
title |
β | Title of the blog, channel, or podcast |
type |
β | One of "blog", "youtube", "podcast" |
url |
β | Canonical URL of the content |
language |
β | ISO 639-1 code, e.g. "en" |
authors |
β | List of author objects β see Authors |
photo_url |
Recommended | Profile picture or logo URL; shown as the card thumbnail |
rss_feed |
Recommended | RSS/Atom feed URL; required for the Mastodon/Bluesky bot to pick up posts |
description |
Optional | Short description of the content; shown on the card |
subtitle |
Optional | Tagline or subtitle (alternative to description) |
Use the content URL as the filename β strip www. and https://, replace / with .:
- Blog at
cosimameyer.comβcosimameyer.com.json - YouTube channel
youtube.com/@PyLadiesBerlinβyoutube.com.@PyLadiesBerlin.json - Podcast at
pod.example.comβpod.example.com.json
One file = one piece of content. If you have both a blog and a YouTube channel, add two files.
photo_url is shown as a circular thumbnail on your card. Use a profile photo, avatar, or your blog's logo. YouTube channel avatars and GitHub profile pictures work well.
The rss_feed field is used by the bots to discover and share new posts automatically.
- Blog β a Python-specific feed is ideal (category/tag feed). A general feed is accepted.
- YouTube β the channel or playlist feed URL. See RSS feed for YouTube below.
- Podcast β the podcast's RSS feed.
Finding your RSS feed β Quarto
Add the following under the listing key in index.qmd (see Quarto docs):
feed:
categories: [Python]The feed URL will be [url]/blog/index.xml (all posts) or a category-specific variant.
Finding your RSS feed β Distill
Distill requires a workaround: generate a categories/ folder containing each category's index.xml and preserve it across renders.
Finding your RSS feed β Hugo
Hugo Academic β RSS is enabled by default; use the category front matter field. See this guide.
Hugo Portio β copy Hugo's default RSS template to layouts/_default/rss.xml and replace {{ .Summary | html }} with {{ .Content | html }}.
Finding your RSS feed β Medium
Medium explains how to find your RSS feed. Tag-specific feeds are not available; please only post Python-related content so bot followers stay on topic.
Set type: "youtube" and use the channel or playlist feed URL in rss_feed. First find your channel or playlist ID (how to), then assemble:
- Channel:
https://www.youtube.com/feeds/videos.xml?channel_id=CHANNEL_ID - Playlist:
https://www.youtube.com/feeds/videos.xml?playlist_id=PLAYLIST_ID
- File is in
data/content/and ends with.json -
title,type,url,language, andauthors[].nameare filled in -
typeis one of"blog","youtube", or"podcast" -
photo_urlpoints to a working image URL -
rss_feedis filled in (required for bot promotion) - All
social_mediavalues are bare handles, not full URLs (exceptwebsiteandmastodon) - No
//requiredor//optionalcomments remain in the file - Optional fields you don't want are removed entirely, not left empty
Create a new file in data/packages/ using this template link.
{
"name": "my-package",
"description": "A Python tool for doing amazing things.",
"repo_url": "https://github.com/yourusername/my-package",
"pypi_url": "https://pypi.org/project/my-package/",
"maintainers": [
{
"name": "Ada Lovelace",
"social_media": [{ "github": "adalovelace" }]
}
]
}| Field | Required | Description |
|---|---|---|
name |
β | Package identifier β usually the PyPI package name (slug, lowercase) |
maintainers |
β | List of maintainer objects β see Authors |
description |
Recommended | One-sentence description of what the package does |
pypi_url |
Recommended | Full PyPI URL (https://pypi.org/project/...) |
repo_url |
Recommended | Source repository URL (e.g. GitHub) |
title |
Optional | Display name if different from name (e.g. capitalised) |
logo_url |
Optional | Package logo image URL |
docs_url |
Optional | Documentation site URL |
bug_reports_url |
Optional | Issue tracker URL |
last_updated |
Optional | Date of last meaningful release, YYYY-MM-DD |
namevstitleβnameis the unique identifier used in the filename and internally.titleis what appears on the card. Iftitleis omitted,nameis used as the display name.
- File is in
data/packages/and ends with.json -
nameandmaintainers[].nameare filled in -
pypi_urlorrepo_urlis provided so the card is clickable - Optional fields you don't want are removed entirely, not left empty
If you identify as a PyLadies member and want to appear in the directory, create a file in data/members/. Name the file after yourself, e.g. jane-doe.json.
Your member file is the authoritative source for your profile: photo and social handles here take precedence over what appears in any content or package entry you're associated with.
{
"name": "Ada Lovelace"
}{
"name": "Ada Lovelace",
"photo_url": "https://example.com/ada.png",
"social_media": [{
"github": "adalovelace",
"x": "adalovelace",
"mastodon": "@ada@fosstodon.org",
"bluesky": "@ada.bsky.social",
"linkedin": "ada-lovelace",
"instagram": "adalovelace",
"website": "https://ada.dev"
}]
}| Field | Required | Description |
|---|---|---|
name |
β | Your display name |
photo_url |
Recommended | Profile photo URL; shown as a circular avatar on your card |
social_media |
Optional | List of one dict with any platforms you want shown |
- File is in
data/members/and ends with.json -
nameis filled in -
photo_urlpoints to a working image URL (if provided)
Create a new file in data/chapters/. Name the file after the chapter's city or region, e.g. berlin.json.
{
"name": "PyLadies Berlin",
"city": "Berlin",
"country": "Germany"
}{
"name": "PyLadies Berlin",
"city": "Berlin",
"country": "Germany",
"lat": 52.52,
"lon": 13.405,
"website": "https://berlin.pyladies.com",
"email": "berlin@pyladies.com",
"photo_url": "https://example.com/berlin_logo.png",
"social_media": [{
"github": "pyladies-berlin",
"x": "PyLadiesBerlin",
"mastodon": "@pyladiesberlin@fosstodon.org",
"bluesky": "@pyladiesberlin.bsky.social",
"instagram": "pyladiesberlin",
"linkedin": "company/pyladies-berlin",
"meetup": "PyLadies-Berlin",
"facebook": "PyLadiesBerlin",
"youtube": "@PyLadiesBerlin",
"website": "https://berlin.pyladies.com"
}]
}| Field | Required | Description |
|---|---|---|
name |
β | Full chapter name, e.g. "PyLadies Berlin" |
city |
β | City of the chapter |
country |
β | Country of the chapter |
lat / lon |
Recommended | Decimal coordinates for the map pin (auto-filled by CI if missing) |
photo_url |
Recommended | Chapter logo URL; shown as a circular avatar on the card |
website |
Optional | Chapter website URL |
email |
Optional | Contact email |
social_media |
Optional | List of one dict with any platforms (see Social Media) |
Coordinates β if
lat/lonare not provided, a GitHub Action will attempt to geocode them automatically fromcity+countryafter your PR is merged.
- File is in
data/chapters/and ends with.json -
name,city, andcountryare filled in -
photo_urlpoints to a working image URL (if provided) - Social media handles are bare usernames, not full URLs (except
websiteandmastodon)
If your chapter has a YouTube channel or blog, you can also add a content entry in data/content/ (following the Content format above). Add "chapter": true at the top level so the site places it in the Chapters section instead of the People section:
{
"title": "PyLadies Berlin",
"type": "youtube",
"url": "https://www.youtube.com/@PyLadiesBerlin",
"photo_url": "https://example.com/berlin_logo.png",
"chapter": true,
"authors": [{ "name": "PyLadies Berlin", "social_media": [{ "youtube": "@PyLadiesBerlin" }] }]
}The chapter card will be enriched with the content entry's photo, social links, and RSS feed (for the bots). If no data/chapters/ file exists yet, the content entry alone is enough to create a chapter card.
To update β find your file in the relevant data/ folder, click the pencil icon on GitHub to edit it directly in your browser, and open a pull request. No local setup needed.
To remove β open an issue or contact me directly and I'll take care of it promptly.
- Automated checks run β CI validates your JSON against the schema and checks that social handles are consistent across all files for the same person. If something fails, the PR will show an error with details.
- Review β I'll review the PR and may leave comments or suggestions.
- Merge β once merged, the site regenerates automatically. Your entry will be live on the next GitHub Pages deployment (usually within a minute or two).
An entry can have multiple authors β for example, a collaborative blog or a YouTube channel with multiple hosts.
"authors": [
{
"name": "Ada Lovelace",
"social_media": [{ "x": "adalovelace", "github": "adalovelace" }]
},
{
"name": "Grace Hopper",
"social_media": [{ "linkedin": "gracehopper", "website": "https://grace.dev" }]
}
]For guest-blogger or community channels, list the editors/maintainers as the primary authors:
"authors": [
{ "name": "Jane Smith" },
{ "name": "Guest bloggers" }
]Social media handles are stored as a list containing one object. Use bare handles β the site adds the base URL automatically.
"social_media": [{
"github": "username",
"x": "username",
"mastodon": "@username@instance.social",
"bluesky": "@username.bsky.social",
"linkedin": "username",
"instagram": "username",
"youtube": "@handle",
"meetup": "group-name",
"facebook": "pagename",
"website": "https://yoursite.com"
}]Special formats:
| Platform | Format | Example |
|---|---|---|
mastodon |
@username@instance |
@ada@fosstodon.org |
bluesky |
@username.domain |
@ada.bsky.social |
linkedin |
username for people; company/slug for orgs |
company/pyladies-berlin |
youtube |
@handle or username/end-url |
@PyLadiesBerlin |
website |
full URL | https://ada.dev |
All other platforms take a plain username with no @ prefix and no URL.
Use ISO 639-1 codes: "en", "de", "fr", "pt", etc. This helps the site and bots categorise content correctly.
If you need help at any step, open an issue or reach out directly.