# SEO Implementation Strategy Using JSON-LD Schemas for Articles and FAQs in Developer Roadmap

> Learn effective SEO implementation using JSON-LD schemas to enhance search visibility for articles and FAQs on the developer roadmap site. Boost your site's ranking today.

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

---

**The Developer Roadmap site boosts search visibility by dynamically generating JSON-LD structured data for every roadmap page, combining BlogPosting schemas for articles with FAQPage schemas for question-answer pairs.**

The `kamranahmedse/developer-roadmap` repository uses a server-side SEO implementation strategy that injects Schema.org markup directly into the HTML head. By leveraging TypeScript helpers to construct JSON-LD objects, the site ensures that search engines receive rich, structured metadata about each roadmap's content, publication dates, author information, and associated FAQs.

## How JSON-LD Schemas Power SEO in Developer Roadmap

Structured data enables search engines to display **rich results**—enhanced listings that include article previews, publication dates, and expandable FAQ snippets. The implementation relies on two core utilities in [`src/lib/jsonld-schema.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/jsonld-schema.ts):

- **`generateArticleSchema`** – Constructs a `BlogPosting` object containing the roadmap's headline, description, image, author, and timestamps.
- **`generateFAQSchema`** – Transforms roadmap questions into a `FAQPage` entity with `Question` and `Answer` pairs.

These helpers are consumed by `src/pages/[roadmapId]/index.astro`, which orchestrates data fetching, schema assembly, and injection into the page layout.

## Generating Article Schemas with `generateArticleSchema`

### The BlogPosting Schema Structure

The article schema follows the Schema.org `BlogPosting` specification, providing search engines with comprehensive metadata about the roadmap content. The generated object includes:

- **Context and Type**: `@context` set to `https://schema.org` and `@type` as `BlogPosting`.
- **Main Entity**: A `WebPage` reference linking to the canonical URL.
- **Content Metadata**: `headline`, `description`, and `image` properties derived from the roadmap data.
- **Attribution**: `author` (Person) and `publisher` (Organization) objects with names, URLs, and logos.
- **Temporal Data**: ISO 8601 formatted `datePublished` and `dateModified` strings generated using **luxon**.

### Implementation in [`src/lib/jsonld-schema.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/jsonld-schema.ts)

The helper function accepts an `ArticleSchemaProps` object and returns a strict Schema.org-compliant JavaScript object:

```typescript
export function generateArticleSchema(article: ArticleSchemaProps) {
  const { url, headline, description, imageUrl, datePublished, dateModified } = article;
  return {
    '@context': 'https://schema.org',
    '@type': 'BlogPosting',
    mainEntityOfPage: {
      '@type': 'WebPage',
      '@id': url,
    },
    headline,
    description,
    image: imageUrl,
    author: {
      '@type': 'Person',
      name: 'Kamran Ahmed',
      url: 'https://twitter.com/kamrify',
    },
    publisher: {
      '@type': 'Organization',
      name: 'roadmap.sh',
      logo: {
        '@type': 'ImageObject',
        url: 'https://roadmap.sh/img/brand-square.png',
      },
    },
    datePublished,
    dateModified,
  };
}

```

## Building FAQ Schemas with `generateFAQSchema`

### Mapping Questions to Schema.org Format

The FAQ schema implementation targets Google's **FAQ rich result** format. Each roadmap may contain multiple FAQ entries stored in the `questions` array. The system filters for items with `type: 'faq'` and transforms them into Schema.org `Question` entities containing nested `Answer` objects.

### Rendering Markdown to Plain Text

Since FAQ content is stored as markdown but JSON-LD requires plain text, the helper uses `renderMarkdownFromJson` to strip formatting and join content into a single string:

```typescript
export function generateFAQSchema(faqs: OfficialRoadmapQuestion[]) {
  return {
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    mainEntity: faqs.map((faq) => ({
      '@type': 'Question',
      name: faq.title,
      acceptedAnswer: {
        '@type': 'Answer',
        text: renderMarkdownFromJson(faq.description, { join: ' ' }),
      },
    })),
  };
}

```

## Integrating Schemas into Roadmap Pages

### Data Fetching in `[roadmapId]/index.astro`

The orchestration happens in `src/pages/[roadmapId]/index.astro`, which serves as the entry point for all roadmap pages. The component executes the `officialRoadmapDetails` GraphQL query to retrieve metadata including `title`, `description`, `createdAt`, `updatedAt`, and the `questions` array.

### Assembling the JSON-LD Array

The page constructs a `jsonLdSchema` array and conditionally pushes schemas based on available data:

```astro
let jsonLdSchema = [];

jsonLdSchema.push(
  generateArticleSchema({
    url: `https://roadmap.sh/${roadmapId}`,
    headline: roadmapData?.seo?.title || roadmapData?.title?.page,
    description: roadmapData?.description,
    datePublished,
    dateModified,
    imageUrl: `${baseUrl}/roadmaps/${roadmapId}.png`,
  })
);

if (faqs.length) {
  jsonLdSchema.push(generateFAQSchema(faqs));
}

```

### Injecting into BaseLayout

Finally, the assembled array is passed to `src/layouts/BaseLayout.astro` via the `jsonLd` prop. The layout serializes the array and injects it into the document head as a `<script type="application/ld+json">` tag, making the structured data immediately available to search engine crawlers.

## Summary

- **Dynamic Generation**: The Developer Roadmap site generates JSON-LD schemas server-side for every roadmap page using `generateArticleSchema` and `generateFAQSchema` in [`src/lib/jsonld-schema.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/jsonld-schema.ts).
- **Dual Schema Approach**: Each page combines a `BlogPosting` schema (describing the roadmap content) with an optional `FAQPage` schema (representing attached questions), maximizing rich result eligibility.
- **Astro Integration**: The implementation leverages Astro's server-side rendering in `src/pages/[roadmapId]/index.astro` to fetch data, assemble schemas, and inject them via `BaseLayout.astro`.
- **Content Transformation**: FAQ answers are converted from markdown to plain text using `renderMarkdownFromJson` to ensure valid Schema.org markup.

## Frequently Asked Questions

### How does the Developer Roadmap site generate JSON-LD structured data?

The site uses two TypeScript helper functions, `generateArticleSchema` and `generateFAQSchema`, located in [`src/lib/jsonld-schema.ts`](https://github.com/kamranahmedse/developer-roadmap/blob/main/src/lib/jsonld-schema.ts). These functions construct Schema.org-compliant objects that are assembled into an array and injected into the page head as a `<script type="application/ld+json">` tag via the `BaseLayout.astro` component.

### What types of Schema.org schemas are implemented for SEO?

The implementation primarily uses two schema types: **BlogPosting** for the roadmap article itself (containing headline, description, author, publisher, and timestamps) and **FAQPage** for collections of frequently asked questions. The FAQ schema contains nested **Question** and **Answer** entities that enable rich Q&A snippets in search results.

### Where does the JSON-LD injection happen in the codebase?

The injection occurs in `src/pages/[roadmapId]/index.astro`, which fetches roadmap data via GraphQL, constructs the schema array, and passes it to `src/layouts/BaseLayout.astro` through the `jsonLd` prop. The layout component then serializes the data and renders it within the HTML `<head>` section.

### How are FAQ answers processed before being added to the schema?

Since FAQ content is stored as markdown but JSON-LD requires plain text strings, the `generateFAQSchema` function processes each answer using `renderMarkdownFromJson`. This utility strips markdown formatting and joins the content into a single space-separated string, ensuring the resulting Schema.org markup is valid and crawler-friendly.