How Resource Progress Statistics Are Calculated and Visualized in Developer Roadmap

The Developer Roadmap application calculates resource progress by dividing the sum of completed and skipped topics by the total topic count, then renders this percentage as a dynamic horizontal progress bar using inline CSS width properties.

The kamranahmedse/developer-roadmap repository powers an interactive learning platform where users track their journey through developer roadmaps and best practices. Understanding how resource progress statistics are calculated and displayed requires examining the client-side utility functions, React components, and state management logic that transform raw completion counters into visual indicators.

Calculating Progress Percentages

The system tracks three integer counters for every resource: totalCount represents all topics in the roadmap, doneCount tracks topics marked as completed, and skippedCount records intentionally bypassed topics. The final percentage derives from the proportion of "covered" topics—those either done or skipped—relative to the total.

The getPercentage Utility Function

All percentage calculations across the application flow through the getPercentage helper located in src/lib/number.ts. This function safeguards against division by zero, handles edge cases where counts exceed totals, and returns a rounded integer capped at 100.

// src/lib/number.ts
export function getPercentage(portion: number, total: number): number {
  if (portion <= 0 || total <= 0) return 0;
  if (portion >= total) return 100;
  const percentage = (portion / total) * 100;
  return Math.min(Math.round(percentage), 100);
}

Components import this utility to ensure consistent rounding behavior and mathematical safety.

Deriving the Covered Count

Before invoking getPercentage, UI components compute the covered count by summing doneCount and skippedCount. This aggregation happens locally within components such as UserPublicProgressStats.tsx, ResourceProgress.tsx, and DashboardProgressCard.tsx.

const totalMarked = doneCount + skippedCount;
const progressPercentage = getPercentage(totalMarked, totalCount);

This calculation treats both completed and skipped topics as progress toward overall coverage, providing users with a realistic view of remaining work.

Visualizing Progress in the UI

Once calculated, the percentage transforms into a visual horizontal bar using a nested container pattern. The outer div establishes a full-width track, while the inner div receives a dynamic width based on the calculated percentage.

Horizontal Progress Bar Implementation

The visualization layer uses standard React components with Tailwind CSS classes for styling and inline styles for dynamic width values. The UserPublicProgressStats.tsx component demonstrates this pattern:

// src/components/UserPublicProfile/UserPublicProgressStats.tsx
<div className="relative mt-5 h-1 w-full overflow-hidden rounded-full bg-black/5">
  <div
    className="absolute left-0 top-0 h-full bg-black/40"
    style={{ width: `${progressPercentage}%` }}
  />
</div>
<span className="text-sm text-gray-600">{progressPercentage}% completed</span>

This markup creates a rounded track with a partially filled bar representing completion status, accompanied by numeric text displaying the exact percentage.

Key Components Rendering Progress

The application reuses this visualization pattern across multiple locations:

  • UserPublicProgressStats.tsx: Displays aggregated progress statistics on public user profile pages.
  • ResourceProgress.tsx: Renders progress indicators within activity feeds and resource listings.
  • DashboardProgressCard.tsx: Shows personalized progress cards on the main dashboard for authenticated users.

Each component imports getPercentage from src/lib/number.ts and implements the same width-calculation logic to maintain visual consistency.

Data Flow and State Management

Progress counters originate from backend API endpoints such as /v1-get-user-progress, which return done, learning, skipped, and total values. These values populate client-side stores managed by React Query and Svelte stores, ensuring UI components access real-time data without prop drilling.

Real-Time Progress Updates

When users toggle a topic's status, the updateResourceProgress function in src/lib/resource-progress.ts handles the API communication and state synchronization. This utility posts updates to /v1-update-resource-progress, then refreshes both the roadmapProgress store and the React Query cache.

// src/lib/resource-progress.ts
roadmapProgress.set({
  done: response.done,
  learning: response.learning,
  skipped: response.skipped,
  personalized: response.personalized,
});

queryClient.setQueryData(
  userResourceProgressOptions(resourceType, resourceId).queryKey,
  old => ({ ...old, done: response.done, learning: response.learning, skipped: response.skipped })
);

This immediate cache invalidation triggers component re-renders, causing the progress bar width to update dynamically without page reloads.

Summary

  • Three counters (totalCount, doneCount, skippedCount) form the foundation of all progress calculations in the Developer Roadmap application.
  • Consistent calculation occurs through the getPercentage utility in src/lib/number.ts, which handles edge cases and caps values at 100%.
  • Visual representation uses horizontal bars with inline style={{ width: '${percentage}%' }} attributes across components like UserPublicProgressStats.tsx and DashboardProgressCard.tsx.
  • Real-time synchronization happens via updateResourceProgress in src/lib/resource-progress.ts, which updates React Query caches and Svelte stores immediately after API confirmation.

Frequently Asked Questions

How does Developer Roadmap calculate the completion percentage for resources?

The system sums the doneCount and skippedCount to determine "covered" topics, then divides this sum by totalCount and multiplies by 100. The getPercentage function in src/lib/number.ts performs this calculation with safeguards against division by zero and values exceeding 100 percent.

What components are responsible for rendering progress bars?

Three primary React components handle visualization: UserPublicProgressStats.tsx for public profiles, ResourceProgress.tsx for activity feeds, and DashboardProgressCard.tsx for the authenticated dashboard. All use identical CSS patterns with dynamic width inline styles.

How does the application keep progress statistics synchronized after user actions?

The updateResourceProgress function in src/lib/resource-progress.ts posts changes to the backend API, then updates the roadmapProgress Svelte store and invalidates the React Query cache. This triggers immediate UI re-renders with new percentage calculations.

Why does the progress bar include skipped topics in the calculation?

Skipped topics count toward progress because the percentage represents "covered" material rather than strictly completed work. This design acknowledges that users deliberately bypassing a topic have still made a decision about that content, distinguishing it from untouched material.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →