DEV Community

Cover image for I built a link-in-bio tool that gamifies your audience growth (with XP, ranks, and achievements)
Folded
Folded

Posted on

I built a link-in-bio tool that gamifies your audience growth (with XP, ranks, and achievements)

Like most developers with a side project, I got tired of the same boring link-in-bio tools. You drop your Linktree in your Instagram bio, people click it, and... nothing. No data, no reward, no reason to come back.

So I built Folded — a link-in-bio that turns your audience growth into a game.

How it works

Every time someone visits your Folded profile, you earn XP.

XP unlocks ranks — 15 tiers with unique badge artwork, from Stone all the way up to Apex. The system uses log-scale thresholds so early progress feels fast and rewarding, while the top ranks remain genuinely hard to reach.

Stone      → 0 XP
Seedling   → 500 XP
Woodcrest  → 1,500 XP
Iron       → 4,000 XP
Summit     → 8,000 XP
Guardian   → 15,000 XP
Spectre    → 30,000 XP
Navigator  → 60,000 XP
Vanguard   → 120,000 XP
Inferno    → 250,000 XP
Sovereign  → 500,000 XP
Warlord    → 1,000,000 XP
Eternal    → 2,500,000 XP
Ascendant  → 5,000,000 XP
Apex       → 10,000,000 XP
Enter fullscreen mode Exit fullscreen mode

There are also 20+ achievements — badges you unlock for hitting milestones like getting your first 100 visitors, maintaining a 7-day streak, or referring 5 friends.

The tech stack

  • React 19 + Vite 8 — fast SPA
  • Firebase — Auth, Firestore, Hosting, Cloud Functions v2
  • Capacitor — wraps the web app into native Android and iOS apps
  • Google AdSense — for monetisation on free profiles

One tricky part was the mobile auth flow. signInWithPopup completely breaks inside a Capacitor WebView (the OAuth popup can't return to the app). The fix is signInWithRedirect + getRedirectResult on native, with a platform check:

import { isNative } from './lib/platform.js'

const handleGoogle = async () => {
  if (isNative()) {
    await signInWithRedirect(auth, googleProvider)
    return
  }
  const result = await signInWithPopup(auth, googleProvider)
  // ...
}
Enter fullscreen mode Exit fullscreen mode

And on mount, pick up the redirect result:

useEffect(() => {
  if (!isNative()) return
  getRedirectResult(auth).then(async result => {
    if (!result) return
    await loadOrCreateProfile(result.user)
  })
}, [])
Enter fullscreen mode Exit fullscreen mode

What's live

  • [x] XP + rank system
  • [x] 20+ achievements with pop-in animations
  • [x] Daily login streaks
  • [x] Discover leaderboard (public, global)
  • [x] QR code for your profile
  • [x] Referral system (+XP for both sides)
  • [x] Native Android + iOS via Capacitor
  • [x] Dark/light mode

Try it

folded.sg — free forever, no credit card needed.

I'd love feedback from the dev.to community, especially on:

  1. What would make you actually use this instead of Linktree?
  2. What gamification mechanics are missing?

Drop a comment below 👇


Justin · maker of Folded · folded.sg

Top comments (0)