My previous solution included yanking the display cable out every time I wanted to close the lid and then plugging it back in.
After looking for an easy solution, I tried https://github.com/pirj/noclamshell but I didn't like the approach it took where it basically polled every 2 seconds and reacted to the lid state at the time of the poll. This + using a stale state reading led to a bug where it activated sleep mode with the lid open. I also did not want to install an app as I see this as a lightweight utility your turn on and forget, not something taking up menu bar space.
The way it works is by listening to native macOS state for power, external displays and the lid position, resulting in a noop if no power of external display is connected or sending the external display to sleep if all conditions are met. The cable still continues to charge the battery even with the lid closed.