Follow your rivals: friends and a friends leaderboard
Follow the players you enjoy beating, see them ranked on their own leaderboard tab, and manage everyone from a new Friends page with nickname search.

In plain words
opolyx is more fun with people you recognise. You can now follow any player — tap Follow on their profile, or find them by nickname on the new Friends page — and they show up on a leaderboard tab that is just you and the people you follow.
Following is one-way, like on most social apps: you do not need them to follow you back, and there is nothing to accept. A leaderboard is a public ranking anyway, so following someone reveals nothing they had not already made visible.
- Follow / unfollow from any profile page with a single button.
- A new Friends page with Following and Followers tabs and a nickname search to find players.
- A Friends tab on the leaderboard ranks you and everyone you follow by XP.
- Follower and following counts now show as chips on every profile.
For the technically curious
Migration 0033 adds a follows table — a directed edge (follower, followee) with a primary-key duplicate guard, a no-self-follow check, and cascade delete. Reads use own-row RLS (each side can read its own edges); writes go through two auth.uid()-based security-definer RPCs modeled on create_game.
-- follow_user / unfollow_user: idempotent, auth.uid()-scoped, security definer
-- 0031 grant lesson applied: default privileges grant EXECUTE to anon —
-- revoke from public, anon FIRST, then grant execute to authenticated only.Counting an arbitrary user’s followers is blocked by that own-row RLS, so migration 0034 adds get_follow_counts(p_user) — a security-definer function returning followers/following. Because counts are non-sensitive and profiles are public-read (a profile renders for anonymous visitors), it is granted to anon + authenticated — the inverse of the 0033 write RPCs.
The Friends leaderboard query is simply the viewer’s id unioned with everyone they follow, ranked by global XP. Both migrations were applied to prod via the Supabase Management API and verified (grants: authenticated yes / anon no for writes, anon yes for counts) before the web change shipped.
