I have loved video games my entire life.
My way of honoring a game was always the same: get 100%.
Every achievement. Every collectible. Every secret.
But after the last achievement popped one day, I felt something
I didn't expect. Emptiness. The game was over. Nowhere left to go.
I looked around. I had done something genuinely hard.
But where could I show it? Nobody cared about a Steam profile screenshot.
So I asked: what if 100% is not the end of a game, but only the beginning?
That question became Pantheon HDS.
How it works
You connect Steam. You get an automatic rank based on your achievement
completion. Then you earn higher ranks by completing community-created
challenges, verified by real judges through anonymous blind voting.
Bronze -> Silver -> Gold (achievement-based, automatic)
|
Complete community challenges
Verified by real judges
|
Platinum -> Diamond -> Master -> Grandmaster
|
Legend
Community vote only. Forever.
No money. No algorithms. Just skill.
How it's built
React 19 + TypeScript 5, Vite, TanStack Query v5.
Backend is Supabase: PostgreSQL with RLS on every table,
Edge Functions on Deno for server-side logic.
Deployed on Vercel. Auth is Steam OpenID only.
No passwords. No emails. Steam is already the source of truth
for achievement data, so it made sense to use it for identity too.
Design decisions
Anonymous blind voting.
Judges are assigned randomly. They don't see the player's name.
The player doesn't know who's judging.
No social pressure, no favoritism. Verdicts stay honest.
JWT with server-side revocation.
Tokens live in localStorage. On logout, the token is killed
via an Edge Function. Leaked token after logout is useless.
const handleLogout = () => {
const token = JSON.parse(
localStorage.getItem('pantheon_user') ?? '{}'
)?.token;
if (token) revokeToken(token); // fire and forget
localStorage.removeItem('pantheon_user');
navigate('/');
};
One file owns all rank data.
Tier strings, colors, ordering — all in constants/ranks.ts.
Nothing hardcoded elsewhere. Refactoring rank logic
never turns into grep-and-pray.
export const RANK_TIERS = [
'Legend', 'Grandmaster', 'Master',
'Diamond', 'Platinum', 'Gold',
'Silver III', 'Silver II', 'Silver I',
'Bronze III', 'Bronze II', 'Bronze I',
] as const;
export type RankTier = typeof RANK_TIERS[number];
Lazy loading gated pages.
Dashboard, Admin, JudgePanel are lazy-loaded.
Visitors who never log in don't pay for that code.
const Dashboard = lazy(() => import('./components/pages/Dashboard'));
const Admin = lazy(() => import('./components/pages/Admin'));
const JudgePanel = lazy(() => import('./components/pages/JudgePanel'));
What's live
- Steam OpenID auth
- Automatic rank assignment via Steam API
- Challenge submission and judge voting
- Anonymous blind voting
- Admin panel
- Public profiles at /u/username
- Playwright E2E + Vitest unit tests
What we will never do
- Sell ranks for money
- Use AI to verify Legend rank. Humans only, always.
- Sell the platform without a community vote
These are the three principles. They don't change.
It's open source
GitHub: https://github.com/pantheon-hds/core
Live: https://pantheonhds.com
If you've ever gotten 100% in a game and wondered "now what?" —
this was built for you.
Top comments (0)