The main problem turned out to be validation. I hugely underestimated this! The validation stack ended up as: blocklist (offensive words), already-used check, stored-path check, connections payload, human-approved matches from previous games (we queue all of these to audit), WordNet subset, ConceptNet subset, extra-pairs, lemma exceptions, hypernyms, troponyms, non-rhotic rhymes. If no match found after all those client side checks we hit some APIs (Datamuse and RhymeBrain in both directions). If all else fails lemma suffix-strip, prefix-antonym check and a local rhyme check. Despite those checks there are some obvious connections that still get rejected but hopefully enough accepted ones that the player does not give up. I was quite pleased with the share dynamic; the recipient will be presented with a challenge where their result will be compared with yours at the end.
It's free, no signup, no ads. Honest feedback would be great and anything constructive even better.