Every Buildml user has a profile page that consolidates their progress across all problem sets. It shows how many problems they have solved at each difficulty tier, a GitHub-style activity heatmap for the trailing year, and three headline stat cards (Total Solved, Streak, and Achievements). Profiles are shareable — you can view any other user’s profile by passing their ID in the URL.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Praashh/buildml/llms.txt
Use this file to discover all available pages before exploring further.
Profile URLs
| URL | Behaviour |
|---|---|
/profile | Shows the currently signed-in user’s own profile. Redirects to / if no session exists. |
/profile?userId={id} | Shows the profile of the user with the given ID. Useful for sharing progress with teammates. |
ProfilePage server component reads searchParams.userId at request time. If a userId param is present it is used as the targetUserId; otherwise it falls back to session?.user?.id. If neither is available the visitor is redirected to the home page.
The
/profile route is covered by Next.js middleware authentication. Users who are not signed in cannot access their own profile — they are redirected to sign in first.user.getProfile Return Shape
Profile data is loaded via the user.getProfile tRPC procedure (public procedure, accepts { userId?: string }). The response contains the following fields:
Basic identity information for the profile owner.
The user’s unique CUID from the database.
The user’s display name sourced from their Google account.
URL to the user’s Google profile picture. Displayed as a rounded avatar at the top of the profile.
Number of unique problems solved (status
PASS) per difficulty tier. A problem solved multiple times is counted only once.Count of unique Easy problems passed.
Count of unique Medium problems passed.
Count of unique Hard problems passed.
Total number of problems available in the database per difficulty tier, used to render the progress bar denominators.
Total Easy problems in the system.
Total Medium problems in the system.
Total Hard problems in the system.
Total unique problems solved across all difficulties. Derived from
solvedProblemIds.size — a Set built while iterating accepted submissions.A date-keyed map of submission activity used to render the heatmap. Keys are
YYYY-MM-DD strings; values are the count of PASS submissions on that date.Example:Stat Cards
The profile renders three stat cards in a responsive grid:| Stat | Source |
|---|---|
| Total Solved | solvedCount from getProfile — unique problems with a PASS submission |
| Streak | Hardcoded placeholder (12 days) — not yet driven by live data |
| Achievements | Hardcoded placeholder (7 badges) — not yet driven by live data |
Math.floor(solvedCount / 10) + 1, so a user who has solved 0–9 problems is Level 1, 10–19 is Level 2, and so on.
Difficulty Progress Bars
The profile renders a Difficulty Breakdown panel showing a labelled progress bar for each tier. The fill percentage is calculated as:{count} / {total} in the header and animates on load via a CSS transition-all duration-1000.
Activity Heatmap
TheHeatmap component (src/app/profile/_components/Heatmap.tsx) renders a GitHub-style contribution grid for the trailing 52–53 weeks. It takes the history map from getProfile as its only prop:
Colour scale
| Submissions on a given day | Cell colour |
|---|---|
0 | bg-[var(--line)] (empty/grey) |
1 | bg-primary/30 (faint) |
2–4 | bg-primary/60 (medium) |
5+ | bg-primary (full accent) |
title attribute showing "N submissions on <date>" on hover. The grid is scrollable horizontally on narrow viewports and is labelled with abbreviated month names (Jan–Dec) along the bottom.
Server-Side Prefetching
Like the leaderboard, the profile page prefetches data on the server before streaming HTML to the client:ProfileClient component then uses useSuspenseQuery to hydrate from the server cache instantly, with no loading state visible on first render.
Sharing Profiles
Each profile page includes a Share Profile button. On devices that support the Web Share API, it invokesnavigator.share with a pre-composed message. On desktop or unsupported browsers it copies the shareable URL (/profile?userId={id}) to the clipboard and shows a toast confirmation.