How the make_content.py Script Generates Monthly HelloGitHub Issues from Templates
The make_content.py script automates HelloGitHub's monthly issue creation by injecting period-specific markdown into a shared template using simple string replacement.
The HelloGitHub repository curates a monthly collection of interesting open-source projects. To maintain consistent formatting across every issue, the script/make_content/make_content.py utility generates final markdown files by merging a common template with issue-specific content, eliminating manual copy-pasting and formatting errors.
Core Template Mechanism
The generation system relies on two placeholder strings inside template.md:
{{ hello_github_num }}— injected with the two-digit issue number (e.g.,01,02){{ hello_github_content }}— replaced by the entire contents of the period-specificcontentXX.mdfile
Rather than using a heavy templating engine like Jinja2, the script performs lightweight substitution via Python's native str.replace() method. This keeps the dependency footprint minimal while allowing quick manual edits to the template layout.
Step-by-Step Generation Workflow
1. Argument Parsing and Routing
Execution begins in main() (lines 80‑98), which inspects sys.argv to determine the target issue. The script accepts either a two-digit issue number (e.g., python make_content.py 02) or the keyword all to trigger bulk generation.
2. Path Resolution and Validation
For single-issue generation, make_content() (lines 55‑58) constructs absolute paths for three critical files:
template.md(repository root)content/<num>/content<num>.md(period-specific source)content/<num>/HelloGitHub<num>.md(final output destination)
Before processing, check_path() (lines 33‑41) verifies that both the template and the source content file exist. If either is missing, the function returns None and halts execution.
3. Template Processing and Content Injection
The script loads file contents using read_file() (lines 44‑51). It performs two sequential replacements on the template string:
- Replaces
{{ hello_github_num }}with the issue number passed via command line - Replaces
{{ hello_github_content }}with the raw markdown fromcontentXX.md
This merge occurs at line 65 in make_content(): output_data = temple_data.replace(CONTENT_FLAG, content_data).
4. Output Generation
Finally, write_file() (lines 67‑68) persists the merged markdown to content/<num>/HelloGitHub<num>.md. The resulting file contains the standardized layout with the period's curated projects injected at the appropriate position.
Bulk Generation Mode
When invoked with the all argument, make_all_content() (lines 71‑76) walks the repository root directory, skips the script folder, and iterates over every numeric subdirectory (e.g., 01, 02, 03). It delegates to make_content() for each folder found, allowing maintainers to regenerate the entire historical archive whenever template.md receives global styling updates.
Practical Usage Examples
Generate a Single Issue
python script/make_content/make_content.py 02
Result: Creates or overwrites content/02/HelloGitHub02.md by merging template.md with content/02/content02.md.
Regenerate All Historical Issues
python script/make_content/make_content.py all
Result: Rewrites every HelloGitHubXX.md file in the repository, propagating any template changes across all periods.
Minimal Template Structure
# HelloGitHub {{ hello_github_num }}
{{ hello_github_content }}
---
*Curated with ❤️ by HelloGitHub*
Summary
- The
make_content.pyscript lives atscript/make_content/make_content.pyand serves as HelloGitHub's automated publishing engine. - It expects a
template.mdfile at the repository root containing{{ hello_github_num }}and{{ hello_github_content }}placeholders. - Single issues are generated via
make_content(), which validates paths, performs dual string replacement, and writes tocontent/<XX>/HelloGitHub<XX>.md. - Batch processing is handled by
make_all_content(), which iterates numeric directories and delegates to the single-issue generator. - The implementation uses native Python
str.replace()rather than external templating libraries for simplicity and speed.
Frequently Asked Questions
What are the exact placeholder strings required in template.md?
The script searches for two literal strings: {{ hello_github_num }} (replaced by the two-digit issue number) and {{ hello_github_content }} (replaced by the entire contents of the period's source file). These are defined as constants in the script and must match exactly, including spaces.
Can I regenerate all historical issues at once?
Yes. Pass the all argument to the script: python script/make_content/make_content.py all. The make_all_content() function will scan all numeric directories and regenerate every merged issue file, ensuring consistent formatting across the entire archive.
Where does the script look for input files?
According to the source code in lines 55‑58, the script resolves paths relative to the repository root: it expects template.md at the root level, reads content from content/<num>/content<num>.md, and writes output to content/<num>/HelloGitHub<num>.md.
Does the script require a templating engine like Jinja2?
No. As implemented in line 65 of make_content.py, the script uses standard Python string methods (str.replace()) to substitute placeholders. This design choice keeps the tool lightweight and eliminates external dependencies beyond the Python standard library.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →