Tag: programming

Sep 04
text posts

Like many, I get annoyed by subscription pricing that doesn't accurately reflect my needs. I don't want to spend $5 a month for a color picker app. I don't really want to spend $4/month on ControlD for ad-blocking and custom internal DNS hosting, and NextDNS is worth $20/month until I hit the five or six times a month it's completely unresponsive and kills all my internet connectivity.

(I recognize I departed from the mainstream on the specifics there, but my point is still valid.)

I've self-hosted this blog and several other websites for more than a decade now; not only is it a way to keep up my Linux/sysadmin chops, it's also freeing on a personal level to know I have control and important to me on a philosophical level to not be dependent on corporations where possible, as I've grown increasingly wary of any company's motivations the older I get.

So I started looking at options that might take care of it, and over the last few months I've really started to replace things that would have previously been a couple bucks a month with a VPS running four such services for $40 a year.

Quick aside: I use RackNerd for all my hosting now, and they have been rock-solid and steady in the time I've been with them (coming up on a year now). Their New Year's Deals are still valid, so you can pay $37.88 for a VPS with 4GB of RAM for a year. Neither of those links are affiliate links, by the way - they're just a good company with good deals, and I have no problem promoting them.

AdGuard Home - Ad-blocking, custom DNS. I run a bunch of stuff on my homelab that I don't want exposed to the internet, but I still want HTTPS certificates for. I have a script that grabs a wildcard SSL certificate for the domain that I automatically push to my non-public servers. I use Tailscale to keep all my devices (servers, phones, tablets, computers) on the same VPN. Tailscale's DNS is set to my AdGuard IP, and AdGuard manages my custom DNS with DNS rewrites.

This has the advantages of a) not requiring to me to set the DNS manually for every wireless network on iOS (which is absolutely a bonkers way to set DNS, Apple), b) keeping all my machines accessible as long as I have internet, and c) allowing me to use the internal Tailscale IP addresses as the AdGuard DNS whitelist so I can keep out all the random inquiries from Chinese and Russian IPs.

The one downside is it requires Tailscale for infrastructure, but Tailscale has been consistently good and generous with its free tier, and if it ever changes, there are free (open-source, self-hosted) alternatives.

MachForm - Not free, not open-source, but the most reliable form self-hosting I've found that doesn't require an absurd number of hoops. I tried both HeyForm and FormBricks before going back to the classic goodness. If I ever care enough, I'll write a modern-looking frontend theme for it, but as of now it does everything I ask of it. (If I ever get FU money, I'll rewrite it completely, but I don't see that happening.)

Soketi - A drop-in Pusher replacement. Holy hell was it annoying to get set up with multiple apps in the same instance, but now I have a much more scalable WebSockets server without arbitrary message/concurrent user limits.

Nitter - I don't like Twitter, I don't use Twitter, but some people do and I get links that I probably need to see (usually related to work/dev, but sometimes politics and news). Instead of giving a dime to Elon, Nitter acts as a proxy to display it (especially useful with threads, of which you only see one tweet at a time on Twitter without logging in). You do need to create a Twitter account to use it, but I'm not giving him any pageviews/advertising and I'm only using it when I have to. When Nitter stops working, I'll probably just block Twitter altogether.

Freescout - My wife and I used Helpscout to run our consulting business for years until they decided to up their subscription pricing by nearly double what we used to pay. Helpscout was useful, but not that useful. We tried to going to regular Gmail and some third-party plugins, but eventually just went with a shared email account until we found Freescout. It works wonderfully, and we paid for some of the extensions mostly just to support them. My only annoyance is the mobile app is just this side of unusable, but hard to complain about free (and we do most of our support work on desktop, anyway).

Sendy - Also not free, but does exactly what's described on the box and was a breeze to set up. Its UI is a little dated, and you're best served by creating your templates somewhere else and pasting the HTML in to the editor, but it's a nice little workhorse for a perfectly reasonable price.

Calibre-web - I used to use the desktop version of Calibre, but it was a huge pain to keep running all the time on my main computer and too much of a hassle to manage when it was running on desktop on one of the homelab machines. Calibre web puts all of the stuff I care about from Calibre available in the browser. I actually run 3-4 instances, sorted by genre.

Tube Archivist - I pay for YouTube premium, but I don't trust that everything will always be available. I selectively add videos to a certain playlist, then have Tube Archivist download them if I ever want to check them out later.

Plex - I have an extensive downloaded music archive that I listen to using PlexAmp, both on mobile devices and various computers. I don't love Plex's overall model, but I've yet to find an alternative that allows for good management of mobile downloads (I don't want to stream everything all the time, Roon).

Permalink

The biggest financial concern right now is my foolhardy spending on domains. I have a problem.

Aug 29
text posts

I have been playing around with Soketi as a self-hosted Pusher alternative and, while the software is great, boy is its documentation and error messaging lacking. If you're trying to run it and get the error

There was an error while parsing the JSON in your config file. It has not been loaded. 

This is, as near as I can tell, the minimum required set of keys to get an app working:

{
    "debug": true,
    "port": 6001,
    "appManager.array.apps": [
        {
            "id": "id",
            "key": "key",
            "secret": "secret",
            "webhooks" : []
        }
    ]
}

Without the empty webhooks array, it kept failing on me.

I still have not gotten a pm2 instance to accept a config file šŸ˜­ļø. I gave up on the Docker instance because it doesn't allow more than one app per instance and I want something more flexible.

I'm sure it's great and super easy if you're just spinning up a single app, though!

Permalink

Open source is wonderful but we'd all appreciate the bare minimum in telling other people how to get it to run as well.

Aug 03
text posts

Note: This content, by Anne Gibson, was originally published at the Pastry Box Project, under a Creative Commons (CC BY-NC-ND 4.0) license. I am reposting it here so that it might remain accessible to the wider web at large.

A is blind, and has been since birth. Heā€™s always used a screen reader, and always used a computer. Heā€™s a programmer, and heā€™s better prepared to use the web than most of the others on this list.

B fell down a hill while running to close his car windows in the rain, and fractured multiple fingers. Heā€™s trying to surf the web with his left hand and the keyboard.

C has a blood cancer. Sheā€™s been on chemo for a few months and, despite being an MD, is finding it harder and harder to remember things, read, or have a conversation. Itā€™s called chemo brain. Sheā€™s frustrated because sheā€™s becoming more and more reliant on her smart phone for taking notes and keeping track of things at the same time that itā€™s getting harder and harder for her to use.

D is color blind. Most websites think of him, but most people making PowerPoint presentations or charts and graphs at work do not.

E has Cystic Fibrosis, which causes him to spend two to three hours a day wrapped in respiratory therapy equipment that vibrates his chest and makes him cough. As an extension, it makes his arms and legs shake, so he sometimes prefers to use the keyboard or wait to do tasks that require a steady touch with a mouse. He also prefers his tablet over his laptop because he can take it anywhere more conveniently, and itā€™s easier to clean germs off of.

F has been a programmer since junior high. She just had surgery for gamerā€™s thumb in her non-dominant hand, and will have it in her dominant hand in a few weeks. Sheā€™s not sure yet how it will affect her typing or using a touchpad on her laptop.

G was diagnosed with dyslexia at an early age. Because of his early and ongoing treatment, most people donā€™t know how much work it takes for him to read. He prefers books to the Internet, because books tend to have better text and spacing for reading.

H is a fluent English speaker but hasnā€™t been in America long. Sheā€™s frequently tripped up by American cultural idioms and phrases. She needs websites to be simple and readable, even when the concept is complex.

I has epilepsy, which is sometimes triggered by stark contrasts in colors, or bright colors (not just flashing lights). I has to be careful when visiting brightly-colored pages or pages aimed for younger people.

J doesnā€™t know that heā€™s developed an astigmatism in his right eye. He does know that by the end of the day he has a lot of trouble reading the screen, so he zooms in the web browser to 150% after 7pm.

K served in the coast guard in the 60s on a lightship in the North Atlantic. Like many lightship sailors, he lost much of his hearing in one ear. He turns his head toward the sound on his computer, but that tends to make seeing the screen at the same time harder.

L has lazy-eye. Her brain ignores a lot of the signal she gets from the bad eye. She can see just fine, except for visual effects that require depth perception such as 3-D movies.

M canā€™t consistently tell her left from her right. Neither can 15% of adults, according to some reports. Directions on the web that tell her to go to the top left corner of the screen donā€™t harm her, they just momentarily make her feel stupid.

N has poor hearing in both ears, and hearing aids. Functionally, sheā€™s deaf. When sheā€™s home by herself she sometimes turns the sound all the way up on her computer speakers so she can hear videos and audio recordings on the web, but most of the time she just skips them.

O has age-related macular degeneration. Itā€™s a lot like having the center of everything she looks at removed. She can see, but her ability to function is impacted. She uses magnifiers and screen readers to try to compensate.

P has Multiple Sclerosis, which affects both her vision and her ability to control a mouse. She often gets tingling in her hands that makes using a standard computer mouse for a long period of time painful and difficult.

Q is ninety-nine. You name the body part, and it doesnā€™t work as well as it used to.

R was struck by a car crossing a busy street. Itā€™s been six months since the accident, and his doctors think his current headaches, cognitive issues, and sensitivity to sound are post-concussion syndrome, or possibly something worse. He needs simplicity in design to understand what heā€™s reading.

S has Raynaudā€™s Disease, where in times of high stress, repetitive motion, or cold temperatures her hands and feet go extremely cold, numb, and sometimes turn blue. She tries to stay warm at her office desk but even in August has been known to drink tea to keep warm, or wear gloves.

T has a learning disability that causes problems with her reading comprehension. She does better when sentences are short, terms are simple, or she can listen to an article or email instead of reading it.

U was born premature 38 years ago ā€” so premature that her vision was permanently affected. She has low vision in one eye and none in the other. She tends to hold small screens and books close to her face, and lean in to her computer screen.

V is sleep-deprived. She gets about five hours of bad sleep a night, has high blood pressure, and her doctor wants to test her for sleep apnea. She doesnā€™t want to go to the test because they might ā€œput her on a machineā€ so instead she muddles through her workday thinking poorly and having trouble concentrating on her work.

W had a stroke in his early forties. Now heā€™s re-learning everything from using his primary arm to reading again.

X just had her cancerous thyroid removed. Sheā€™s about to be put on radioactive iodine, so right now sheā€™s on a strict diet, has extremely low energy, and a lot of trouble concentrating. She likes things broken up into very short steps so she canā€™t lose her place.

Y was in a car accident that left her with vertigo so severe that for a few weeks she couldnā€™t get out of bed. The symptoms have lessened significantly now, but that new parallax scrolling craze makes her nauseous to the point that she shuts scripting off on her computer.

Z doesnā€™t have what you would consider a disability. He has twins under the age of one. Heā€™s a stay-at-home dad who has a grabby child in one arm and if heā€™s lucky one or two fingers free on the other hand to navigate his iPad or turn Siri on.

=====

This alphabet soup of accessibility is not a collection of personas. These are friends and family I love. Sometimes Iā€™m describing a group. (One can only describe chemo brain so many times.) Some people are more than one letter. (Yay genetic lottery.) Some represent stages people were in 10 years ago and some stages we know they will hit ā€” we just donā€™t know when.

Robin Christopherson (@usa2day) points out that many of us are only temporarily able-bodied. Iā€™ve seen this to be true. At any given moment, we could be juggling multiple tasks that take an eye or an ear or a finger away. We could be exhausted or sick or stressed. Our need for an accessible web might last a minute, an hour, a day, or the rest of our lives. We never know.

We never know who. We never know when.

We just know that when itā€™s our turn to be one of the twenty-six, we will want the web to work. So today, we need to make simple, readable, effective content. Today, we make sure all our auditory content has a transcript, or makes sense without one. Today, we need to make our shopping carts and logins and checkouts friendly to everyone. Today, we need to design with one thought to the color blind, one thought to the photosensitive epileptic, and one thought to those who will magnify our screens. Today we need to write semantic HTML and make pages that can be navigated by voice, touch, mouse, keyboard, and stylus.

Tomorrow, itā€™s a new alphabet.

Permalink
Jul 30
text posts

Forgive the lack of posts recently, a back injury has mostly confined me to bed, and I get a little sick of staring at computer screens.

But while I've been out of it I caught up on Aaron Sorkin's The Newsroom, which I had never seen. As a fan of The West Wing and yes, even Studio 60, I thought, as a former journalismo myself, this would be right up my alley.

And it definitely inspired me ... to get back into writing code. It was so bad. I was surprised at how bad it was. It made me question my own taste and wonder whether I'd misjudged Sorkin's talent.

Don't get me wrong, he has some good scripts, and some of his meaty monologues and dialogues in various things he's written are an absolute delight.

But he's also written the same show at least three times now? Including similar (in some cases, identical) plot points, themes, specific jokes, even a reference to using too much back medicine as an excuse for why a white man said something dumb.

In case you couldn't tell from my recipe intro up top there, this is a post about how I reworked Newslurp, a little app I coded four years ago (right before the Big Newsletter Boom thanks to Covid!). I switched RSS services at one point and was using a "subscribe to the newsletter from the service's email" feature, but the lack of polish in the app (and severe degredation of basic feed-reading) means I'm back on the market.

And rather than tying all my content to another proprietary app, I decided revive Newslurp so I could keep better control of everything. The app had a significant overhaul, with most of the email heavy lifting now being done in Google Apps Script (thus removing the need for Google API integration and the PECL mailparse extension, which is not readily available on shared hosts).

I also switched from MySQL to SQLite (because this is not really an application that needs a whole MySQL DB), and updated the code/dependencies to run on PHP 8.2

My biggest takeaway from the whole thing is that while I really love types, PHP does not make it easy to use them properly with collections or array-like objects. Yikes.

As always, I hope this is in some way helpful to others, but mostly it's helpful to me! Enjoy.

Permalink

I think legitimately 2 hours of the 5-hour revamp was spent debugging TypedArray issues.

Apr 15
text posts

The Game is a mind game in which the objective is to avoid thinking about The Game itself. Thinking about The Game constitutes a loss, which must be announced each time it occurs.

The programming version of The Game has the same rules, but you lose if you think about David Heinemeier Hansson (aka DHH).

And no, I'm not linking to why I lost today.

Permalink

Broke a four-month winning streak, dangit.

Mar 09
quote posts

If you rush and donā€™t consider how it is deployed, and how it helps your engineers grow, you risk degrading your engineering talent over time

Source

Permalink

I don't disagree that overreliance on AI could stymie overall growth of devs, but we've had a form of this problem for years.

I met plenty of devs pre-AI who didn't understand anything other than how to do the basics in the JS framework of the week.

It's ultimately up to the individual dev to decide how deep they want their skills to go.

Feb 27
longtext posts

Today I want to talk about data transfer objects, a software pattern you can use to keep your code better structured and metaphorically coherent. Itā€™s a tool that can help you stay in the logical flow of your application, making it easier to puzzle through and communicate about the code youā€™re writing, both to yourself and others.

The DTO is one of my go-to patterns, and I regularly implement it for both internal and external use.
Iā€™m also aware most people already know what pure data objects are. Iā€™m not pretending weā€™re inventing the wheel here - the value comes in how theyā€™re applied, systematically.

This is a long 'un, buckle in
Feb 23
text posts

ā€œ[Random AI] defines ...ā€ has already started to replace ā€œWebsterā€™s defines ...ā€ as the worst lede for stories and presentations.

Permalink

I let the AI interview in the playbill slide because the play was about AI, but otherwise, no bueno.

Feb 22
photo posts

The way to guarantee durability and failure recovery in serverless orchestration and coordination is ā€¦ a server and database in the middle of your microservices.

Iā€™m sure itā€™s a great product, but come on.

Feb 20
text posts

I have previously mentioned that I love NextDNS, but they do not make certain fundamental things, like managing your block and allow lists, very easy. Quite often I'll hit a URL that's blocked that I'd like to see - rather than use their app, I have to load their (completely desktop-oriented) website, navigate to the right tab, then add the URL in.

That's annoying.

Without writing an iOS app all of its own (which sounds like a lot of work), I wanted an easy to way to push URLs to the block or deny list. So I wrote an iOS Shortcut that works with a PHP script to send the appropriate messages.

You can find the shortcut here.

The PHP script can found at this Gist. You'll need to set the token, API key (API key can be found at the bottom of your NextDNS profile) and profile ID variables in the script. The token is what you'll use to secure your requests from your phone to the server.

I thought about offering a generic PHP server that required you to set everything in Shortcuts, but that's inherently insecure for everyone using it, so I decided against it. I think it would be possible to do this all in Shortcuts, but Shortcuts drives me nuts for anything remotely complex, and this does what I need it to.

Permalink

It really is annoying how hard it is to manage a basic function. NextDNS also doesn't seem to have set their CORS headers properly for OPTIONS requests, which are required for browser-based interactions because of how they dictated the API token has to be sent.

Feb 08
photo posts

At least I finished it, eventually!

Feb 06
longtext posts

As part of my plan to spend more time bikeshedding building out my web presence than actually creating content, I wanted to build an iOS app that allowed me to share short snippets of text or photos to my blog. I've also always wanted to understand Swift generally and building an iOS app specifically, so it seemed like a nice little rabbit hole.

Be wary of chasing rabbits down their holes

I later expanded the app's remit to include cross-posting to BlueSky and Mastodon, which is a double-bonus because BlueSky STILL doesn't support sharing an image from another application (possibly because they couldn't find the Medium post???)

Jan 29
text posts

I've recently been beefing up my homelab game, and I was having issues getting a Gotify secure websocket to connect. I love the Caddy webserver for both prod and local installs because of how easy it easy to configure.

For local installs, it defaults to running its own CA and issuing a certificate. Now, if you're only running one instance of Caddy on the same machine you're accessing, getting the certs to work in browsers is easy as running caddy trust.

But in a proper homelab scenario, you're running multiple machines (and, often, virtualized machines within those boxes), and the prospect of grabbing the root cert for each just seemed like a lot of work. At first, I tried to set up a CA with Smallstep, but was having enough trouble just getting all the various pieces figured out that figured there had to be an easier way.

There was.

I registered a domain name (penginlab.com) for $10. I set it up with an A record pointing at my regular dev server, and then in the Caddyfile gave it instructions to serve up the primary domain, and a separate instance for a wildcard domain.

When LetsEncrypt issues a wildcard domain, it uses a DNS challenge, meaning it only needs a TXT record inserted into your DNS zone to prove it should issue you the server. Assuming your registrar is among those included in the Caddy DNS plugins, you can set your server to handle that automatically.

(If your registrar is not on that list, you can always use

certbot certonly --manual

and enter the TXT record yourself. You only need to do it once a quarter.)

Now we have a certificate to use to validly sign HTTPS connections for any subdomain for penginlab.com. You simply copy down the fullchain.pem and privkey.pem files to your various machines (I set up a bash script that scps the file down to one of my local machines and then scps it out to everywhere it needs to go on the local network.)

Once you have the cert, you can set up your caddy servers to use it using the tls directive:

tls /path/to/fullchain.pem /path/to/privkey.pem

You'll also need to update your local DNS (since your DNS provider won't let you point public URLs at private IP addresses), but I assume you were doing that anyway (I personally use NextDNS for a combination of cloud-based ad-blocking and lab DNS management).

Bam! Fully accepted HTTPS connections from any machine on your network. And all you have to do is run one bash script once a quarter (which you can even throw on a cron). Would that all projects have so satisfying and simple a solution.

Permalink

I'm definitely not brave enough to put it on a cron until I've run it manually at least three times, TBH. But it's a nice thought!

Jan 28
text posts

Re: Appleā€™s convoluted EU policies

It's surprising how often D&D is relevant in my everyday life. Most people who play D&D are in it to have fun. They follow the rule - not just the letter of the law, but the spirit.

But every once in a while you'll encounter a "rules lawyer," a player who's more concerned with making sure you observe and obey every tiny rule, punish every pecadillo, than actually having fun.

All the worse when it's your GM, the person in charge of running the game.

But there's one thing you learn quickly - if someone is trying to game the rules, the only way to win (or have any fun) is play the game right back.

For smaller/mid-tier devs, if you're only offering free apps you should probably just continue in the App Store.

But for larger devs who might run afoul of the new guidelines where apps distributed outside the App Store get charged a fee every time they go over a million users?

Oops, Apple just created collectible apps, where if you have Facebook (and not Facebook2), we know you got in early. Think about it: Same codebase, different appId. The external app stores can even set up mechanisms for this to work - every time you hit 999,000 installs, it creates a new listing that just waits for you to upload the new binary (and switches when you hit 995K). Now your users are incentivized to download your app early, in case becomes the big thing. Lower app # is the new low user ID.

If I'm Microsoft, I'm putting a stunted version of my app in the App Store (maybe an Office Documents Viewer?) for free, with links telling them if they want to edit they have go to the Microsoft App Store to download the app where Apple doesn't get a dime (especially if Microsoft uses the above trick to roll over the app every 995K users).

Even in the world where (as I think is the case in this one) Apple says all your apps have to be on the same licensing terms (so you can't have some App Store and some off-App Store), it costs barely anything to create a new LLC (and certainly less than the 500K it would cost if your app hits a million users). Apple's an Irish company, remember? So one of your LLCs is App Store, and the other is external.

To be clear, I don't like this setup. I think the iPhone should just allow sideloading, period. Is all of this more complicated for developers? Absolutely! Is the minimal amount of hassle worth saving at least 30% percent of your current revenue (or minimum $500K if you go off-App Store)? For dev shops of a certain size, I would certainly think so.

The only way to have fun with a rules lawyer is to get them to relax, or get them to leave the group. You have to band together to make them see the error of their ways, or convince them it's so much trouble it's not worth bothering to argue anymore.

Permalink

Yes, Apple is going to (rules-)lawyer this, but they made it so convoluted I would be surprised if they didn't leave some giant loopholes, and attempting to close them is going to bring the EU down on them hard. If the EU is even going to allow this in the first place.

Jan 22
text posts

I'll be hitting the lecture circuit again this year, with three conferences planned for the first of 2024.

In February, I'll be at Developer Week in Oakland (and online!), talking about Data Transfer Objects.

In March, I'll be in Michigan for the Michigan Technology Conference, speaking about clean code as well as measuring and managing productivity for dev teams.

And in April I'll be in Chicago at php[tek] to talk about laws/regulations for developers and DTOs (again).

Hope to see you there!

Permalink

Who holds a conference in the upper Midwest in March???

Aug 04
text posts

Hey everybody, in case you wanted to see my face in person, I will be speaking at LonghornPHP, which is in Austin from Nov. 2-4. I've got two three things to say there! That's twice thrice as many things as one thing! (I added a last-minute accessibility update).

In case you missed it,Ā I said stuff earlier this year at SparkConf in Chicago!

I said stuff about regulations (HIPAA, FERPA, GDPR, all the good ones)Ā at the beginning of this year.Ā This one is available online, because it was only ever available online:

I am sorry for talking so fast in that one, I definitely tried to cover more than I should have. Oops!

Permalink

The SparkConf talks are unfortunately not online yet (for *reasons*), and I'm doubtful they ever will be.

Jul 03
text posts

WordPress 6.2.1 changelog:

Block themes parsing shortcodes in user generated data; thanks to Liam Gladdy of WP Engine for reporting this issue

As a reminder, from Semver.org:

Given a version number MAJOR.MINOR.PATCH, increment the:
1.Ā MAJOR version when you make incompatible API changes
2.Ā MINOR version when you add functionality in a backward compatible manner
3.Ā PATCH version when you make backward compatible bug fixes

As it turns out, just because you label it as a "security" patch doesn't make it OK to completely annihilate functionality that numerous themes depend on.

This bit us on a number of legacy sites that depend entirely on shortcode parsing for functionality. Because it's a basic feature. We sanitize ACTUAL user-generated content, but the CMS considers all database content to be "user content."

WordPress is not stable, should not be considered to be an enterprise-caliber CMS, and should only be run on WordPress.com using WordPress.com approved themes. Dictator for life Matt MullenwegĀ hasĀ pretty explicitly stated he considers WordPress'Ā competitors to be SquareSpace and Wix. Listen to him.

Permalink

Friends don't let their friends use WordPress

Aug 29
longtext posts

As I was evaluating the options, in addition to the dealbreakers, I kept finding small annoyances. The backend interface was confusing, or required too many clicks to get from place to place; the speed to first paint was insane; just the time waiting for the content editor to load after I clicked it seemed interminable. At the same time, I was also going through a similarly frustrating experience with cloud music managers, each with a vital missing feature or that implemented a feature in a wonky way.

Then I had an epiphany: Why not just build my own?

Wait, I bet there's a catch!

I set out to build my own CMS in an attempt to circumvent some of the problems I'd had with others in the past. I wound up inventing a whole new set of problems! What a neat idea.

Jul 21
longtext posts

Thus was born Newslurp. It's not pretty. I will 100% admit that. The admin interface can be charitably described as "synthwave brutalist." That's because you really shouldn't spend any time there. The whole point is to set it up once and never have to touch the thing again. The interface really only exists so that you can check to see if a specific newsletter was processed.

It's not perfect. There are some newsletters that depend on a weirdly large amount of formatting, and more that have weird assumptions about background color. I've tried to fix those as I saw them, but there are a lot more mistakes out there than I could ever fix. Hopefully they include a "view in browser" link.

We should all aspire to be called "synthwave brutalist"

Loogit me, building the Substack app 3 years too early. And without the infrastructure. OK, I built an RSS feed. But I still saw the newsletter boom coming!

Jun 09
longtext posts

We got past it (and got the API into core, where it has been [ab]used by Automattic), but it left a sour taste in my mouth. WordPress development was supposed to be community-driven, and indeed though it likely would not exist in its current state without Automattic's help, neither would Automattic have been able to do it all on its own. But the community was shut out of the decision-making process, a feeling we would get increasingly familiar with.

A mostly-fond farewell

A farewell to a CMS that taught me how to program, and eventually how to know when it's time to move on.