# How Resource Progress Statistics Are Calculated and Visualized in Developer Roadmap

> Learn how Developer Roadmap calculates resource progress using topic counts and visualizes it with CSS progress bars. Understand your learning journey better.

- Repository: [Kamran Ahmed/developer-roadmap](https://github.com/kamranahmedse/developer-roadmap)
- Tags: internals
- Published: 2026-02-24

---

**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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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.

```typescript
// 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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/UserPublicProgressStats.tsx), [`ResourceProgress.tsx`](https://github.com/kamranahmedse/developer-roadmap/blob/main/ResourceProgress.tsx), and [`DashboardProgressCard.tsx`](https://github.com/kamranahmedse/developer-roadmap/blob/main/DashboardProgressCard.tsx).

```typescript
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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/UserPublicProgressStats.tsx) component demonstrates this pattern:

```tsx
// 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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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.

```typescript
// 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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/UserPublicProgressStats.tsx) and [`DashboardProgressCard.tsx`](https://github.com/kamranahmedse/developer-roadmap/blob/main/DashboardProgressCard.tsx).
- **Real-time synchronization** happens via `updateResourceProgress` in [`src/lib/resource-progress.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/UserPublicProgressStats.tsx) for public profiles, [`ResourceProgress.tsx`](https://github.com/kamranahmedse/developer-roadmap/blob/main/ResourceProgress.tsx) for activity feeds, and [`DashboardProgressCard.tsx`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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`](https://github.com/kamranahmedse/developer-roadmap/blob/main/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.