I needed a new password generator last week. The top three Google results all wanted my email, ran ads that looked like antivirus scams, or, in one case, POSTed the generated password to their own backend "for logging". None of that is what a password generator is supposed to do.
So I built one. It is live at nimoyburrowes.com/tools/password-generator. Free, no signup, no ads.
What it does
Four modes:
- **Random** for maximum entropy per character. Length up to 128, all four character classes optional, exclude ambiguous characters (0, O, 1, l, I) with one toggle.
- **Easy to read** for passwords you have to type off a screen. Random alphanumerics grouped in blocks of four with hyphens, ambiguous characters stripped.
- **Easy to say** for passwords you have to dictate over a call. Alternating consonants and vowels.
- **Passphrase** for the master password to your password manager. Random words from the EFF large diceware list.
Plus a strength meter that runs zxcvbn on anything you type, a QR code for scanning a password into another device without typing it and a "generate 20 at once" button so you can pick your favourite.
The one design constraint that shaped everything
**Nothing leaves the browser.** Not to my server, not to Google, not to a third-party API. The generator, the strength meter, the QR encoder, the diceware wordlist. Everything is in the tab.
You can verify. Open DevTools → Network before you click Generate. There is no request.
That constraint drove a few decisions:
**Randomness comes from `crypto.getRandomValues`**, the Web Crypto API. Same source your browser uses when it negotiates TLS or generates a passkey. Never `Math.random`, which is fast but not cryptographic.
**Rejection sampling instead of modulo**. Naive `bytes[i] % pool.length` biases the output when the pool size does not divide 2^32. The fix is boring but critical: draw a random 32-bit value, throw it away if it falls into the biased tail, redraw. For a 26-character pool the loop runs once 99.99999% of the time.
**Zxcvbn ships lazily**. The strength meter library is 100 KB minified. If someone lands on the page and just wants a random password, they should not pay for a strength engine they never use. It only loads the first time you type into the analyzer.
**The diceware wordlist is a static asset**. 7,772 words, 62 KB, fetched from the same origin as the page the first time you switch to passphrase mode. Cached forever after that. No CDN, no API.
The educational section is deliberate
I could have shipped just the generator. But the two questions I get every time someone asks about passwords are:
- "Should I use symbols?"
- "Is a passphrase really as strong as a random password?"
The answers are "not really, add length instead" and "yes, and it is much easier to type". Both are on the page in full sentences. Both are wrapped in `HowTo` and `FAQPage` structured data so Google (and increasingly, AI answer boxes) can quote them directly.
What I would build next
Not sure. Maybe an in-browser JWT decoder that never sends the token anywhere. Maybe a diff viewer for sensitive text. The `/tools/` route is the pattern I want to follow: small, single-purpose, everything client-side, no signup.
If there is a tool you keep wishing existed, tell me. I take on a couple of outside builds a year and I always want good tool ideas for the in-between.
Meanwhile, the generator is at nimoyburrowes.com/tools/password-generator. If it saved you from a shady site, buy me a coffee.
