Patching the harbour master's charts
I’d been scheduling the game site’s socials through Buffer, and the plan was to move them onto the planner I self-hostedYou run the software on your own machine instead of paying someone to run it for you. More control and no monthly bill; you are the one who fixes it at midnight.. Then I sat down to recreate a normal week of posts and ran aground on the first one. Buffer lets you choose an Instagram post, reel or story, tick the box that says a post was made with AI, and pick music from Instagram’s library. The planner had post-or-reel as a single option, no AI label, no Facebook reels at all, and a music picker that only ever showed 25 songs. For a game site, reels with music are most of the point.
Reading the charts first
Before touching anything I read Meta’s APIA defined way for one program to ask another for data or an action — usually over the web, request in, structured response out. "Steam’s API" is how other software reads Steam data. docs against what the planner actually sends. Most of it was there under the surface. An Instagram media container takes a media_type of REELS or STORIES, a share_to_feed flag for reels, and an is_ai_generated flag for the label. Facebook Page reels have their own three-step dance: start an upload on /video_reels, hand Meta the video’s URL in a file_url header, then finish with video_state=PUBLISHED and the caption. And the music search did get 25 results, because that’s the default page size, and it never asked for the next page.
A fork and a handful of patches
The planner is open source, so I forkYour own copy of someone else's code repository, which you can change freely and still pull their updates into. it and kept the patches small and in the providers where they belong. Instagram’s choice is now post, reel or story, with share-to-feed for reels and the AI label on single posts, stories and the parent of a carousel, where Meta wants it rather than on each image. Facebook grew a reel option that walks the three-step upload and publishes on the planner’s second pass, once Meta says the video’s processed. The music search asks for 100 at a time, follows the after cursor up to five pages and drops duplicates. Trending went from 25 songs to 98, which still isn’t every song on Instagram, because the API only ever shows a business account a curated slice of the catalogue.
Nine tests cover it, and none of them talk to Meta. The provider’s fetch is swapped for a stubA stand-in for something real, used in tests. It answers like the real thing would and writes down what it was asked. that records every request, so the tests check the URLs and bodies that would have gone out, including that nothing gets published until the reel’s confirmation step comes back.
Built somewhere else
The VPSVirtual Private Server — a slice of a machine you rent in a data centre, with its own public IP address. A few dollars a month gets you enough to run a small production app. the planner runs on is small and already busy, and building a monorepoOne repository holding several apps and libraries that are built together. Convenient to work in, heavy to build.’s DockerA tool that packages an app together with everything it needs to run into a "container", so it runs the same on any machine and does not collide with anything else installed. image there would have sunk it for an afternoon. So a tag like x-hakt-v2.24.0-2 on the fork kicks off a GitHub Actions workflow that runs the tests and then builds an amd64 image and pushes it to the fork’s package registry, GHCRGitHub Container Registry — GitHub’s own place to publish container images, next to the code they came from. Push a tagged release and a workflow can build and land one there automatically.. On the server, the Docker ComposeA file (docker-compose.yml) that describes all the containers a project needs — the web app, its database, a cache — and one command to start or stop the lot together. file’s image line became ${POSTIZ_IMAGE:-ghcr.io/gitroomhq/postiz-app}:${POSTIZ_VERSION}, so switching to the patched build is two lines in .env fileA plain text file of secrets and settings a project reads at startup — database passwords, API keys. Never committed to git; easy to lose because it only exists on the running machine., and switching back is deleting them. As a side effect the patched image boots in about thirty seconds instead of three and a half minutes, because it doesn’t compile anything on start.
Bring me that horizon, and a reel with the Mario 64 race music on it. Fair winds.
-x