Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
c1cc945
Add categories and tags placeholders to blog post templates
mrbiggred Feb 24, 2026
602c2f0
Refactor reminder messages in create_post.sh to be consistent with th…
mrbiggred Feb 24, 2026
5a5618e
Refactor date calculation in create_post.sh for compatibility with ma…
mrbiggred Feb 24, 2026
e768f37
Add comment to category and tag section reminding people to use exist…
mrbiggred Feb 25, 2026
7700ed3
Fix indentation in YAML frontmatter comments and correct typo in READ…
mrbiggred Feb 25, 2026
6073e57
Add a script to harvest tags and categories. Initially by Grok, then…
normanlorrain Feb 25, 2026
57a0a98
restored the mistakenly auto-formatted lines
normanlorrain Feb 25, 2026
9e8a387
Refactor find_tags_categories.py to use string parsing instead of YAM…
mrbiggred Mar 9, 2026
17ee852
Printer out tags in alphabetical order
mrbiggred Mar 9, 2026
2ad9497
Moved the find tags script from docs/ to the new scripts/ folder.
mrbiggred Mar 9, 2026
a0e47b4
Fixed path to find tags script in create post scripts.
mrbiggred Mar 9, 2026
49848f9
Updated documentation about the find tags script.
mrbiggred Mar 9, 2026
82a366a
Removed unneeded check.
mrbiggred Mar 9, 2026
fe91f73
Moved discard tags to outside the loop.
mrbiggred Mar 9, 2026
ed97a82
Updated README tag/category examples to match the scripts
mrbiggred Mar 9, 2026
f0d1cae
Python should be launched with "py" or "python",
normanlorrain Mar 9, 2026
c5317c8
Re-added the YAML library to the find tags script.
mrbiggred Mar 17, 2026
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
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ These scripts will:
authors:
- chris
categories:
- Category Name
# use existing categories when possible, in YAML list format.
- CATEGORY_ONE
- CATEGORY_TWO
tags:
- relevant-tag
# use existing tags when possible, in YAML list format.
- TAG_ONE
- TAG_TWO
---
```

Expand All @@ -116,11 +120,21 @@ These scripts will:

### Categories and Tags

Categories are broad topic groupings and tags are specific topic labels for filtering. New categories and tags can be added as needed — these are the ones currently in use.
Categories are broad topic groupings and tags are specific topic labels for filtering. **Please use existing categories and tags when possible** to keep the taxonomy consistent. New ones can be added when truly needed.

**Categories**: Business, Career, Community, Culture, Security, Technical
To see all categories and tags currently in use, run:

**Tags**: `administration`, `advent-of-code`, `advent-of-cyber`, `agile`, `ai`, `architecture`, `branding`, `cancelled`, `career`, `change-management`, `claude`, `code-quality`, `coding-challenges`, `coding-practices`, `community`, `conferences`, `creativity`, `ctf`, `culture`, `curriculum`, `cybersecurity`, `data`, `databases`, `design-patterns`, `devops`, `editors`, `education`, `entrepreneurship`, `ergonomics`, `estimation`, `ethics`, `events`, `finance`, `github-copilot`, `goals`, `gratitude`, `growth`, `habits`, `hacktoberfest`, `hardware`, `health`, `hiring`, `history`, `holiday`, `industry`, `infrastructure`, `innovation`, `inspiration`, `irl`, `job-market`, `learning`, `local-tech`, `marketing`, `meetup`, `meetups`, `metaphors`, `methodology`, `metrics`, `mob-programming`, `motivation`, `naming`, `networking`, `open-discussion`, `open-source`, `optimization`, `organizations`, `pair-programming`, `performance`, `philosophy`, `picoctf`, `predictions`, `priorities`, `privacy`, `productivity`, `project-management`, `prototyping`, `quality-assurance`, `reflection`, `remote-work`, `resilience`, `security`, `self-hosting`, `self-improvement`, `side-projects`, `society`, `supply-chain`, `surveys`, `swap-meet`, `systems`, `tdd`, `teaching`, `teamwork`, `technology`, `testing`, `thinking`, `time-management`, `tools`, `trends`, `unconference`, `version-control`, `watch-party`, `wellness`, `work-life-balance`, `workplace`, `workspace`, `year-in-review`
**Bash (Linux/macOS)**:
```bash
python3 scripts/find_tags_categories.py
```

**PowerShell (Windows)**:
```powershell
python scripts/find_tags_categories.py
```

This script requires `pyyaml`, which is included in `requirements.txt`. It is also run automatically by the `create_post` scripts when scaffolding a new post.

## Project Structure

Expand All @@ -131,6 +145,8 @@ Categories are broad topic groupings and tags are specific topic labels for filt
├── docker-compose.yml # Docker development environment
├── create_post.sh # Bash script to create blog posts
├── create_post.ps1 # PowerShell script to create blog posts
├── scripts/
│ └── find_tags_categories.py # List all existing tags and categories
├── .github/
│ ├── dependabot.yml # Dependabot configuration
│ └── workflows/
Expand Down
13 changes: 12 additions & 1 deletion create_post.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ title: "$title"
date: $date
authors:
- chris | norm | omar
categories:
# use existing categories when possible, in YAML list format.
- CATEGORY_ONE
- CATEGORY_TWO
tags:
# use existing tags when possible, in YAML list format.
- TAG_ONE
- TAG_TWO
---

TOPIC_INTRODUCTION_HERE
Expand All @@ -55,4 +63,7 @@ Everyone and anyone are welcome to [join](https://weeklydevchat.com/join/) as lo
# Write the content to the file
Set-Content -Path $filePath -Value $yamlContent

Write-Output "Blog post template created at $filePath"
Write-Output "Blog post template created at $filePath"
Write-Output ""
Write-Output "Reminder: Use existing categories and tags when possible."
python "./scripts/find_tags_categories.py"
32 changes: 24 additions & 8 deletions create_post.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
#!/bin/bash

# Calculate the next Tuesday (or today if it's Tuesday)
# In Linux date, weekday: 0=Sunday, 1=Monday, ..., 6=Saturday
current_weekday=$(date +%w) # 0=Sun ... 6=Sat
days_to_tuesday=$(( (2 - current_weekday + 7) % 7 ))

# If today is Tuesday, days_to_tuesday will be 0 → perfect
# Add the calculated days
tuesday=$(date -d "+${days_to_tuesday} days" +%Y-%m-%d)
# Add the calculated days (compatible with both macOS and Linux)
if date -v +0d &>/dev/null; then
# macOS (BSD date)
tuesday=$(date -v "+${days_to_tuesday}d" +%Y-%m-%d)
else
# Linux (GNU date)
tuesday=$(date -d "+${days_to_tuesday} days" +%Y-%m-%d)
fi

year=$(date -d "$tuesday" +%Y)
month=$(date -d "$tuesday" +%02m)
day=$(date -d "$tuesday" +%02d)
year=${tuesday%%-*} # 2026
month=${tuesday#*-}; month=${month%-*} # 02
day=${tuesday##*-} # 24

# Define paths
folder_path="docs/posts/$year/$month/$day"
Expand All @@ -27,6 +31,14 @@ title: "Your Blog Post Title"
date: $tuesday
authors:
- chris | norm | omar
categories:
# use existing categories when possible, in YAML list format.
- CATEGORY_ONE
- CATEGORY_TWO
tags:
# use existing tags when possible, in YAML list format.
- TAG_ONE
- TAG_TWO
---

TOPIC_INTRODUCTION_HERE
Expand All @@ -36,4 +48,8 @@ Everyone and anyone are welcome to [join](https://weeklydevchat.com/join/) as lo
![alt text](${tuesday}_image_filename.webp)
EOF

echo "Blog post template created at $file_path"
echo "Blog post template created at $file_path"
echo ""
echo "Reminder: Use existing categories and tags when possible."

python3 "./scripts/find_tags_categories.py"
75 changes: 75 additions & 0 deletions scripts/find_tags_categories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""
Lists all unique tags and categories found in YAML front matter of .md files.
Looks for both 'tags' and 'categories' keys (common variations).
"""

import yaml
from pathlib import Path

DOCS_DIR = Path(__file__).parent.parent / "docs"
EXTENSIONS = (".md", ".markdown", ".mkd")


def extract_frontmatter(file_path: Path) -> dict[str, list[str]]:
Comment on lines +9 to +14
"""Extract YAML front matter if present."""
content = file_path.read_text(encoding="utf-8")
if not content.startswith("---"):
return {}
try:
parts = content.split("---", 2)
if len(parts) < 3:
return {}
fm = yaml.safe_load(parts[1])
if not isinstance(fm, dict):
return {}
return fm
except yaml.YAMLError:
print(f"Warning: Invalid YAML in {file_path}")
return {}


def collect_tags() -> tuple[set[str], set[str]]:
all_tags = set()
all_categories = set()

docs_path = Path(DOCS_DIR)
if not docs_path.is_dir():
print(f"Error: Directory not found: {docs_path}")
return all_tags, all_categories

for file_path in docs_path.rglob("*"):
if not file_path.is_file() or file_path.suffix.lower() not in EXTENSIONS:
continue

fm = extract_frontmatter(file_path)

tags = fm.get("tags", [])
all_tags.update(str(t).strip() for t in tags if t)

cats = fm.get("categories", [])
all_categories.update(str(c).strip() for c in cats if c)
Comment on lines +47 to +51

all_tags.discard('TAG_ONE')
all_tags.discard('TAG_TWO')
all_categories.discard('CATEGORY_ONE')
all_categories.discard('CATEGORY_TWO')

return all_tags, all_categories


def main() -> None:
tags, categories = collect_tags()

print("\nExisting categories:")
for cat in sorted(categories):
print(f" {cat}")
print(f"\nExisting tags:")
for tag in sorted(tags):
print(f" {tag}")


if __name__ == "__main__":
main()


Loading