Profile Page & Badge System
| Profile page | app/(dashboard)/profile/page.tsx |
| Badge definitions | lib/utils/badges.ts |
| Badge hook | lib/hooks/useAchievements.ts |
| Badge images | public/badges/*.webp |
| Route | /profile |
Profile Page
Displays the user's profile with:
- Avatar, name, email, member-since date
- Quick stats: stories count, badges earned, quizzes taken
- Credits card: plan label ("Free Plan" / "Pro Plan"), credits remaining, usage breakdown
- Pro users: expiry date ("Expires May 31, 2026") + "⭐ Pro" badge
- Free users: "Upgrade to Pro" button (opens
https://www.kidstory.app/upgradein new tab)
- Full Achievements section (all badges)
- Personalized for You section (AI learning recommendations)
Accessible from: dashboard navbar avatar click, dashboard profile card.
Badge System
12 custom badges with .webp artwork (not emojis). Each badge has:
id— unique identifierimage— path to/badges/*.webpname— display namedescription— how to earn itcolor— Tailwind gradient for glow effectcheck(stats)— function that determines if earned
All Badges
| Badge | Image | Requirement |
|---|---|---|
| First Chapter | /badges/First-Chapter.webp | Read 1 story |
| Bookworm | /badges/Bookworm.webp | Read 5 stories |
| Story Collector | /badges/Story-Collector.webp | Read 10 stories |
| Library Hero | /badges/Library-Hero.webp | Read 25 stories |
| Quiz Starter | /badges/Quiz-Starter.webp | Complete 1 quiz |
| Star Student | /badges/Star-Student.webp | Get a perfect quiz score |
| Triple Star | /badges/Triple-Star.webp | Get 3 perfect scores |
| Quiz Champion | /badges/Quiz-Champion.webp | Average score above 80% (min 3 quizzes) |
| Story Burst | /badges/Story-Burst.webp | Create 3 stories in one day |
| World Explorer | /badges/World-Explorer.webp | Read stories in 2+ languages |
| Young Author | /badges/Young-Author.webp | Download a story as PDF |
| Super Reader | /badges/Super-Reader.webp | 10+ stories AND 70%+ average score |
How badges are computed
Story/quiz activity
│
▼
useAchievements(uid, stories) hook
│
├── buildStats(stories, pdfDownloads) → UserStats
│ totalStories, totalQuizzesTaken, perfectScores,
│ avgScore, storiesInOneDay, languagesUsed, pdfDownloads
│
├── computeEarnedBadgeIds(stats) → Set<string>
│ Runs each badge's check() function against stats
│
├── Compare with Firestore saved earnedIds
│ New badge? → show BadgeToast + save to Firestore
│
└── Return: earnedIds, newBadge, dismissNewBadgeBadge unlock toast
When a new badge is earned, BadgeToast component shows a floating notification at the top of the screen for 4 seconds with the badge image, name, and description.
Persistence
Earned badges are stored in Firestore at:
users/{uid}/settings/achievements
{
earnedIds: ["first_story", "bookworm", ...],
pdfDownloads: 2,
updatedAt: "2026-04-28T..."
}

