The situation is very similar to password storage, where you want to not make it trivial to brute-force moderate-entropy passwords even if your database gets breached. We have functions designed specifically for that: scrypt, argon2 etc. https://www.npmjs.com/package/scryptsy is a pure JS implementation of scrypt for example.
Even with scrypt the situation is not great, but using sha for this kind of thing is no longer state of the art. If people are willing to (a) download and run a program rather than rely on the browser and (b) willing to wait half a minute or so for the result then you could easily tune the scrypt/argon parameters up to 11 but at the cost of quite a bit in the way of usability. If "must work on smartphones without extra app downloads" is a requirement you're pretty limited in what you can do this way.
Another solution might be to use real servers but host them on the "dark web" - get Tor a bit of publicity in Catalunya!
EDIT: in response to a few posts that briefly appeared and then disappeared again - IPFS is fine. SHA256 for authenticating a page is fine. I'm only objecting to using raw SHA-anything as a key derivation function as in the section "A static database".