Blog Posts

Advent 2023: NTP on AWS

Continuing my 2023 advent blogging, today is a tip on getting NTP to work on Amazon AWS EC2 instances.

Continue reading...

Advent 2023: Logseq

In years past, folks across a variety of programming languages have organized Advent events in December, to highlight different tools, different frameworks, different programming practices, and more, often inviting guests to author each post.

I thought I'd try an experiment: I've had a ton of ideas for blog posts, many of them short, and just... never write them. What if I were to do a personal advent, and write these up?

Let's see how far I get.

Today's topic: Logseq.

Continue reading...

3 Months, 3 Weeks, and 3 Days

I started this post early, finished it late, but the sentiment remains the same.

3 months, 3 weeks, and 3 days ago, I dislocated my shoulder, and turned my world upside down.

Trigger warning

I discuss a traumatic injury in this post.

Continue reading...

Zentangle Back to Basics, 2022 Retrospective

This week in Eni Oken's Art Club, we did a 2022 retrospective, and went back to basics with a standard Z-string tile. Here are my reflections and thoughts.

Continue reading...

Goodbye Twitter

This is a long, personal post.

tl;dr: I'm leaving Twitter. You can find me in the Fediverse as

Continue reading...

TailwindCSS Tips

I've been dabbling in CSS my entire career. In the early days, it was relatively simple, as our browsers were fairly limited. But over the years, CSS has become more and more capable, allowing styles to target only tags with specific tag attributes, only apply at specific screen sizes, and even perform complex layouts using things like flexbox and grid. I take a bit of time every now and then to understand these things... but since I don't use CSS a ton, it's hard to keep up.

As such, over the past decade, I've tended to use CSS frameworks, and generally Bootstrap. Every couple years, a new major version is dropped, and I have to learn new structures and components, and struggle to get things to look the way I want. Worse, when I use these frameworks, injecting custom CSS often means understanding how the framework is already styling components so I can ensure things don't conflict.

The last couple years, I've been keeping an eye on TailwindCSS. I've been a bit skeptical, as its declarative, utility-first approach looks a lot like doing CSS inside your HTML, which, honestly, feels off. I've typically subscribed to the idea of semantic HTML, which advocates separating style from markup. Having styles directly that mimic CSS directives associated with every tag feels like an unholy mix, and a far cry from semantic HTML.

And then there's the hype. The original author and project lead of Tailwind is a huge hype man, and hype tends to turn me off. That's on me, not them, but having been in the business for over two decades, I'm finding I'm more and more likely to discount hyped products and projects, because I've seen them come and go so frequently; there's often an indirect relationship between the amount of hype and the long-term viability of a project. I've also often observed that hype serves as a way for users to deflect reasonable critique, and the more vehement the user base, the less interested I am in engaging with them because of this. Clearly, YMMV, but it was definitely something keeping me from really investigating Tailwind.

However, recently, in helping out the PHP Foundation, I volunteered to setup their static website, and the team requested using TailwindCSS, so I dove in.

And I discovered... I kind of love it.

This is one of those "I'll be googling this in the future" posts.

Continue reading...

Getting OpenSwoole and the AWS SDK to Play Nice

I have some content that I store in S3-compatible object storage, and wanted to be able to (a) push to that storage, and (b) serve items from that storage.

Easey-peasey: use the Flysystem AWS S3 adapter, point it to my storage, and be done!

Except for one monkey wrench: I'm using OpenSwoole.

Continue reading...

Exposing webhooks via mezzio-swoole

I was first introduced to the concept of webhooks via a 2009 blog post by John Herren, a former colleague at Zend. At the time, they were in their infancy; today, they're ubiquituous, as they provide a mechanism for a service to notify interested parties of events. This saves traffic; instead of consumers polling an API for event changes, the service notifies them directly. It also means that the consumer does not need to setup things like cronjobs; they instead setup a webhook endpoint, register it with the service provider, and their application takes care of the rest.

The thing is, handling a webhook can often lead to additional processing, and you are expected to send an immediate response to the provider indicating you received the event.

How can you achieve this?

Continue reading...

Running cronjobs via an Openswoole timer

Sites I build often utilize cronjobs to periodically pull in data from other sources. For example, I might want to poll an API once a day, or scrape content from another website once a month. Cronjobs are a perfect fit for this.

However, cron has a few problems:

  • If the job is writing information into the file tree of your web application, you need to ensure permissions are correct, both at the filesystem level, and when writing the cronjob (e.g., running it as the same user, or changing permissions on completion).
  • If you are running console tooling associated with your PHP application, you may need to worry about whether or not particular environment variables are in scope when you run the job.
  • In containerized environments, usage of cron is strongly discouraged, as it means running another daemon. You can get around this with tools such as the s6-overlay, but it's another vector for issues.

Since most sites I build anymore use mezzio-swoole, I started wondering if I might be able to handle these jobs another way.

Continue reading...

Caddy as a Secure Reverse Proxy

I've been using Caddy as a front-end reverse proxy for several years now, on the advice of Marco Pivetta. Somewhere along the line version 2 was released, and I updated at some point, but evidently didn't quite understand some of its configuration options, particularly around HSTS support and providing your proxied application information about how the client tried to connect.

Continue reading...