I should've been more verbose. You cannot calculate the signature client side without leaking the key. So you need a server. That step is identical to what this "serverless" implementation is doing.
Correct. But the signature doesn't necessarily need to be per-file upload, so I have it embedded in JS. For my use case, saving the extra network hop is worthwhile.