/colophon
or: technologies used on this site
PHP
It's no secret that I use PHP. I've been active in the PHP community since the early oughts, and using it since 2000. I'd frankly be surprised if I didn't use it!
I use PHP-FPM, and have one pool for answering front-end requests, and another that acts as a set of queue workers.
Mezzio
I use Mezzio, a PHP middleware framework that implements and uses PSR-7 (HTTP Messages) and PSR-15 (HTTP Middleware and Handlers). I helped create it (and each of the standards), and still help maintain it from time to time.
Plates
Plates is a native PHP template system. PHP was originally developed as a templating system, and I appreciate not having to learn a new syntax when creating templates. Plus, having all the power of PHP at hand is useful!
nginx
nginx is a high-performance web server. I use it as the internal web server for my application, and it manages both incoming traffic from my frontend web server, as well as internal queue worker traffic from ZendHQ.
Caddy
While I use nginx internally, the actual web server on the frontend is Caddy. It's ridiculously easy to configure, and I have it acting both as a static site server for a few websites, as well as a reverse proxy for others, including mwop.net.
ZendHQ
In my role as a product manager at Zend by Perforce, I directed development of the ZendHQ product, which provides observability and scalability tooling. I use it on my site to perform a number of recurring jobs, but also to offload database operations that I don't need to wait for (generation of feeds or static pages after posting on my blog or gallery, etc.).
PostgreSQL
For many years, I was using SQLite, but in early 2024 rewrote my site to use Postgres. Why? There were a few reasons:
- I was no longer just reading from the database. For years, I'd been generating it during deployment, but when I started uploading images to my gallery, I was writing to it, and because I use Docker, I was struggling with maintaining consistent backups.
- I wanted better search. SQLite has some reasonable fulltext search, but Postgres has some GREAT search capabilities, and they are incredibly fast.
- Better performance. I have normalized databases and use foreign keys, and while SQLite does well, Postgres does better.
Redis
I use Redis as my session storage as well as for some caching. It's simple to use, and fast.
Docker Compose
I use Docker Compose to orchestrate my website. This allows me to have identical environments during development as in production, and allows me to run multiple applications on the same server without conflicting dependencies and environments. Because my application spans multiple services (PHP-FPM, nginx, Redis, Postgres, ZendHQ...), it greatly simplifies deployment.
S3-Compatible Storage
Amazon Web Services Simple Storage Service (AWS S3) revolutionized how we build applications that need to store files and unstructured data. Since I use Docker, and I have an art gallery on my site, I need a way to decouple storage of my art from the application itself, and S3 provides a great way to do that. However, I do not host on S3. Fortunately, there are a number of S3-compatible solutions to choose from, and these all work with various S3 development libraries.
Plain old CSS
I've used Bootstrap and Tailwind in the past for doing my site layouts, but I now am back to plain old CSS. Why? Because CSS has come so far that the abstractions each of these present are basically unnecessary. I can define variables, nest selectors, create grid layouts that reorder and place content, and more. Taking the time to learn CSS means taking control of your site design.
HTMX
One thing I've lamented for more than a decade is that HTML has not allowed us to do anything more than GET or POST. On top of that, it makes replacing small areas of content ridiculously obtuse. HTMX is a small JS library that gives both of those things. You can see it in action on this site — clicking a link within the site reloads within the site, instead of doing a full page reload; pages like the art gallery load more content as the end scrolls into view; the search results are displayed in the page. These sorts of small features make the site feel like a more cohesive application, which I appreciate. Even better, it's not a full-blown JS front-end framework like React; it's just a small set of unobtrusive elements that are completely opt-in, and work fine even without JavaScript present.