Skip to content

Band Name Validation

Every submitted band name goes through four checks in order. Failing any check ends the game immediately — the submitting player loses.

Validation Order

  1. Not empty
  2. Not a duplicate
  3. Exists on Spotify with ≥ 500 followers
  4. Follows the letter chain

1. Not Empty

The band name, after trimming whitespace, must have a non-zero length.

Error: "Band name cannot be empty"


2. Duplicate Detection

The same band cannot be played twice in the same match.

Normalisation rule: strip a leading "The " (case-insensitive) and lowercase the remainder before comparing.

text
"The Beatles"  →  "beatles"
"Beatles"      →  "beatles"   ← same, rejected
"BEATLES"      →  "beatles"   ← same, rejected
"Metallica"    →  "metallica"

Only moves with moveType = 'playBand' and valid = true in the current match are checked.

Error: "Band name already used in this game"


3. Spotify Lookup

Handled by SpotifyService.validateBand().

Calls GET /v1/search with:

  • q: the submitted band name
  • type: artist
  • limit: 5 results

Name Matching (case-insensitive)

The service checks results against three forms of the submitted name:

If input…Also checks
Does NOT start with "the ""the " + input
DOES start with "the "input without the leading "the "

A result matches if artist.name equals any of the above variants (case-insensitive).

Follower Threshold

Matched artist must have followers.total >= 500.

Error (not found): "No band with the name \"{bandName}\" found on Spotify."
Error (too few followers): "Band has too few followers ({count}). Minimum required: 500."
Error (API failure): "Failed to validate band with Spotify API"

Canonical Name

The Spotify artist name is used as the canonical band name — not what the player typed.

text
Player types:  "beatles"
Spotify finds: "The Beatles"
Stored as:     { bandName: "The Beatles", submitted: "beatles" }

The submitted field is only stored when it differs from the canonical name. All downstream checks (letter chain, duplicate detection) use the canonical name.

Token Management

  • Uses Spotify client credentials flow (no user login needed)
  • Token cached in memory with expiry; auto-refreshed when stale
  • Requires env vars: SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET

4. Letter-Chain Rule

Each band name must start with the last letter of the previous canonical band name.

"The" Handling

The word "The" at the start of a band name is treated as a prefix, not part of the effective name for letter-chain purposes.

  • Starting letter: first letter of the word after "The"
  • Ending letter: last letter of the full canonical name (including "The" bands — last letter of the last word)
text
"The Cardigans"  →  effective start = 'C',  end = 'S'
"The Stooges"    →  effective start = 'S',  end = 'S'
"Slayer"         →  effective start = 'S',  end = 'R'

Special Case: Previous Band Ends with 'T'

If the previous band name ends with the letter 'T', any band starting with "The" is also valid, because the T in "The" satisfies the chain.

text
Previous: "Warrant"  (ends R) → next must start with R
Previous: "Accept"   (ends T) → next can start with T OR be any "The X" band

First Move

The first band in any game always passes the letter-chain check (no previous band to match against).


Move Response Shapes

Valid move:

json
{ "success": true, "gameState": { "..." } }

Invalid move (game ends, player loses):

json
{
  "success": false,
  "illegal": true,
  "reason": "No band with the name \"Bnad\" found on Spotify.",
  "gameState": { "...with move recorded as invalid..." }
}

Rejected move (not recorded, game continues):

json
{
  "success": false,
  "error": "Not your turn"
}

Move rejections (not your turn, game not active, player not in game) do not end the game and do not record the move. Only invalid band submissions end the game.