Joel Kalich's Scripts for Ghost
Scripts for extending Ghost functionality on Joel+.
LLMs were used to assist in the creation of these scripts. I have tested them and they seem to work well on my Ghost instance.
Both scripts are configured via a .env file placed next to them (not via
editing the scripts themselves).
- Copy
.env.exampleto.env. - Fill in the values —
.env.exampledocuments every variable, which script uses it, and what it does. - Run either script. It automatically loads
.envfrom its own directory before doing anything else, and will exit with an error naming any required variable that's still unset.
.env is gitignored, so your Ghost admin key and PeerTube credentials never
get committed.
There's no separate script/state directory to configure — each script writes
its seen-id file (and --test/cron output goes wherever you redirect it) next
to itself, wherever you've placed it.
Checks YouTube for new Community posts and cross-posts them to Ghost.
- Supports
--testmode:- Creates draft Ghost posts instead of public ones.
- Does not add the YouTube post ID to the seen-posts file.
- Supports
--initmode:- Creates the seen posts file.
- Populates file with existing YouTube posts.
- Does not make any draft or public posts to Ghost at all.
- Stores seen YouTube post IDs in a text file to prevent duplicate posts.
- Detects the YouTube post type and reflects it in the Ghost post title.
- Tags Ghost posts with a specified tag.
- Uses the first line of the YouTube post text as the Ghost subtitle.
- Embeds the YouTube post as a Ghost bookmark card.
- Extracts the first YouTube post image and uses it as the Ghost feature image.
- Notifies Ghost members via email by publishing a draft, then changing the post to published.
- It does not fully replicate YouTube Community posts inside Ghost.
- Polls, quizzes, and other interactive post types would be silly to replicate, so instead it just links to YouTube.
- The logic could likely be updated to replicate text posts and image posts, and link to YouTube for interactive posts, but that is not implemented.
Fill in .env (see Configuration above)
- Set
YOUTUBE_CHANNEL_ID.- This is not your (for example)
@JoelKalichhandle, it's a unique ID generated by YouTube. - Use a YouTube channel ID finder if needed.
- At time of writing, this one worked for me.
- This is not your (for example)
- Set
GHOST_URLto your Ghost instance URL. - Create a Ghost Admin API key:
Ghost Admin → Settings → Integrations → Custom Integrations → Add Custom Integration- Copy the Admin API key into
GHOST_ADMIN_KEY.
- Set
GHOST_NEWSLETTER_SLUG.- If you use the default newsletter, the default value may already work.
- You can verify this by poking around in the F12 inspector while editing the newsletter setting in the admin settings, looking for the newsletter slug.
- Set
YOUTUBE_GHOST_TAGif you want it to be different from the default. - Set
YOUTUBE_GHOST_VISIBILITYif you want the cross-posted Ghost posts to be something other thanpublic(e.g.membersorpaid). - Update the bookmark card URLs (
YOUTUBE_BOOKMARK_ICON/YOUTUBE_BOOKMARK_THUMBNAIL).- Icon: YouTube logo (included in repo)
- Thumbnail: default image if post is not an image post.
- You can probably generate these automatically by manually creating a draft post with a /bookmark card of an existing YouTube text post, then inspecting the element and copying the URLs of the images.
- Run the script in --init mode to populate post IDs.
- Create a new YouTube community post (or edit the seen post file to remove one of the posts).
- Run the script in --test mode to ensure it makes a draft post to your Ghost instance.
- Add a cron job to run the script automatically. I haven't had any issues with having it run every minute.
Checks PeerTube instance for new videos from specified channels, makes a playlist containing those videos in chronological order, and creates a ghost post with that playlist embedded.
- Supports
--testmode:- Creates a draft Ghost post instead of public ones.
- Does not add the PeerTube post ID to the seen-posts file.
- Supports
--initmode:- Creates the seen posts file.
- Populates file with existing PeerTube posts.
- Does not make any draft or public posts to Ghost at all.
- Stores seen PeerTube post IDs in a text file to prevent duplicate posts.
- Tags Ghost posts with a specified tag.
- Creates a PeerTube playlist automatically.
- Embeds PeerTube playlist in ghost post.
- Notifies Ghost members via email by publishing a draft, then changing the post to published.
- None at the moment.
Fill in .env (see Configuration above)
- Set
PEERTUBE_URLto your PeerTube instance URL. - Set
PEERTUBE_CHANNELSto the comma-separated channels you'd like to scan for new videos. - Set
PEERTUBE_USERNAMEandPEERTUBE_PASSWORD. - Set
PEERTUBE_PLAYLIST_CHANNEL_ID. - Set
GHOST_URLto your Ghost instance URL. - Create a Ghost Admin API key:
Ghost Admin → Settings → Integrations → Custom Integrations → Add Custom Integration- Copy the Admin API key into
GHOST_ADMIN_KEY.
- Set
GHOST_NEWSLETTER_SLUG.- If you use the default newsletter, the default value may already work.
- You can verify this by poking around in the F12 inspector while editing the newsletter setting in the admin settings, looking for the newsletter slug.
- Set
PEERTUBE_GHOST_TAGif you want it to be different from the default. - Other variables in
.env.example(playlist naming, fetch count, live-skipping, email segment, link ref) can be left at their defaults or customized. - To change the post itself beyond what
.envcovers, edit the script. ctrl+f forSunday Sidecarto find the section that builds the ghost post, as this is what I titled my weekly post.
- Run the script in --init mode to populate post IDs.
- Upload a new peertube video to one of the watched channels (or edit the seen post file to remove one of the posts).
- Run the script in --test mode to ensure it makes a draft post to your Ghost instance.
- Add a cron job to run the script automatically.