58ef5122acbfd966ca4e533e632384deb31c031b
Wiki.js Blog Writer Pipeline
Automated pipeline that fetches a page from a Wiki.js instance, turns it into a blog post using Google Gemini, translates it, and publishes it back to the wiki under /blog/.
How it works
Wiki.js page → SOURCE.md → BLOGPOST.md → TRANSLATED_BLOGPOST.md → Wiki.js /blog/
fetch write translate upload
- fetch — Downloads a Wiki.js page as Markdown via GraphQL
- write — Gemini reads
INSTRUCTIONS.mdand writes a blog post fromSOURCE.mdin the configured language - translate — Gemini translates the blog post into the target language
- upload — Publishes the translated post to Wiki.js under
/blog/{kebab-case-title}; creates the page if it doesn't exist, updates it if it does
Requirements
- Python 3.8+
- A running Wiki.js instance with API access
- A Google Gemini API key (get one free at aistudio.google.com)
Setup
1. Clone the repo and enter the directory
git clone <your-repo>
cd blog_writer
2. Copy the example env file and fill in your values
cp .env.example .env
| Variable | Description |
|---|---|
WIKI_BASE_DOMAIN |
Base URL of your Wiki.js instance, e.g. https://wiki.example.com |
WIKI_TOKEN |
Wiki.js API bearer token (Admin → API Access) |
GEMINI_API_KEY |
Google Gemini API key |
ORIGINAL_LANG |
Language for the generated blog post (default: Hungarian) |
TRANSLATE_LANG |
Target language for translation (default: English) |
3. Create an INSTRUCTIONS.md file
This file tells Gemini how to write the blog post — tone, structure, length, style, etc. Example:
Write an engaging blog post aimed at a general technical audience.
Use a friendly but professional tone. Keep it under 600 words.
Start with a short hook, then summarize the key points, and end with a call to action.
Do not use bullet points — write in flowing paragraphs.
Usage
# Fetch a wiki page
make fetch URL=/path/to/page
# Generate the blog post
make write
# Translate it
make translate
# Upload to Wiki.js
make upload
# Run the full pipeline (write → translate → upload)
make all
make fetchmust be run separately with aURLargument beforemake all.
File overview
| File | Description |
|---|---|
tool.py |
Main Python script |
Makefile |
Convenience wrapper around tool.py |
.env |
Your local environment variables (never commit this) |
.env.example |
Example env file safe to commit |
INSTRUCTIONS.md |
Gemini prompt instructions for blog post style |
SOURCE.md |
Raw Markdown fetched from Wiki.js |
BLOGPOST.md |
Generated blog post in ORIGINAL_LANG |
TRANSLATED_BLOGPOST.md |
Translated blog post in TRANSLATE_LANG |
Notes
- The
# H1title is extracted fromTRANSLATED_BLOGPOST.mdand used as both the Wiki.js page title and the URL slug — it is stripped from the content body to avoid duplication. - If a page already exists at the target path, it will be updated rather than duplicated.
- Add
.env,SOURCE.md,BLOGPOST.md, andTRANSLATED_BLOGPOST.mdto your.gitignore.
Description
Languages
Python
94.5%
Makefile
5.5%