Set up your pan.
Choose a medium, heavy-bottomed saucepan. Heavy pans prevent scorching, which keeps the pudding smooth.
Whisk the dry base. Off the heat, whisk together sugar, cocoa powder, cornstarch, and a pinch of salt in the saucepan until no cocoa lumps remain.
Add milk and yolks. Gradually whisk in the milk, a little at a time, until the mixture is smooth.
Whisk in the egg yolks until fully combined. The mixture should be uniform with no dry spots.
Heat gently. Place the pan over medium heat.
Whisk constantly, making sure to reach the edges and corners. As it warms, the mixture will loosen, then start to thicken after 5–7 minutes.
Thicken to pudding. Once the mixture begins to bubble, reduce to medium-low and cook for 1–2 minutes, whisking the whole time.
It should be thick enough to coat the back of a spoon and hold a line when you drag a finger across.
Stir in chocolate and butter. Remove from heat. Add the chopped semisweet chocolate and butter.
Let stand for 30 seconds, then whisk until glossy and fully melted. Stir in vanilla. If using espresso powder or zest, add it now.
Optional: Strain.
For the silkiest pudding, pour through a fine mesh sieve into a bowl or large measuring cup to catch any tiny bits of egg or cocoa clumps.
Portion and cover. Divide into ramekins or cups, or keep it in one large container. Press plastic wrap directly onto the surface to prevent a skin unless you prefer one.
Chill.
Refrigerate at least 2 hours to set. For the best texture and flavor, chill 4 hours or overnight.
Serve. Top with a dollop of whipped cream, a sprinkle of flaky sea salt, shaved chocolate, or fresh berries.
Enjoy cold.