More about use case than how to do it: client side certificate authentication is not a rocket science.
Unless you 100% need to use signing for the use case like a client side ACL, there is genuinely no need to overengineer your web app with your own authentication scheme.
But if your scale already mandates doing operations without server side ACL lookup for performance reasons, doing it over HTTP and web stack might already be inefficient by itself for the task.
Client certs are great if you control the client. If, say, Slack told me that to use the Slack API I'd need to get a client cert, I would laugh.
One thing that comes to mind is that either you have to check revocation on the server side, or you have to re-provision client certs frequently, and in most client libraries that's actually difficult / annoying. If the server just sends me an updated token, I can just put that in a local variable and call it done.
There's a reason most APIs have moved to "you can just put the token in the request payload". It's hard enough to ask people to set HTTP headers, asking them to set client certs will be super complicated.
Two, I'm talking about client libraries, not web browsers. Every client library (including those used by web browsers) is perfectly capable of passing a query parameter. Most can pass cookies or custom headers. Not all of them can pass client certs.
Unless you 100% need to use signing for the use case like a client side ACL, there is genuinely no need to overengineer your web app with your own authentication scheme.
But if your scale already mandates doing operations without server side ACL lookup for performance reasons, doing it over HTTP and web stack might already be inefficient by itself for the task.