WordLock — Reference

This app generates passwords entirely in your browser. Nothing leaves your device — no network requests are made, no passwords are logged or stored on any server. Your settings and generation history are saved only in your browser's local storage.

Seven generator types are available, each optimized for a different use case, alongside the options they share, the appearance settings, and what the site is built with. Click any tile to jump to its documentation.

The site is also an installable web app: install it from your browser's menu and it runs in its own window and works fully offline — a generator that never talks to a server has no reason to require a network.

Simple

Generates a random string of characters from selected character sets.

Example output
mX7!vQ#nR2@kLpT9&wZ
Options
Password Length 6 – 128
Total number of characters in the generated password. The slider controls the exact count.
Lowercase letters
Includes a – z in the character pool when checked.
Uppercase letters
Includes A – Z in the character pool when checked.
Numbers
Includes 0 – 9 in the character pool when checked.
Symbols
Includes the full symbol set ! # $ % & ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~ when checked. At least one character type must remain selected.
Emoji 🎲
When checked, emoji characters are included in the pool as a fifth character type. Each position in the password has an equal chance of being any enabled type, so emoji slots count toward the total length. Off by default. See Shared Options — Emoji for the full pool details.
Exclude look-alikes
Removes the characters that read alike when a password moves between screens — 0/O and the four vertical strokes 1/l/I/| — from every enabled set. The strength breakdown states the measured cost (about 2.6 bits at 20 characters) and its remedy: one more character returns more than it takes. Off by default. These six are the tight set, the confusions that survive most fonts; the wider family (2/Z, 5/S, 8/B, 6/G, o/O) costs more than twice as much for rarer confusions and is deliberately not offered.

Each position draws a character type uniformly among the enabled types, then a character from that type — see Strength & Entropy for why that is slightly different from a uniform draw over the combined pool. No placement guarantees are made — to enforce minimums per type, use the Advanced generator.

Back to top

Advanced

Like Simple, but with per-character-type minimum and maximum counts, plus a customizable symbol set.

Example output (length 20, ≥2 of each type)
Kp3!mW#8vL$2rN@5qX&1
Options
Password Length 6 – 128
Total number of characters. Must be reachable by the sum of all minimums and not exceed the sum of all maximums.
Lowercase Letters
Min / Max
Min — at least this many lowercase letters will appear.
Max — no more than this many lowercase letters will appear.
Set Min to 0 to make lowercase optional.
Uppercase Letters
Min / Max
Same min/max controls for A – Z.
Numbers
Min / Max
Same min/max controls for 0 – 9.
Symbols
Min / Max + Symbol Set
Same min/max controls for symbols. Below the sliders, individual symbol chips let you choose exactly which symbols are included in the pool:

All — activate every symbol.
Common — activate a curated subset: ! @ # $ % & * - _ + = ?
None — deactivate all but one (at least one must remain).

Toggle individual chips to fine-tune. At least one symbol must remain active when the Symbols count is non-zero.
Exclude look-alikes
Removes 0/O and 1/l/I/| from every set, including your chosen symbol set. If stripping would empty the symbol set (only | selected), the set is kept as chosen. The strength breakdown states the measured cost from the counts actually drawn. Off by default.
Validation rules
The generator validates before producing a password: the sum of all minimums must not exceed the total length, and the sum of all maximums must not be less than the total length. An error notification is shown if either condition fails.
Emoji 🎲
Emoji 🎲
Min / Max
Same min/max controls as the other character types. Emoji slots count toward the total password length and are included in the min/max validation — the sum of all minimums (including emoji) must not exceed the total length, and the sum of all maximums must not fall below it.

Min defaults to 0 — emoji is effectively off until you raise the minimum or the random fill selects it. Set Min to 0 and Max to 0 to exclude emoji entirely. See Shared Options — Emoji for the pool details.
Back to top

Words

Combines random words from a built-in wordlist with separators, affixes, capitalization, and leet-speak substitutions.

Example output (4 words, Title Case, $ separator)
Flame$River$Anchor$Cloud
Options
Number of Words 2 – 20
How many words are drawn from the wordlist and joined together.
Word Separator
The character or characters placed between each word. See the Shared Options — Separator section for the full list of choices.
Exclude look-alikes
Keeps 0/O and 1/l/I/| out of the random separator, prefix and suffix draws. See Shared Options — Look-alikes.
Capitalization
Controls how each word's letters are cased. See Shared Options — Capitalization.
Prefix & Suffix
Optional characters prepended (prefix) or appended (suffix) to the full password. See Shared Options — Prefix & Suffix.
Leet Speak
Substitutes selected letters with look-alike characters. See Shared Options — Leet Speak.
Emoji 🎲
When enabled, a random emoji from a general-purpose pool is prepended to each word (e.g. 🌟Flame-🌊River). Toggling it immediately rebuilds the password using the current words without re-rolling them. See Shared Options — Emoji.
Word pills & lock
After generation, each word appears as a clickable pill. Clicking a pill swaps just that word while keeping all others and the current separator/affix values — useful for quickly replacing one word you don't like without regenerating the whole password.

The lock icon beside the pills freezes the current prefix, separator, and suffix so that clicking a word pill or the "Generate" button replaces only the words without re-rolling the affixes. While locked, the strength breakdown prices the held values at 0 bits (“locked — reused, adds nothing”) — a value reused across passwords is a constant, not a secret.
Character count pill
Once a password is generated, a small pill badge appears inside the output field to the left of the copy button, showing the total character count of the password at a glance. The pill is hidden when the field is empty.
Back to top

Passphrase

Builds a phrase from a configurable sequence of word slots, each with a grammar role (adjective, adverb, noun, verb) and an optional thematic category.

Example output (adj + noun + verb, UPPERCASE, $ separator)
SILENT$RIVER$FLOWS
Word Slots
The passphrase is assembled from an ordered sequence of word slots (up to 8). Each slot has a type and a category:

TypeColorAvailable Categories
Adj Blue Random, Colors, Size, Texture, Mood, Weather, Time
Adv Teal Random, Manner, Intensity, Time, Place
Noun Slate Random, Animals, Vehicles, Food, Places, Nature, Tech, Jobs, Music, Sports
Verb Amber Random, Movement, Action, Nature, Cognition

Each category draws from a curated list of ~100–220 words per category (2,400+ words total across all categories). The word pool is large enough that repeated words are rare even across many generations.
Slots can be added, removed, and reordered with the arrow buttons. The default structure is Adj + Noun + Verb.
Additional options
Word Separator
Exclude look-alikes
Keeps 0/O and 1/l/I/| out of the random separator, prefix and suffix draws. See Shared Options — Look-alikes.
Capitalization
Prefix & Suffix
Emoji 🎲
When enabled, each word gets a category-matched emoji prepended — words drawn from Animals get an animal emoji, Colors get a color emoji, and so on. Toggling immediately rebuilds using the current words. See Shared Options — Emoji.
Word pills & lock
Same as in Words. Each word pill is color-coded to its slot type.
Character count pill
A badge inside the output field shows the total character length of the generated passphrase. Hidden when the field is empty.
Back to top

Wireless

A WiFi-optimized passphrase generator with router-friendly defaults and an alliteration mode.

Example output (defaults: Adj + Noun, Title Case, hyphen, 2-digit suffix)
Crimson-River42
Example output with alliteration (letter S)
Silent-Sparrow87

Wireless uses the same slot-based word engine as Passphrase but ships with presets suited for WiFi network names: memorable, typeable on a phone keyboard, and visually distinct. All Passphrase options are available here with independent settings storage.

Generated passwords are guaranteed to be at least 8 characters. If a result falls below this minimum, the generator automatically retries (up to 10 times) before accepting the output.

Default presets
Word slots
Starts with Adj + Noun — a concise, memorable two-word phrase. Additional slots can be added to increase length and variety.
Separator
Hyphen — widely accepted by routers and easy to type on mobile.
Capitalization
Title Case — each word capitalized for readability.
Prefix
None — no prefix by default.
Suffix
2 Random Digits — a short numeric suffix helps meet the 8-character minimum and satisfies many router password requirements without making the phrase hard to remember.
Alliteration mode
The Alliteration toggle appears in the Word Slots card header. When enabled:

  • The generator finds letters that exist in all active slot categories, then picks one at random.
  • Every word pool is filtered to words beginning with that letter before a word is drawn.
  • The active letter is shown as a badge on the toggle button (e.g. S).
  • Clicking a word pill to swap a single word also respects the locked letter.
  • Hitting "Generate WiFi Password" picks a new shared letter each time.
  • If no letter is shared across all categories (rare), the constraint is silently dropped for that slot.

Alliteration produces passwords that are easier to dictate aloud: "Silent Sparrow Storm" is far easier to spell out over a phone than a random mix of words.
All other options
Word Slots
Same as Passphrase. Up to 8 slots; each has a type (Adj, Adv, Noun, Verb) and a thematic category.
Separator, Capitalization, Prefix & Suffix, Leet Speak
Identical to Passphrase. Settings are stored independently under the wifi.* namespace in localStorage.
Exclude look-alikes
On by default here — WiFi keys get read off a router label and typed on a phone or TV remote, which is exactly where 0/O and 1/l/I/| misfire. Filters the random separator, prefix and suffix draws. See Shared Options — Look-alikes.
Emoji 🎲
Same as Passphrase — each word gets a category-matched emoji prepended. Alliteration mode is respected: words are still letter-filtered, and the emoji is drawn from the word's category pool. Toggling immediately rebuilds using current words. See Shared Options — Emoji.
Word pills & lock
Each generated word appears as a clickable pill. The lock icon holds prefix/separator/suffix across word swaps and Generate, as in Words. When alliteration is on, swapped words are drawn from the same letter-filtered pool.
Character count pill
A badge inside the output field shows the total character length of the generated password. Hidden when the field is empty.
Back to top

Mad Lib

Fills a pre-written sentence template with random words, then compresses it into a password.

Example — "The Hero" template, Title Case, - separator
The-Silent-River-Swiftly-Crosses-The-Ancient-Bridge
Template
Choose one of 12 pre-written story templates. Each template is a sentence structure containing typed placeholders (adj, adv, noun, verb) that get filled with random words at generation time.

NameTemplate structure
The HeroThe {adj} {noun} {adv} {verb} the {adj} {noun}
The VillainA {adj} {noun} {adv} {verb} every {noun}
The Quest{noun} {adv} {verb} beyond the {adj} {noun}
Science!The {adj} {noun} {adv} {verb} any {noun}
Wise ProverbA {adj} {noun} {adv} {verb} alone
Breaking News{adj} {noun} {adv} {verb} the {noun}
Haiku-ish{adj} {noun} {adv} {verb}
Epic Tale{noun} and {noun} {adv} {verb} the {adj} world
MysteryA {noun} {adv} {verb} the {adj} {noun}
RomanceThe {adj} {noun} {adv} {verb} a {adj} {noun}
Sci-Fi{adj} {noun} {adv} {verb} every {noun}
FableOnce the {adj} {noun} {adv} {verb} alone

Literal words in the template (e.g. "the", "beyond", "alone") are included verbatim in the readable phrase preview but are not compressed into the password — only the filled placeholders are joined with the separator.
Word Categories
Each placeholder occurrence in the selected template gets its own category selector. When a template uses the same type more than once (e.g. two adj slots), each is listed separately and can have a different category. Category choices are the same as in Passphrase.
Additional options
Word Separator
Joins the filled words (not the literal template words). See Shared Options — Separator.
Exclude look-alikes
Keeps 0/O and 1/l/I/| out of the random separator, prefix and suffix draws. See Shared Options — Look-alikes.
Capitalization
Applied to each filled placeholder word. See Shared Options — Capitalization.
Prefix & Suffix
Emoji 🎲
When enabled, each filled placeholder word gets a category-matched emoji prepended. Literal template words (e.g. "the", "beyond", "alone") are not decorated. Toggling immediately rebuilds using current words. See Shared Options — Emoji.
Readable phrase preview
Shown below the word pills — displays the full human-readable sentence so you can verify or remember the password structure.
Word pills & lock
Same as in Words. Only token words appear as pills; literal template words are not swappable.
Character count pill
A badge inside the output field shows the total character length of the generated password. Hidden when the field is empty.
Back to top

Numbers

Generates a numeric PIN or code with configurable limits on repeated and sequential digits.

Example output (8 digits, max 2 repeated, max 2 sequential)
47293816
Options
Number of Digits 4 – 32
Total length of the generated numeric code.
Max Repeated Digits 2 – 5
Limits how many times the same digit may appear consecutively. For example, with a limit of 2, 33 is allowed but 333 is not. A value of 5 is effectively unconstrained for most PIN lengths.
Max Sequential Digits 2 – 5
Limits how long an ascending or descending run may be. For example, with a limit of 3, 123 or 987 is allowed but 1234 or 9876 is not. The direction must be consistent — a direction change resets the counter.

Numbers has no look-alike exclusion on purpose: an all-digit code has no letters for 0 or 1 to be confused with, so excluding them would spend entropy (3.32 → 3.00 bits per digit) buying nothing.

Back to top

Shared Options

The following options appear across multiple generator types with identical behavior.

Word Separator

Inserted between each word in word-based generators (Words, Passphrase, Wireless, Mad Lib). Literal separators (Space, Hyphen, …) are priced at 0 bits and the random ones at their pool's worth — see Strength & Entropy — Why a space is 0 bits for the reasoning.

OptionDescription
NoneNo separator — words are joined directly.
SpaceA single space character.
Hyphen -A literal hyphen.
Underscore _A literal underscore.
Period .A literal period.
Dollar $A literal dollar sign.
1 Random SymbolOne symbol drawn randomly from ! # $ % & * + - / : ; = ? @ ^ _ | ~ — the same symbol is used for every separator position in that generation.
2 Random SymbolsTwo random symbols from the same set, each drawn independently per generation.
New Symbol Each GapDraws an independent random symbol at every gap, so no two gaps need match — each gap adds its own entropy. Redrawn every generation, even when the affix lock is on.
1 Random NumberOne random digit (0–9).
2 Random NumbersTwo random digits.
New Number Each GapDraws an independent random digit at every gap, like New Symbol Each Gap.
1 Symbol + 1 NumberOne random symbol followed by one random digit.
1 Number + 1 SymbolOne random digit followed by one random symbol.
2 Symbols + 2 NumbersTwo random symbols followed by two random digits.
2 Numbers + 2 SymbolsTwo random digits followed by two random symbols.
Custom…Type any literal text to use as the separator (revealed when selected).

Exclude Look-alikes

Removes the characters that read alike when a password moves between screens — 0/O, and the four vertical strokes 1/l/I/|. The toggle appears in six generators, with a scope that fits each:

WhereWhat it filtersDefault
SimpleEvery enabled character set.Off
AdvancedEvery set, including your chosen symbol set. If stripping would empty the symbol set (only | selected), the set is kept as chosen.Off
Words, Passphrase, Mad LibThe random separator, prefix and suffix draws only — never the words, and never literal or custom text you typed.Off
WirelessSame as the other word modes.On — WiFi keys are made to be read off a router label and typed on a phone or TV remote, which is exactly where a misread l bites.
NumbersNot offered, on purpose: an all-digit code has no letters for 0 or 1 to be confused with, so excluding them would spend entropy buying nothing.—

The cost is measured and displayed, never hidden: the option pickers reprice live (a random digit drops from 3.3 to 3.0 bits), and the strength breakdown states the total with its remedy — “costs 2.6 bits — one more character returns 6.3.” These six are the tight set, the confusions that survive most fonts. The wider family (2/Z, 5/S, 8/B, 6/G, o/O) costs more than twice as much for rarer confusions, so it is deliberately not offered.

Prefix & Suffix

This group (like Leet Speak & Emoji) starts collapsed — most passwords never touch it. Click the header to open it; the open state is remembered per generator, and a collapsed group that is doing something shows an in use badge on its header.

Optional characters added to the very beginning (prefix) or very end (suffix) of the assembled password. Prefix and suffix are independent — either or both can be set.

The prefix shares the same options as the separator (None through Custom). The suffix has two additional options:

Suffix-only optionDescription
Mirror PrefixReverses the characters of the generated prefix and appends them. If the prefix is @7, the suffix becomes 7@.
Mirror Prefix (new digits)Same reversal, but each digit in the mirrored string is replaced with a fresh random digit — symbols are kept. Useful for symmetric-looking passwords where digits differ.

The lock icon in the output area freezes the current prefix, separator, and suffix values so that clicking a word pill or the Generate button regenerates only the words without re-rolling the affixes. While locked, the strength breakdown prices the held values at 0 bits — reused across passwords, they are constants, not secrets. The New … Each Gap separators are the exception: they redraw every generation even when locked, and keep their per-gap bits.

Capitalization

Controls the casing applied to each word before it is joined with separators and affixes.

OptionBehaviorExample
Title CaseFirst letter uppercase, rest lowercase.River Flow
lowercaseAll letters lowercase.river flow
UPPERCASEAll letters uppercase.RIVER FLOW
rAndOm LetTerSEach character is randomly uppercased or lowercased.rIvEr fLoW
AlTeRnAtInGAlternates uppercase and lowercase on each character (1st = upper, 2nd = lower, …).RiVeR FlOw
lasT letteRAll letters lowercase except the last letter of each word, which is uppercase.riverR floW
FIRST word onlyFirst word all-uppercase, remaining words all-lowercase.RIVER flow cloud
last word ONLYLast word all-uppercase, all other words all-lowercase.river flow CLOUD
WORD word WORD wordAlternates between all-uppercase and all-lowercase by word position (1st = upper, 2nd = lower, 3rd = upper, …).RIVER flow CLOUD drift
WORD word is RANDOMEach word is randomly chosen to be all-uppercase or all-lowercase.RIVER flow CLOUD DRIFT

Leet Speak Substitutions

After capitalization and assembly, selected letters are replaced with look-alike symbols or digits. Case is preserved where possible (e.g. A → @, a → @).

SubstitutionCharacter replacedReplacement
a → @a / A@
e → 3e / E3
i → 1i / I1
o → 0o / O0
s → $s / S$
t → +t / T+
l → !l / L!
b → 8b / B8
g → 9g / G9
z → 2z / Z2

All activates every substitution. None clears all substitutions. Individual chips can be toggled independently. Leet speak is applied last, after capitalization.

Emoji

All generators except Numbers support an Emoji 🎲 option. It is off by default and persisted independently per generator. Behavior varies by generator type:

GeneratorHow emoji is integrated
Simple Emoji is a fifth character type checkbox alongside Lowercase, Uppercase, Numbers, and Symbols. When checked, each position in the password has an equal probability of becoming any enabled type — so emoji characters are randomly distributed throughout the password and count toward the total length.
Advanced Emoji is a fifth character type with min/max sliders, identical to the other four types. Emoji slots count toward the total password length and are fully included in the min/max validation. Min defaults to 0 (effectively excluded); set Max to 0 to exclude emoji entirely.
Words A random emoji from a general-purpose pool is prepended before each word (e.g. 🌟Flame-🌊River).
Passphrase Each word gets a category-matched emoji prepended — a noun from Animals gets an animal emoji, an adjective from Colors gets a color emoji, and so on.
Wireless Same as Passphrase. Emojis respect alliteration mode — words are still filtered by the shared starting letter; the emoji is drawn from the word's category pool independently.
Mad Lib Each filled placeholder word gets a category-matched emoji prepended. Literal words from the template structure (e.g. "the", "beyond", "alone") are not decorated.
Numbers Not available.

Emojis are drawn from curated per-category pools (Animals, Colors, Food, Weather, etc.) totalling hundreds of options. The setting is saved to localStorage per generator and restored on your next visit.

Note: Many authentication systems and websites do not accept emoji characters in passwords. This option works best for passphrases stored in a password manager rather than for general account passwords.

Generation History

Each generator maintains its own history of recently generated passwords. Clicking any history entry restores that password to the output field. The history strip only appears when there are 2 or more entries.

The History control — in the settings gear, in the floating bar at the bottom of the page — sets the maximum number of entries kept per generator. With all seven in use at the default of 10, that is up to 70 stored passwords.

SettingEffect
Off (0)No entries are stored, and every generator's existing history is erased — not only the one currently open.
5 / 10 / 20 / 50Keeps up to that many entries per generator. Reducing the limit trims existing history to fit.

History is encrypted at rest: entries are stored in browser local storage as AES-GCM ciphertext, and the key — generated in your browser, marked non-extractable — lives in IndexedDB on your device. Pre-existing plaintext history is encrypted automatically on the first visit, across all seven generators at once. What that honestly buys: the history is shielded from casual inspection and from anything that scrapes localStorage off disk; it is not protected against someone with full control of your browser profile, because the browser must be able to use the key to show you the history. If the browser cannot encrypt, history stays in memory for the session and is never written to disk. It persists across sessions and is cleared when you clear site data for this page.

Active Tab

The last generator tab you had open is automatically saved to localStorage (global.activeTab) and restored the next time you visit the app. If no saved tab exists the app defaults to Simple.

Back to top

Strength & Entropy

Every generated password shows its entropy in bits, with a meter and a full breakdown. Here is exactly how those numbers are computed.

What the number means
Entropy measures how unpredictable a password is: N bits means an attacker who knows your exact settings would need, on average, 2N−1 guesses to find it. Each additional bit doubles the work. The figure counts only genuine randomness — the coin flips the generator actually made — never the length or appearance of the result. A long password built from few random choices is still a weak password, and the readout will say so.
Meter tiers
Weak under 40 bits, fair 40–60, good 60–80, strong 80 and up. The 40-bit line is anchored to offline attacks: modern hardware can try billions of guesses per second against a stolen password database, and 40 bits (~1012 possibilities) is roughly where that stops being quick.
Open the breakdown
The how? link under the meter itemizes every source of randomness. Options that add nothing say so explicitly — a deterministic capitalization pattern, a fixed separator, or leet substitution (a fixed mapping) each show 0 bits rather than being silently omitted.
Why a space is 0 bits
Pick Space as your separator and the picker prices it at 0 bits; pick 1 Random Symbol and it says 4.2. Both put one character between every pair of words — so why does only one of them count?

The bits count the generator's random choices, not the characters in the output. A fixed separator is chosen once, by you, in settings: every password you generate carries a space in the same positions, so across all possible outputs there is exactly one way those positions can read — and log2 1 = 0. A random symbol is drawn fresh at generation time from 18 candidates, so even an attacker who knows your settings must try all 18 — log2 18 ≈ 4.2 bits of real guessing work.

Assuming the attacker knows your settings is the standard, safe assumption — cryptography calls it Kerckhoffs's principle. Settings make poor secrets: there are only about fifteen separator choices to sweep, versus 17,576 possibilities per word, and settings are reused across every password you make while each password's draws are fresh. If an attacker genuinely doesn't know your settings, every figure shown is an underestimate — the safe direction to be wrong in. The same rule prices custom text, literal affixes, and leet at zero: anything you typed or toggled is part of the settings, not part of the draw.

A fixed separator still earns its place — it makes the password readable and typeable — it just does not make it harder to guess. That is the same trade as Title Case: worth choosing, and honestly priced at zero.
Per-generator math
Simple
The generator first picks a character type (uniformly among the enabled sets), then a character from that set. Entropy is therefore length × (log2 T + mean of log2 set sizes) for T enabled types. This is slightly less than the naive "log2 of the combined pool" formula most strength meters use, because equal type weighting makes a digit more likely than any single letter. We display the honest, smaller number.
Advanced
With a fixed count of each character type, entropy is the arrangement term (log2 of the multinomial coefficient — how many ways the types can be ordered) plus log2(set size) for each drawn character. When min/max ranges let the composition itself vary, the extra randomness in choosing the composition has no closed form, so the figure shown is a floor — the true entropy is at least what is displayed.
Words
Each word drawn from the Orchard Street list contributes log2 17,576 ≈ 14.10 bits, so the word count dominates. A random separator or affix token is drawn once per generation and reused at every gap, so it is priced once (an 18-symbol draw adds log2 18 ≈ 4.17 bits, a digit 3.32 bits). The New … Each Gap separators are the exception: they redraw at every gap and are priced per gap.
Passphrase & Mad Lib
Each slot contributes log2 of its pool size — a 359-noun slot adds about 8.5 bits, a 149-adjective slot about 7.2. Grammar templates make phrases memorable, but a predictable structure means only the pool sizes count. The category pickers state each pool's size and bits up front, so a narrow category shows its price before you choose it.
Wireless
Without alliteration, slots are priced like Passphrase. With alliteration, the shared first letter is one random draw (log2 of the usable letters), and each word is then drawn from the letter-narrowed pool — much smaller than the full list. The breakdown states the cost in bits versus free word choice, so the memorability trade-off is visible, not hidden.
Numbers
The repeat and sequence limits make some codes impossible and others more likely, so no simple formula applies. Instead the app replays the generator's own decision process over the finished code and computes the exact probability it had of producing it — the entropy shown is −log2 of that probability. The breakdown reports how many bits the limits cost versus unrestricted digits.
Bits per character
The foot of the breakdown states the password's efficiency — total bits divided by length — next to what random characters at the same length could carry (6.26 bits each, the Simple four-set figure). A passphrase might read 2.7 bits per character against that ceiling: the gap is what structure and memorability cost, paid for with length. Slot modes also show what the same word count drawn from the flat Words list would carry (14.10 bits per word), so the two passwords that both read as “three words” stop hiding their difference.
Guess times
The breakdown ends with the average time to find the password in four named attack scenarios: offline against a fast hash (a stolen database of MD5/SHA-1-style hashes, a GPU rig at ~1011 guesses/second), offline against a slow hash (bcrypt or argon2, ~104/second), online, throttled (a live login form, ~10/second), and online with a lockout policy (the classic domain-account rule: five wrong guesses lock the account for 15 minutes, about 480 tries a day). A single unqualified number would mislead — the same password is trivial in one scenario and infeasible in another, which is also why the 40-bit weak line is anchored to the fast-hash case. The lockout row is the argument at its sharpest: a 6-digit PIN that falls in under a second offline holds for about two years behind the lockout — which is how short PINs survive online at all, and why the offline rows are the ones that should drive your choices. Because that spread is the message, the two extremes — leaked database and lockout login — are shown right under the meter on every password, without opening the breakdown. 480 guesses a day and 1011 a second are different worlds. Times are average-case and assume the attacker knows your settings.

The math: N bits means 2N equally likely possibilities. An attacker sweeping them finds the password, on average, halfway through — 2N−1 guesses — so the displayed time is simply 2N−1 ÷ rate, in seconds.

Worked through for a five-word passphrase at 70.5 bits: 269.5 ≈ 8.3 × 1020 average guesses. Against the GPU that is 8.3 × 1020 ÷ 1011 ≈ 8.3 × 109 seconds ≈ 264 years; against bcrypt, the same guesses at 104/second stretch to about 109 years; online at 10/second, about 1012. And for the weak line: 40 bits is 239 ≈ 5.5 × 1011 average guesses ÷ 1011/second ≈ 5 seconds on one rig — which is why 40 is where the meter starts calling a password fair.

Because the time is 2 raised to the bit count, every added bit doubles it, and ten added bits multiply it by about a thousand. That is why one extra word (14.1 bits, ×18,000) or one extra random character (6.26 bits, ×77) moves the guess time more than any tweak to capitalization or substitutions ever could.
Excluding look-alikes
With look-alikes excluded, the random pools shrink (lowercase 26 → 25, uppercase 26 → 24, digits 10 → 8, symbols lose |) and every draw is priced from the reduced pool. The breakdown states the total cost and its remedy — at typical settings the cost is around 2–3 bits, less than the ~6 bits one extra character returns.
What never counts
Deterministic transformations add zero bits and are labeled that way: every capitalization mode except the two random ones, leet substitution (fixed mapping), fixed separators and affixes, and mirrored suffixes (a copy of characters already counted). Only new random digits inside a mirrored suffix are priced.
Tested, not trusted
The math is verified two ways. In the test suite, the Numbers model is proven to be a true probability distribution by enumerating every possible output and checking the probabilities sum to exactly 1, and canary tests fail the build if a generator's code drifts from the entropy model that mirrors it. Against the running app, generated output is collected in bulk and compared to the model statistically — character-type frequencies in Simple match the displayed model (and rule out the naive combined-pool formula), every Numbers output gets a finite, matching surprisal, and Words draws match the word list's own letter distribution.
Back to top

The Vault

Somewhere for a password to go after you generate it — encrypted with a passphrase you choose, stored on this device, and belonging to no account.

What it is

A generator is a moment-tool: you arrive, take a password, and leave. With the clipboard timer on, the only copy is gone thirty seconds later. The vault is where that password can go instead — a list of entries, encrypted as a single sealed blob in this browser's storage, unlocked with a passphrase only you know.

There is no account and no server. Nothing is uploaded, nothing is synchronised, and nobody — including us — can open your vault or reset your passphrase. That is the whole point, and it is also the whole cost: see Backups, because it means the only copy is the one you keep.

Vault vs. History
Two different things, deliberately kept apart. History is a short list of what you recently generated, encrypted with a key the browser holds for you, and it forgets on its own. The vault is a deliberate act: you name an entry and put it there, and it stays until you remove it. Turning History off does not touch the vault, and nothing in history is ever promoted to the vault without you pressing Keep.
How it is encrypted
Key derivation
Your passphrase is stretched into an encryption key with PBKDF2-SHA256 at 1,000,000 iterations — comfortably above the 600,000 OWASP recommends as a floor for that combination. The stretching is what makes a guessing attack expensive: an attacker with your encrypted vault file must pay those 1,000,000 rounds for every passphrase they try, which turns billions of guesses per second into a few thousand.
Why not ten million?

Because it would barely help. An attacker's cost rises linearly with the iteration count, so the strength it buys rises only logarithmically. Going from 600,000 to 10,000,000 is 16.7× the work, which is log2(16.7) ≈ 4.1 bits — less than one extra random lowercase letter. It would cost about a second of waiting every time you unlock on a fast computer, and several on a phone.

Adding one more word to your passphrase beats it outright, and costs nothing. A word from the generator's list is worth 14.1 bits — more than three times what a sixteen-fold slowdown buys. That is the same arithmetic the rest of this page runs on: bits come from the number of random choices made, and stretching only raises the price of each guess.

Why not Argon2id?
It is the better algorithm, and we would rather use it. PBKDF2 is merely slow; Argon2id is memory-hard, which is what actually blunts an attacker running thousands of guesses in parallel on a graphics card — and no iteration count fixes that, because iterations raise the cost of each guess without limiting how many run at once. The obstacle is that browsers do not implement it: the built-in crypto offers PBKDF2 and nothing comparable, so Argon2id would have to arrive as a compiled WebAssembly bundle sitting in the most security-critical path in the app. For a site whose whole claim is that you can read the source, that is a trade to make deliberately rather than quietly. Each vault records the parameters it was sealed with, so switching later will not strand anything.
The sealed vault
Entries are encrypted together as one blob with AES-256-GCM, under a random salt and a fresh random IV each time it is written. GCM is authenticated, so a vault that has been tampered with fails to open rather than opening with quietly altered contents. Nothing outside the blob reveals how many entries there are or what they are called.
Where the key lives
In memory, only while the vault is unlocked, as a non-extractable CryptoKey — a handle the page can encrypt with but cannot read the bytes of. Locking discards it. The passphrase itself is never stored anywhere, in any form.
Raising the bar later
The iteration count is recorded inside each vault, so raising the default in a future version never strands an older vault. If yours was made at a lower count, the vault page says so and changing the passphrase re-encrypts it at the current one.
Locking
Auto-lock
The vault locks itself after a period with no activity — 15 minutes by default, adjustable in the settings gear (Vault lock: Every page, 1, 5, 15 or 60 minutes). Locked means the key has been discarded, not merely hidden; reopening needs the passphrase again. The deadline is checked against the clock rather than trusted to a timer, so a laptop that slept through it locks on waking rather than staying open.
Moving between pages

Within that same window, walking from the generator to the vault does not ask for the passphrase again. Making that work costs something specific and worth knowing: the vault key is written to browser storage, wrapped under a second key the browser holds, so the next page can pick it up. For the length of the window, that is a slightly weaker position than "the key exists only in memory".

Setting Vault lock to Every page switches this off entirely: nothing is stored, the key is never even made exportable, and every page asks. The same setting governs both the idle timeout and this window, so there is one number to reason about rather than two.

What an entry holds
Label & password
The password, a label for it, and — when the entry came from Keep — the exact entropy the generator computed at the time, shown as a coloured pill so a weak old entry is visible at a glance. Passwords are masked until you reveal them, and copying one starts the same clipboard-clear timer the generator uses.
Username & web addresses
A username, and any number of web addresses — one per line when editing, shown by host so a long link does not swamp the row. Both are searchable along with the label and note.
Anything else
Named fields you add yourself, for whatever the account actually needs — a second login, a PIN, a customer number, a support passphrase. Mark one secret and it behaves like the password: masked until revealed, copied through the clipboard timer, and it can be generated. Leave it plain and it is just text, because hiding a customer number behind a row of dots helps nobody.
Security questions

Question and answer pairs, masked and copyable exactly like the password, because that is what they are: a second password with a friendlier name. They are covered by the clipboard timer too.

The answers need not be true. Your real mother's maiden name and the street you grew up on are matters of public record; an invented answer stored here is strictly stronger, and the only reason people use the true one is that they have nowhere to keep the invented one. Now you do.

Generating into an entry

Every secret field in the vault has a Generate split button beside it: the left half runs whichever of the seven generators is in use and says which (Generate Words), and the arrow beside it opens the list to change that. It runs that generator with its own current settings — whatever the Words tab is set to is what the Words option produces here. There is deliberately no second copy of the options: one place to configure a generator, and it is that generator's tab.

Picking from the list sets the generator rather than running once with it, so there is one generator in use and the password row always shows which. The control is on every secret box for a plain reason: choosing a generator used to mean scrolling up to the password field, changing it there, and scrolling back.

The entropy comes back with the password and is stored on the entry, so something generated here carries the same exact figure as something filed with Keep — not an estimate. The two paths run the same code.

Security answers too
The same button sits on every security answer. An answer that came out of the generator is the strongest possible version of a field whose usual content is a fact about you that other people know.
Groups & sorting
Groups
A free-text field, not a managed folder tree. Type anything — Finance, Work, Household — and it joins the suggestions offered on every other entry. A vault of a few dozen entries does not need a taxonomy, and the cost of imposing one is that every new entry becomes a filing decision. Leave it blank and the entry sits under Ungrouped, which is a perfectly good place to stay.
How the list is arranged
Groups are the outer order, sorting the inner one — entries are sorted within their group, and the group headings appear only once something is actually filed. Ungrouped sorts last: it is where things sit when nobody has decided, and leading with the undecided pile would be an odd headline.
Choosing which groups to show
The group button opens a list of checkboxes, so you can show several at once rather than one at a time. Ticking nothing means all groups, not none — an empty list is never what anyone wanted. With exactly one group ticked, a new entry starts in it; with several, it starts blank, because guessing between them would be worse than not guessing.
Group them (the toggle)

Turn grouping off and the list becomes one flat run in pure sort order. This matters more than it sounds. With grouping on, Weakest first means weakest-within-each-group, so the worst password in the whole vault can sit halfway down the page under a heading.

A four-entry vault at 128, 56, 26 and 56 bits sorts grouped as 56, 128, 26, 56 and flat as 26, 56, 56, 128. The first is right for finding an entry you already know about; the second is right for auditing. No single default serves both, which is why it is a switch rather than a decision.

Sort orders

Newest first (the default, because the thing you just saved is the thing you most likely want back), Oldest first, Name, and Weakest first.

Weakest-first is the audit view: it orders by the stored entropy so the entries worth changing come to the top. Entries with no recorded figure sort to the bottom, not the top — an unknown number is not evidence of a weak password, and putting the unknowns first would bury the ones you can actually act on. Anything without a date sorts as oldest, because an entry predating the date field genuinely is.

Tags
Why both
A group is one dimension: an entry is filed in exactly one, the way a piece of paper is in exactly one drawer. Tags are as many dimensions as you like. The company credit card really is both Work and Finance, and forcing that into a single folder means losing one of the two answers. Groups still decide where the entry lives; tags describe what it is.
How they are stored
Lower-cased, with runs of whitespace collapsed, deduplicated and kept in alphabetical order. So Work and work are the same tag rather than two that look identical in a list. Thirty per entry, forty characters each — limits high enough that nobody will meet them by accident and low enough that a bad import cannot fill the vault with them.
Filtering is and, not or
This is the one thing worth stating outright, because the tag menu looks exactly like the group menu and does the opposite. Ticking two groups shows entries in either: an entry has one group, so and would always return nothing. Ticking two tags shows entries with both: an entry has many, and work plus needs-2fa means the things that are both. The menu says so above the list rather than leaving it to be inferred from the results.
Adding them
Type and press Enter, or pick from the tags already in use — every existing tag is offered as a chip below the field, and clicking one toggles it. A tag on a saved entry is a button: clicking it filters the vault to that tag, which is the entire reason for having tagged anything. With tags ticked in the filter, a new entry starts with them already applied.
In exports
Tags survive the encrypted backup and the plain JSON export intact, and the CSV has a tags column of its own — space-separated, which is the shape 1Password and Bitwarden both read. Imports recognise tags, tag and labels, so a 1Password CSV arrives tagged rather than flattened.
One-time codes

Lose this vault and you are locked out. The seed lives only here. If this browser's data goes and there is no backup, the password is gone and so is the second factor — which is exactly the situation the second factor exists to survive. Keep an encrypted backup, and keep the provider's own recovery codes somewhere else entirely.

And it weakens two-factor authentication. A one-time code is a second factor only while it is kept apart from the first. Storing the seed in the same vault as the password collapses two factors into one: whoever opens the vault has both, and an attacker who gets in needs nothing else.

It is still a real gain against the common case — a password leaked from the site's own database, where the attacker never touches your device. And it is the same trade every password manager offering this feature makes. The difference is that here it is said before you paste the secret rather than discovered afterwards. If you would rather not make the trade, keep the codes in a separate app; that is the stronger arrangement and always was.

Adding one
Paste the otpauth:// link or the base32 secret. Most sites put both behind a "can't scan the QR code?" link. The full link is better: it carries the digit count, interval and hash algorithm, so nothing has to be assumed. A secret with an invalid character is rejected rather than accepted and quietly mangled — six plausible digits that never work is a miserable thing to debug.
Using it
The current code shows on the entry with the seconds remaining, and is not masked — it expires in under a minute, and a reveal click on the one time-critical thing in the vault would be pure friction. The countdown turns amber for the last five seconds, when starting to type it is a mistake.
Correctness
RFC 6238, computed with the browser's own HMAC — no dependency, nothing to trust beyond the platform. The implementation is checked against the test vectors published in the RFC itself, for SHA-1, SHA-256 and SHA-512, rather than against another implementation of the same guesswork.
Reused passwords

If two entries share a password, both say so — a badge on the entry naming how many others use it, a summary line above the list, and a filter to show only those. Editing an entry warns as you type, before the password is filed under a second name, and names the entries it collides with.

Reuse is the failure that turns one breach into several: the site that leaks your password is rarely the site you cared about, and it hands over the one you did. It is also the only piece of password health a vault like this can assess with certainty — no guessing, no corpus, no network. It is comparing what is already in front of it.

Exact matches only
Password1 and Password2 are two passwords, and so are Password1 and password1. There is deliberately no fuzzy matching: a near-miss flagged as reuse is a guess presented as a finding, and this page does not do that anywhere else either.
Still nothing leaves the device
The check runs entirely in memory on the vault you have open. This is the local kind of password health; the remote kind — asking a service whether your passwords appear in a breach corpus — is on the permanent no list, along with telemetry. See Legal.
Backups, export and import

A vault living in one browser profile is one clear site data away from gone, and no account exists to recover it from. The vault page keeps a quiet line of text — not a modal — noting how many entries have been added since your last backup.

Under it is an expandable list of the last five backups: when each was made, how many entries the vault held at the time, and which browser made it. The count is what makes an old one legible — "3 entries" against today's forty says more than the date does. This record lives inside the vault, not in this browser, so every machine that opens it sees the same history; a backup made in Chrome is not reported as missing by Edge. Only encrypted backups are recorded, because a plain-text export is not a backup. It is a note that a file was made, not proof it still exists.

Encrypted backup
A .json file containing the sealed vault verbatim: still encrypted, safe to keep in cloud storage or on a drive, and restorable only with the passphrase it was made with — not necessarily the one your current vault uses. This is the backup, and it is the default.
Plain-text export

JSON or CSV with your passwords in the clear, behind a confirmation that says so, with PLAINTEXT in the filename. This exists for one purpose — moving to a different password manager — and the file should be deleted the moment that is done.

We would rather not offer it. It ships anyway, because refusing every exit but "another copy of WordLock" is lock-in, and an escape hatch you cannot use is not an escape hatch. CSV is additionally lossy: a row is flat, so only the first web address survives and security questions are folded into the note.

Import
Reads an encrypted WordLock backup, a WordLock plain export, or a CSV from another manager — the common header names from Bitwarden, LastPass and 1Password are recognised. Importing always merges and never deletes: entries already present are skipped, new ones are added, and restoring an old backup cannot silently wipe work done since.
Choosing the passphrase

This one passphrase is the only key to everything in the vault, so the page shows a live strength reading as you type it — and labels it at most N bits rather than a score. That wording is deliberate. Everywhere else on this site the entropy figure is exact, because the generator made every random choice itself and can count them. It cannot know what went into a passphrase you typed. A real attacker's dictionary knows words, names, dates and keyboard patterns that a few hundred lines of arithmetic do not, so the honest reading is a ceiling: it can tell you a passphrase is bad, never that one is good.

The reliable way out of that uncertainty is to generate a passphrase and use it, at which point the number stops being a guess.

Refused outright
A passphrase on the built-in list of the few hundred passwords attackers try first is rejected, not merely scored badly. Against a vault, such a passphrase is not a weak key; it is no key at all. The list is compiled offline and shipped with the site — nothing you type is ever sent anywhere to be checked.
Nobody can reset it for you
There is no reset link, because there is nobody to send one. Forget the passphrase with no recovery key and the vault cannot be opened, by you or by anyone. Deleting it also requires the passphrase, so in practice a forgotten vault sits there until you clear this site's data in your browser. A recovery key is the one thing that changes this, and it is a key you hold rather than one we do.
Recovery key
What it is for
A second way into the vault, for the one failure a backup cannot touch: forgetting the passphrase. The two are complements and you want both. A backup protects the data — if the device dies, the file is what brings it back. A recovery key protects access — a backup you cannot decrypt is as lost as no backup at all. Neither substitutes for the other, and a recovery key does nothing at all for a vault that was never exported and no longer exists.

How two keys open one vault. The short version: your passwords are not encrypted with your passphrase. They are encrypted with a random key, and it is that key which gets locked up — once per way in.

When the vault is created the browser generates a master key: 256 random bits, never typed by anyone and not derived from anything you chose. That key encrypts your entries, and it is the only key that ever touches them. The master key is then encrypted — wrapped — under a key derived from your passphrase, and the wrapped copy is what gets stored.

Making a recovery key wraps the same master key a second time, under a key derived from the sixteen words. So the stored vault holds three things: your entries encrypted under the master key, and two locked copies of that master key. Unlocking is the same operation either way — derive a key from whichever secret you have, use it to unwrap the master key, use the master key to read the entries.

What that shape buys, and why it is worth the extra step:

  • Neither key reveals the other. Opening the passphrase copy gives you the master key and nothing else. There is no path from one locked copy to the other, so holding one does not help you find the second.
  • Changing the passphrase does not invalidate the recovery key, and costs 32 bytes of work rather than re-encrypting the whole vault. The master key never changed; only the lock around one copy of it did.
  • Removing the recovery key is deleting one field. Your entries and the master key are untouched — the second copy simply stops existing.
  • Recovering deliberately breaks that pattern. It generates a brand new master key and re-encrypts under it, rather than re-wrapping the old one. That is the point: the forgotten passphrase’s copy does not survive, so anyone who might have learned it is locked out along with your memory of it.

The plainest way to picture it: the master key is the key to your house. You put a copy in two lockboxes, one opening to your passphrase and one to the recovery words. Changing a lockbox combination does not change the house key, and losing one combination does not matter as long as you know the other. Lose both and the house stays shut — there is no locksmith, because there is no one holding a third copy.

Sixteen words, generated, never chosen

Drawn here from the same 17,576-word list the Words generator uses: 14.1 bits a word, 225 bits in total. There is deliberately no way to supply your own phrase, and that restraint is the whole security argument rather than fussiness.

A vault with two keys is only as strong as the weaker one, because an attacker takes whichever is cheaper to break. A memorable recovery phrase would therefore become the real strength of your vault, silently, no matter how good the passphrase was. At 225 bits of generated randomness the recovery path is not attackable at all, so the passphrase stays the binding constraint and this costs nothing. Between those two positions is a trap: anything memorable is anything guessable.

Words rather than a string of base32, because this gets written on paper and typed back by hand, months later, by someone already having a bad day. Duplicates are allowed — each draw is independent, which is exactly what makes the bit count true; removing them would look tidier and quietly lower it.

Shown exactly once
The vault stores your master key encrypted under those words, which is not the same as storing the words. There is no screen that shows it again, because there is nothing to show. Lose it and you generate another — which retires the previous one the moment it is made, so the old paper stops working.
It is a second key to everything
Anyone holding those words can read every password in the vault without knowing your passphrase. Store them the way you would a spare house key: on paper is fine, inside the vault is not, and the same drawer as the laptop is worse than a different building.
Using it retires it
Recovering asks for the key and a new passphrase together, so the vault is never sitting open with no passphrase anyone knows. Afterwards the forgotten passphrase no longer works — the vault is re-sealed under a brand new master key, so whoever might have learned the old one is locked out too — and the recovery key is spent, because it has just been typed onto a screen and possibly read aloud. Make a fresh one from settings.
Adding or removing one needs the passphrase
Even with the vault already open. An unlocked tab proves a tab is open, not who is asking, and minting a permanent second key to someone's vault — or removing the one they are relying on — is not something a passer-by should be able to do. The same rule guards deleting the vault.
Where the vault is kept

By default the vault lives in this browser's storage and nowhere else. It can instead live as a single encrypted file in a folder you choose — and if that folder is one your computer already syncs, such as Dropbox, OneDrive or iCloud Drive, then your vault is carried between machines and backed up by software you already trust, with no account here and nothing of ours in the middle.

What the file contains is the same sealed ciphertext the browser was holding. Your cloud provider learns that a file changed and roughly how big it is. It never learns what is in it, because it cannot.

Move it to a folder
Copies the vault out, reads it back to check it arrived, records the new location, and only then removes the old copy — in that order. If any step fails nothing has changed, and a folder that already holds a WordLock vault is refused rather than overwritten. Two vaults meeting is a merge, and silently replacing one with the other is the worst answer available.
Open a vault in a folder
The opposite operation, and how a second computer joins: it requires a vault to already be there, writes nothing at all, and only records where to look. You unlock it with its own passphrase. Deliberately a separate button from Move rather than one that guesses — a control whose destructive behaviour depends on what it happens to find is fine until the day it is not.
Two computers, one folder

Saving reads what is in the folder first and merges rather than overwriting. Entries added on either machine survive, and a deletion made on one is not resurrected by the other still holding the entry. The same applies to two tabs of one browser, which is the same problem over a shorter distance.

If you both changed the same entry, it stops and asks. You get the fields that differ side by side and three choices: keep yours, keep theirs, or keep both as two entries. Nothing is written until you pick. It asks because it cannot know — the timestamps only say which was saved last, not which knew more, and an edit box open in one browser holds a copy from before the other browser saved.

What this does not cover. Two machines saving while the folder itself is out of sync — offline, or inside the seconds your cloud client takes to catch up — is resolved by Dropbox or OneDrive, not by us: they write a second conflicted copy file, which this page cannot see. Import that file and its entries merge back in.

Stop using it here
Leaving a folder vault is not a way of deleting it. This forgets the folder on this browser and touches nothing in it: the file stays, other devices carry on, and this browser locks the vault and offers to make a new one. It asks for no passphrase, because nothing is destroyed. That is the way off a work machine or a browser you were only trying, without deleting anybody's vault and without clearing site data.
If the folder cannot be read
Browsers forget folder access after a restart, and a drive can be unmounted or a directory renamed. That gets its own screen saying the vault is not lost, with a Reconnect button — a button, because the permission prompt requires a deliberate click and a page that could silently reopen a folder would not need to ask. It is never reported as "no vault found", because the answer to that is an offer to create one, on top of a real vault.
Which browsers

Chromium on the desktop — Chrome, Edge, Brave, Opera. This needs the File System Access API to write back to a file you chose, and Firefox and Safari have not implemented it. That is unlikely to change: Mozilla's published position on the folder and file pickers is harmful. Reading a file you pick works everywhere, which is why Import works in every browser; it is writing back that has no equivalent. Elsewhere the vault stays in the browser and an encrypted backup is how it moves.

Not on phones, deliberately, even where the browser allows it. Chrome and Edge on Android both have the API, so this used to be offered there — and then asked to reconnect on every refresh — not each time you open the app, each time the page loads — and twice over, once in the page and once from Android itself. Its picker also lists local storage rather than the cloud locations your provider’s app shows, so there was nothing to sync with even after all that. A button that relocates the only copy of your vault should not lead somewhere that awkward, so it is not shown. Keep the vault in the browser on a phone, and move it with an encrypted backup.

Storage
Persistent storage
On creating a vault the page asks the browser not to evict it under storage pressure, via navigator.storage.persist(), and shows you the answer. It asks again on every visit, because the answer can change. If the browser has not promised, the vault page says so rather than letting you find out by losing it.
If it says it has not promised

Install the app. That is the reliable fix. Chrome and Edge never ask you about this — they decide, granting it once a site is installed, bookmarked, or used often enough, and reporting it as refused until then. So "denied" usually means "not yet", not "no". Use Install or Add to Home Screen in the browser menu and it is generally granted the next time you open the vault. Firefox does ask, and there the Ask again button is the request.

It is also worth knowing how unlikely eviction is. Browsers evict under genuine storage pressure, least-recently-used first, and a vault is tiny — the page shows you its size against the space available, which is typically a few dozen kilobytes against several gigabytes.

None of it replaces a backup. A promise not to evict is not a promise against a lost laptop, a reinstalled browser, or your own hand on Clear browsing data — which ignores the promise entirely. Keep an encrypted backup.

Back to top

Appearance & Settings

The gear in the floating bottom bar, available on every page.

Theme
Light / Dark / System

System follows your operating system's appearance setting and switches live if you change it while the page is open. Choosing Light or Dark overrides that and stays fixed.

Your choice is saved in localStorage and applies across every page. It is applied before the page draws, so switching to dark never flashes the light theme first.

Text size
Default / 112% / 125% / 150%
Scales the whole interface, not just the text — controls, spacing and icons grow with it. Applied as a percentage of your browser’s own font size, so if you have already raised that, this multiplies it rather than replacing it. Saved across pages and applied before the page draws.
Colors
Sky / Blue / Indigo / Violet / Fuchsia / Rose / Emerald / Teal / Slate / Mono

Ten accent themes, independent of Light and Dark — every one works in both. A theme changes the accent color, the focus ring and the page background. In dark mode it also tints the cards, so a violet theme is violet throughout rather than the same gray card with a violet button.

Mono is a true grayscale theme. It is the only one that also drops color from the status messages and the changelog categories, which then tell themselves apart by lightness instead of hue.

Saved in localStorage and applied before the page draws, like the others.

The eye marker

Marks themes whose accent stays clearly distinct from the success, warning and error colors for every kind of color blindness — protanopia, deuteranopia and tritanopia. Blue, Indigo, Violet, Slate and Mono qualify.

An unmarked theme is not a problem to use. Nothing here depends on color alone: every status message and every changelog category is labelled in words. The marker only says the color is doing useful work on top of the words.

It is measured rather than asserted. Each theme is simulated under all three deficiencies and the color distances recomputed on every build, so the marker cannot quietly go out of date. Two candidate themes were rejected by that process: an amber accent that was identical to the warning color, and an earlier, brighter red that made error messages stop standing out.

What the marker deliberately does not cover: the accent's distance from the changelog category colors and the docs badge colors. Those were measured too, and several accents sit close to — or exactly on — a family color, by design: the Sky accent is the sky badge color. That is reuse, not confusion. Status colors are signals that must be tellable apart from an interactive accent; categories and badges always carry their names in text, so hue never bears their meaning alone. A floor that failed a palette for matching its own badge would be a badly chosen floor.

History
Entries per generator
Shown on the generator page only, since the other pages have no history. See Generation History for what each setting does.
Bit hints
On / Off
Shown on the generator page only. Controls the advisory bit annotations: the ▲ vs last chip in the strength readout, the price tags on the separator, prefix, suffix and capitalization options (1 Random Symbol · 4.2 bits), and the pool sizes in the category pickers (Colors — 149 · 7.2 bits). Some people find the running commentary useful; others find it noisy. Turning it off hides only the coaching: the total, the tier, the meter and the “how?” breakdown all stay. See Strength & Entropy.
Clear clipboard
Keep / 30s / 60s / 2 min
Shown on the generator page only. After you copy a password, the clipboard is wiped once the chosen delay passes. The wipe is deliberately blunt: it overwrites whatever is in the clipboard at the deadline — including something else you copied in the meantime — because checking first would mean asking permission to read your clipboard, which this site has no business requesting. It also never triggers a permission prompt of its own: where the browser allows silent clipboard writes the wipe fires right at the deadline, and everywhere else (Edge prompts for gesture-less writes) it waits for your next click or keypress, which lets the write through without asking. Off (“Keep”) by default.
Generator shortcuts
Regenerate
On the generator page, pressing R generates a new password on whichever tab is active. It stays out of the way while any form control has focus, so typing an r into a custom separator or prefix never fires it.
Keyboard
Operating the panel
KeyAction
Enter / SpaceOpen or close the panel
Arrow keysMove between the options in a group
Home / EndJump to the first or last option
EscapeClose the panel and return focus to the gear
TabLeave the panel, which closes it
Back to top

Built With

The tools and technologies used to create this app.

Vue 3
The UI is built with Vue 3 using the Composition API, loaded as a native ES module from a copy served by this site. Reactivity, computed properties, and watchers drive all generator logic without any external state-management library.
Nothing between the repository and your browser

There is no bundler and no deploy pipeline. The browser loads src/main.js as a native ES module and the site is served as plain static files, so what runs in your browser is exactly what is in the repository — readable, and checkable.

One thing is generated rather than hand-written. Component templates are compiled to render functions ahead of time, so the browser never compiles them itself — which is what lets the security policy refuse unsafe-eval and the page ship a Vue build with no compiler in it at all. Both halves are committed: the templates you would actually read, in src/templates/, and the generated code that runs. A test recompiles the first and fails if it no longer produces the second, so the two cannot drift.

Material Design Icons
All interface icons are served from the @mdi/font icon font. Icons are referenced by CSS class name and require no additional JavaScript.
AI-assisted development
Much of this app was built with assistance from Bolt, an AI-powered coding environment, which accelerated the initial feature development and UI design. Claude Code has handled later work: the move to a cryptographic random source, the design token system and color themes, the accessibility audit, and the test suite.
Render
The app is hosted on Render, which serves the static build output. Deployments happen automatically on every push to the main branch via the render.yaml configuration file.
Back to top