Building a Moon Phase Bot for Bluesky: Because Every Platform Needs More Werewolf Energy

I've been tinkering around Bluesky for a while now, and one thing kept nagging at me: where are all the moon bots? Twitter had them. Mastodon had them. But Bluesky? Crickets. Just endless discourse about algorithm timelines and not nearly enough lunar content for my liking.

So naturally, I did what any reasonable person would do when faced with a distinct lack of automated celestial updates: I built my own.

The Motivation

The thing is, I've always been partial to moon tracking bots. There's something oddly comforting about a reliable daily update on what our cosmic neighbour is up to. Whether it's waxing gibbous or completely dark, I want to know. Call it lycanthropic tendencies, call it astronomy appreciation – either way, the timeline felt incomplete without it.

I'd gotten used to these bots on other platforms, so when I migrated to Bluesky and found... nothing? That was a problem that needed solving.

The Stack (Probably Sensible This Time)

Unlike my Minecraft server adventure , I kept this one refreshingly simple:

Node.js/TypeScript
↓
Farmsense Moon API
↓
@atproto/api
↓
Bluesky

No Docker containers. No custom domains. No DuckDNS shenanigans. Just a straightforward bot that fetches moon data and posts it daily at midnight UTC.

Working with Bluesky's API has become second nature by now, so the authentication and posting logic came together without much fuss. The real find was discovering Farmsense's free moon phase API – exactly what I needed without having to scrape NASA or build my own lunar calculations.

The Personality Problem

Here's where things got interesting. A bot that just posts "Moon is 73.2% illuminated" is functional but boring. This needed character.

Three types of flair made it into the final version:

Lycanthropic phrases because I'm fond of werewolves and "Awooo!" never gets old. Lines like "Call of the wild is strong tonight" and "Beware the moon, lads" (yes, that's an American Werewolf in London reference) felt right for a moon bot with personality.

British references because I'm British and it amused me to have a bot that says things like "Fancy a cuppa under its glow?" and "Bloody hell, what a moon!" Nothing too forced, just enough to give it a distinctly UK flavour.

Pride references in June because I'm gay-ace and June felt like the right time for "Love wins, even under the moon!" and "Queer joy, moonlit sky!" It's subtle, seasonal, and adds a bit of warmth to an otherwise astronomy-focused feed.

Each post randomly combines these elements, so you might get lycanthropic energy with British charm, or Pride sentiment with moon phase facts. The randomisation keeps it from feeling repetitive while maintaining consistent personality.

Month-Specific Touches

Rather than generic moon facts, I added seasonal flair:

January gets "Frosty start to lunar year!" and Wolf Moon references

June combines summer solstice mentions with Pride content

October leans into "Spooky season moon vibes!"

December brings "Winter wonderland, moon shining bright!"

It's these small details that make automated content feel less robotic and more like something a slightly eccentric astronomy enthusiast might actually post.

The Technical Bits

The core logic is straightforward: fetch current moon phase data, generate a playful message with random flair, format it properly for Bluesky's rich text system, and post it daily at midnight UTC.

The trickiest part was handling UTF-8 encoding for hashtags. Bluesky's facet system requires precise byte offsets, not character positions, so I had to use TextEncoder to get the measurements right. Nothing too complex, but it took a bit of debugging to ensure hashtags rendered properly.

What I Learned

Building this reinforced a few things about bot development:

Personality matters more than features. The moon phase data is simple – it's the random British quips and werewolf enthusiasm that make people actually want to follow it.

Free APIs still exist. Farmsense's moon API is reliable, requires no authentication, and returns exactly the data I needed. Sometimes the solution really is that straightforward.

Bluesky's API is genuinely pleasant to work with. Having worked with it on other projects, the AT Protocol feels refreshingly consistent and well-documented.

What's Next

The bot works perfectly in testing, but I haven't deployed it yet. I'm considering a few options:

Simple VPS deployment with PM2 or similar

Possibly GitHub Actions for the scheduling

Maybe just running it locally since it's lightweight

I could probably add monitoring and logging systems, but for something that posts once daily and either works or doesn't, the complexity feels unnecessary. Sometimes keeping things simple is the better choice.

The Real Win

More than anything, this scratched a very specific itch. Bluesky needed moon content, I wanted to see moon content, so I made moon content happen. It's the kind of small contribution that makes a platform feel more complete – not groundbreaking, just filling a gap that shouldn't have existed in the first place.

Plus, now I get to see "🌕 By Jove, a magnificent Full Moon! 99.8% light. Howl at the moon! #FullMoon" in my timeline, and that's exactly the sort of delightfully ridiculous content the internet needs more of.

The bot's code is available on GitHub if you're curious about the implementation details or want to deploy your own lunar companion. Just remember to add your own personality quirks – the moon deserves better than bland automation.