# How Related Roadmaps Are Determined and Displayed Dynamically in the Developer Roadmap Repository

> Discover how related roadmaps are determined and displayed dynamically in the developer roadmap repository. Learn about the YAML front-matter and Astro component integration.

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

---

**Related roadmaps are determined by a hardcoded list of slugs in each roadmap’s YAML front‑matter and displayed dynamically at request time by an Astro component that fetches all official roadmaps and filters them by those slugs.**

The **developer‑roadmap** repository powers roadmap.sh, an open‑source learning path platform. The “Related Roadmaps” feature helps learners discover complementary skills by suggesting contextual links at the bottom of every roadmap page. This feature relies on static content definitions but resolves the actual roadmap data dynamically on every page load.

## Front‑Matter Configuration

Content authors define relationships directly in the markdown files that store each roadmap. Every roadmap file (e.g., [`src/data/roadmaps/vue/vue.md`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/data/roadmaps/vue/vue.md)) contains a `relatedRoadmaps` key in its YAML front‑matter that lists the URL slugs of other roadmaps to recommend.

```yaml
---
title: Vue.js
relatedRoadmaps:
  - javascript
  - typescript
---

```

The front‑matter structure is strictly typed. In [`src/lib/roadmap.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/roadmap.ts), the `RoadmapFrontmatter` interface declares the field as a string array:

```typescript
export interface RoadmapFrontmatter {
  // ... other fields
  relatedRoadmaps?: string[];
}

```

This type safety ensures that only valid slugs can be assigned as related roadmaps during the content authoring process.

## Data Flow and Type Safety

When a user visits a roadmap page at `/[roadmapId]`, the application loads the full document via the `officialRoadmapDetails` query. The API response conforms to the `OfficialRoadmapDocument` type defined in [`src/queries/official-roadmap.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/queries/official-roadmap.ts), which mirrors the front‑matter structure:

```typescript
export interface OfficialRoadmapDocument {
  // ... other fields
  relatedRoadmaps?: string[];
}

```

The page component located at `src/pages/[roadmapId]/index.astro` receives this data and forwards the `relatedRoadmaps` array to the presentation layer:

```astro
<RelatedRoadmaps relatedRoadmaps={roadmapData?.relatedRoadmaps || []} />

```

This separation of concerns keeps the routing layer agnostic of how the related roadmaps are resolved, while ensuring the UI component receives a clean list of slugs to process.

## Runtime Resolution and Rendering

The dynamic behavior occurs inside `src/components/RelatedRoadmaps.astro`. Rather than relying on static props passed at build time, the component resolves the full roadmap objects at request time through the following steps.

First, it fetches the complete list of official roadmaps using the `listOfficialRoadmaps()` query, which hits the `/v1-list-official-roadmaps` endpoint:

```typescript
import { listOfficialRoadmaps } from '../queries/official-roadmap';

const { relatedRoadmaps } = Astro.props;
const allRoadmaps = await listOfficialRoadmaps();

```

Next, it filters the full dataset to keep only the items whose `slug` property appears in the `relatedRoadmaps` prop:

```typescript
const relatedRoadmapsDetails = allRoadmaps.filter((roadmap) =>
  relatedRoadmaps.includes(roadmap.slug),
);

```

Finally, the component maps over the filtered results to render interactive links. Because this filtering happens on every request, changes to a roadmap’s front‑matter are reflected instantly without requiring a site rebuild:

```astro
<div class="flex flex-col gap-1 pb-8">
  {relatedRoadmapsDetails.map((relatedRoadmap) => (
    <a
      href={`/${relatedRoadmap.slug}`}
      class="flex flex-col gap-0.5 rounded-md border bg-white px-3.5 py-2 hover:bg-gray-50 sm:flex-row sm:gap-0"
    >
      <span class="inline-block min-w-[195px] font-medium">
        {relatedRoadmap.title.card}
      </span>
      <span class="text-gray-500">{relatedRoadmap.description}</span>
    </a>
  ))}
</div>

```

This architecture allows content editors to define relationships declaratively in markdown while the system resolves and displays the current metadata (titles, descriptions) dynamically from the live data source.

## Summary

- **Authoring**: Content creators assign related roadmaps by listing slugs in the `relatedRoadmaps` front‑matter array within each roadmap’s markdown file.
- **Typing**: The `RoadmapFrontmatter` interface in [`src/lib/roadmap.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/roadmap.ts) and the `OfficialRoadmapDocument` type in [`src/queries/official-roadmap.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/queries/official-roadmap.ts) enforce type safety across the data pipeline.
- **Routing**: The page component at `src/pages/[roadmapId]/index.astro` retrieves the roadmap document and passes the related slugs to the UI component.
- **Dynamic Resolution**: `RelatedRoadmaps.astro` fetches all official roadmaps via `listOfficialRoadmaps()`, filters them by the provided slugs at runtime, and renders the matching items with current titles and descriptions.

## Frequently Asked Questions

### How do I add a related roadmap to an existing learning path?

Edit the markdown file for the source roadmap (e.g., [`src/data/roadmaps/react/react.md`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/data/roadmaps/react/react.md)) and add the target roadmap’s URL slug to the `relatedRoadmaps` array in the front‑matter. The change will appear on the next page load without requiring a full site rebuild.

### Why does the component fetch all roadmaps instead of using static props?

The `RelatedRoadmaps` component calls `listOfficialRoadmaps()` at request time to ensure the displayed titles and descriptions are always current. If the related roadmap’s metadata changes (e.g., a title update), the dynamic resolution captures that change immediately, whereas static props would require a rebuild to reflect updates.

### Where is the relationship data stored in the codebase?

The relationship definitions live as YAML front‑matter inside individual roadmap markdown files under `src/data/roadmaps/*/*.md`. The TypeScript interfaces that validate this data are located in [`src/lib/roadmap.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/roadmap.ts), and the runtime filtering logic resides in `src/components/RelatedRoadmaps.astro`.

### Can related roadmaps be defined automatically based on tags or categories?

Currently, the system only supports manually curated relationships via the `relatedRoadmaps` front‑matter array. There is no automatic tagging or categorization logic in `RelatedRoadmaps.astro`; the component strictly filters by the explicit slug list provided by the content author.