How Role, Skill, and Best-Practice Roadmap Types Are Handled Distinctly in Developer Roadmap

The repository treats role, skill, and best-practice as separate architectural categories through distinct type definitions in src/queries/official-roadmap.ts, separate data fetching mechanisms (API endpoints versus static Markdown globbing), unique URL routing patterns, and differentiated metadata tagging during site generation.

The developer-roadmap repository organizes learning paths into three distinct roadmap types: role-based career tracks, skill-specific technologies, and best-practice guidelines. Understanding how these different roadmap types are handled distinctly requires examining the type definitions, data layer implementations, and routing architectures that separate role and skill roadmaps from best-practice content.

Type Definitions and Allowed Categories

The codebase enforces strict type safety across the three roadmap variants through a centralized type definition system.

Role and Skill Enumeration

In src/queries/official-roadmap.ts, the allowed categories are declared as a const assertion that forms the basis of the type system:

export const allowedOfficialRoadmapType = ['skill', 'role', 'best-practice'] as const;
export type AllowedOfficialRoadmapType = (typeof allowedOfficialRoadmapType)[number];

This AllowedOfficialRoadmapType union ensures that only valid roadmap types propagate through the application's data layer.

Best-Practice Data Model

Unlike role and skill types, best-practice roadmaps are managed by a dedicated module in src/lib/best-practice.ts. This module handles Markdown file discovery and content loading rather than API endpoint consumption, establishing a separate architectural path for this roadmap type.

Data Fetching Architectures

The repository implements two fundamentally different data retrieval strategies based on roadmap classification.

API-Based Retrieval for Role and Skill Roadmaps

Role and skill roadmaps are fetched via the official-roadmap API endpoint (/v1-official-roadmap/:slug). The response includes a type field that distinguishes between career roles (e.g., "frontend-developer") and specific skills (e.g., "react").

import { officialRoadmapDetails } from '$src/queries/official-roadmap';

const roleRoadmap = await officialRoadmapDetails('frontend-developer');
if (roleRoadmap?.type === 'role') {
  console.log('This is a role roadmap for a Front-End Developer');
}

For skill-specific roadmaps, the same function returns a type of 'skill':

import { officialRoadmapDetails } from '$src/queries/official-roadmap';

const skillRoadmap = await officialRoadmapDetails('react');
if (skillRoadmap?.type === 'skill') {
  console.log('Skill roadmap for React');
}

Static File Loading for Best-Practice Content

Best-practice roadmaps bypass the API entirely. The system uses Vite's import.meta.glob to dynamically load static Markdown files from the filesystem:

import { getBestPracticeById } from '$src/lib/best-practice';

const bp = await getBestPracticeById('frontend-performance/use-https-everywhere');
console.log(bp.frontmatter.title); // "Use HTTPS Everywhere"

This approach allows best-practices to be maintained as documentation-like content in src/data/best-practices/*/*.md, loaded via the getAllBestPractices and getBestPracticeById helpers.

Routing and URL Structure

The URL architecture reinforces the semantic differences between roadmap types. Role and skill roadmaps share the dynamic route pattern /[roadmapSlug], with beginner variants expressed through query parameters (?r=…). Best-practice content lives under the dedicated /best-practices/:id namespace, as defined in src/lib/best-practice.ts.

Metadata Tagging and Site Generation

During the build process, src/pages/pages.json.ts assigns distinct metadata tags based on the roadmap type. Role roadmaps receive ['role-roadmap'] tags, while skill roadmaps receive ['skill-roadmap']. Best-practice pages receive a static group: 'Best Practices' entry and never receive the role/skill classification tags.

import { listOfficialRoadmaps } from '$src/queries/official-roadmap';

const roadmaps = await listOfficialRoadmaps();
const roleMeta = roadmaps
  .filter(r => r.type === 'role')
  .map(r => ({
    url: `/${r.slug}`,
    tags: ['role-roadmap'],
  }));

Resource Type Discrimination

The getResourceMeta helper in src/lib/roadmap.ts performs top-level discrimination using the ResourceType union (defined in src/lib/resource-progress.ts as 'roadmap' | 'best-practice'). When processing roadmaps, the helper further inspects the type field to distinguish role from skill variants. Best-practice resources are identified by their /best-practices/ URL prefix:

if (resourceType === 'roadmap') {
  return page.url === `/${resourceId}`;
} else if (resourceType === 'best-practice') {
  return page.url === `/best-practices/${resourceId}`;
}

Summary

  • Type Safety: The AllowedOfficialRoadmapType union in src/queries/official-roadmap.ts enforces strict typing across role, skill, and best-practice categories.
  • Data Layer Separation: Role and skill roadmaps use the official API endpoint, while best-practices use static Markdown globbing via import.meta.glob in src/lib/best-practice.ts.
  • URL Architecture: Role and skill roadmaps share /{slug} routes; best-practices use the dedicated /best-practices/{id} path.
  • Metadata Differentiation: Site generation applies role-roadmap or skill-roadmap tags to official roadmaps, while best-practices receive static group assignments in the site map.
  • Resource Helpers: The getResourceMeta function in src/lib/roadmap.ts routes logic based on resourceType and URL patterns, with special handling for best-practice identification.

Frequently Asked Questions

What distinguishes a role roadmap from a skill roadmap in the codebase?

While both use the same API infrastructure in src/queries/official-roadmap.ts and share routing patterns, the type field in the roadmap document differentiates them. Role roadmaps represent career paths (e.g., "DevOps Engineer"), while skill roadmaps cover specific technologies (e.g., "Docker"). During site generation in src/pages/pages.json.ts, roles receive ['role-roadmap'] metadata tags, and skills receive ['skill-roadmap'] tags, enabling filtered views and categorization.

Why are best-practice roadmaps handled separately from role and skill types?

Best-practice content resides in static Markdown files within src/data/best-practices/ rather than the database-driven API used for official roadmaps. This architectural decision allows best-practices to be maintained as documentation-like content, loaded via Vite's import.meta.glob helpers in src/lib/best-practice.ts, and served under the /best-practices/ URL namespace, completely separate from the dynamic roadmap routing system.

How does the application determine which type of roadmap to render?

The getResourceMeta helper in src/lib/roadmap.ts checks the resourceType parameter against the ResourceType union ('roadmap' | 'best-practice'). For roadmaps, it matches URLs against /${resourceId}, while best-practices match against /best-practices/${resourceId}. When processing roadmaps, the system further inspects the type property (role vs. skill) to determine specific rendering metadata and page classifications.

Can the roadmap type be changed dynamically after creation?

The roadmap type is defined at the data level in the source files. For role and skill roadmaps, the type field is set in the backend API data consumed by src/queries/official-roadmap.ts. For best-practices, the type is implicit in the file location and loading mechanism in src/lib/best-practice.ts. Changing a roadmap's classification requires updating these source definitions, as the frontend relies on these distinctions for routing logic, metadata generation, and resource progress tracking.

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 →