Tooling that turns daily Bodhisattva Challenge verse/practice text into finished social-media post images: batch-generates line-art illustrations with Gemini, then composes them with text into branded 1080x1920 posts (English, Tibetan, and Hindi).
Project description • Who this project is for • Project dependencies • Instructions for use • Contributing guidelines • How to get help • Terms of use
This project automates production of the daily Bodhisattva Challenge posts
for @WeBuddhist. It has three stages, each a
standalone CLI script under src/illustration_generator/:
generate_illustrations.py— Parses aVerse_and_challenge.mdfile (verses in Tibetan with English practice/explanation), submits a batch job to Gemini 3 Pro Image to generate three line-art illustrations per verse (verse-only, practice-only, combined), and saves them per-verse with transparent backgrounds.compose_challenge_post.py— Composes a single-language (English) daily "challenge" post: title, bold practice, illustration, left-aligned verse with right-aligned verse id citation, and the@WeBuddhisthandle, rendered onto a background template.compose_multilang_post.py— Composes the same style of post in three languages (English, Tibetan, Hindi) from oneday_NN_sharable_image_text.mdfile containing all three language sections, producing one image per language underdata/output/<language>/day{N}.png.generate_preview_post.py— Generates an alternate "preview" post layout (verse + explanation + bottom-anchored illustration) matching a reference template, with an optional--comparemode to measure pixel difference against a reference image.
This project is intended for the OpenPecha/WeBuddhist team producing the daily Bodhisattva Challenge social media content, who want to generate illustrations and compose branded post images from markdown source text.
Before using this project, ensure you have:
- Python >= 3.8 (Tibetan/Hindi text uses
list[str]/str | Nonesyntax, so 3.10+ recommended) - A Gemini API key (set as the
GEMINI_KEYenvironment variable) forgenerate_illustrations.py - Pillow built with
libraqmfor correct Tibetan/Devanagari text shaping (used bycompose_multilang_post.py). Verify with:python -c "import PIL.features as f; print(f.check('raqm'))" - Bundled fonts under
src/illustration_generator/fonts/(already included in the repo)
pip install -e .
# or with dev/test dependencies
pip install -e ".[dev]"Export your Gemini API key (only required for generate_illustrations.py):
export GEMINI_KEY="your-api-key-here"1. Generate illustrations from a verse markdown file:
python -m illustration_generator.generate_illustrations path/to/Verse_and_challenge.mdCreates one verse_<N>/ folder per verse next to the markdown file, each with
illustration_1.png (verse), illustration_2.png (practice), and
illustration_3.png (combined), all with transparent backgrounds.
2. Compose a single-language challenge post:
# from a daily folder containing a 06_July.md and one illustration PNG
python -m illustration_generator.compose_challenge_post path/to/06_July_folder
# or pass files explicitly
python -m illustration_generator.compose_challenge_post path/to/06_July.md path/to/illustration.png3. Compose multi-language (English/Tibetan/Hindi) posts:
python -m illustration_generator.compose_multilang_post \
path/to/day_20_sharable_image_text.md \
path/to/illustration_or_dir \
--output path/to/output_dirOutputs output_dir/english/day20.png, output_dir/tibetan/day20.png, and
output_dir/hindi/day20.png (default output dir is data/output/).
4. Generate a preview-style post:
python -m illustration_generator.generate_preview_post path/to/06_July_folder
# optionally compare against a reference image
python -m illustration_generator.generate_preview_post path/to/06_July_folder --compare data/17.jpg| Issue | Solution |
GEMINI_KEY environment variable not set |
Export GEMINI_KEY with a valid Gemini API key before running generate_illustrations.py. |
| Tibetan/Devanagari text renders incorrectly (no stacking/conjuncts) | Rebuild Pillow with libraqm support; verify with the snippet in Project dependencies. |
No date markdown file like 06_July.md found / Multiple date markdown files found |
Ensure the target folder has exactly one markdown file matching the expected naming pattern. |
Missing required field(s) when parsing markdown |
Confirm the markdown file has the expected headings (e.g. Practice of the day, Verse of the day, Verse id). |
If you'd like to help out, check out our contributing guidelines.
- File an issue.
- Email us at openpecha[at]gmail.com.
- Join our discord.
This project is licensed under the MIT License.