Retour au catalogue

Developer API Playground

Playground API interactif avec selecteur de methode HTTP, editeur de body JSON, en-tetes personnalisables et reponse en temps reel avec coloration syntaxique.

developercomplex Both Responsive a11y
darkcorporatesaasuniversalsplit
Theme

How to build an interactive API playground in React

A React API playground component renders an endpoint selector, a URL bar, an optional JSON request body, and a response panel with syntax highlighting. Clicking Run triggers an 800ms simulated request, then reveals the JSON response via Framer Motion AnimatePresence.

  • Stack: React 18 + Framer Motion 11 + Lucide React + Tailwind v4 CSS tokens, ~540 lines.
  • Custom JSON tokenizer highlights string keys (accent color), string values (green), numbers (amber), booleans/null (purple) without any external syntax library.
  • Accessible: all interactive elements are native buttons; the Run button disables and shows a spinner during the pending state.
  • Fully responsive, the header row wraps on small screens; the request/response grid collapses to a single column when no body is provided.
  • Copy-to-clipboard uses navigator.clipboard.writeText with a 2-second visual confirmation state.

An API playground section lets developers test HTTP endpoints directly inside your documentation page, without opening Postman or switching context. This React component bundles endpoint selection, request body display, a simulated execution flow, and a syntax-highlighted JSON response panel into a single self-contained section.

Anatomy

The component has three visual zones. A header bar contains the endpoint selector (a dropdown animated with AnimatePresence), the URL bar showing base URL + path, and the Run button with loading state. Below it, a content area splits into two columns when the selected endpoint has a request body: left column shows the JSON body, right column the response. When there is no body, the response takes the full width. A pill badge with a Braces icon sits above the heading as a category marker.

How it works

State is managed with four booleans: isRunning, showResponse, copied, and showEndpointList. Pressing Run sets isRunning to true and showResponse to false, then a setTimeout of 800ms flips both. The response panel uses AnimatePresence in wait mode to cross-fade between three keyed states: 'loading' (centered spinner), 'response' (fades in from y+8), and 'empty' (dimmed prompt text). The JSON tokenizer is a custom character-by-character parser that matches key patterns, string values, numbers, and booleans using regex, returning an array of colored segments rendered as inline spans inside a pre element with line numbers.

How to build it in React

  1. Define your endpoint data structure

    Create an ApiEndpoint interface with method, path, label, an optional body string, and a response string. The response is pre-serialized JSON, this keeps the component purely presentational and avoids any live network call in the demo.

    interface ApiEndpoint {
      method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
      path: string;
      label: string;
      body?: string;
      response: string;
    }
  2. Build the animated endpoint dropdown

    Toggle showEndpointList with the selector button. Wrap the dropdown list in AnimatePresence and animate it with opacity and a 4px y offset. On item click, update selectedIdx, close the list, and reset showResponse so the old response does not persist.

    <AnimatePresence>
      {showEndpointList && (
        <motion.div
          initial={{ opacity: 0, y: -4 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: -4 }}
          transition={{ duration: 0.15 }}
          style={{ position: "absolute", top: "calc(100% + 4px)", zIndex: 50 }}
        >
          {endpoints.map((ep, i) => (
            <button key={i} onClick={() => {
              setSelectedIdx(i);
              setShowEndpointList(false);
              setShowResponse(false);
            }}>
              {ep.label}
            </button>
          ))}
        </motion.div>
      )}
    </AnimatePresence>
  3. Simulate the loading and response cycle

    The handleRun callback sets isRunning true and clears showResponse, then resolves after 800ms. In the response panel, use AnimatePresence with mode='wait' and three keyed children so React unmounts one state fully before mounting the next.

    const handleRun = useCallback(() => {
      setIsRunning(true);
      setShowResponse(false);
      setTimeout(() => {
        setIsRunning(false);
        setShowResponse(true);
      }, 800);
    }, []);
  4. Write the JSON syntax tokenizer

    Implement tokenizeLine as a while loop that matches patterns left-to-right: JSON key (quoted word followed by colon), string value, integer, or boolean/null. Each match pushes a segment with text and a CSS color string. Render segments as colored spans inside a pre block, with a line-number column rendered via map over the split lines.

    function tokenizeLine(line: string): TokenSegment[] {
      const segments: TokenSegment[] = [];
      let remaining = line;
      while (remaining.length > 0) {
        const keyMatch = remaining.match(/^("[w_]+")(s*:s*)/);
        if (keyMatch) {
          segments.push({ text: keyMatch[1], color: "var(--color-accent)" });
          segments.push({ text: keyMatch[2], color: "var(--color-foreground-muted)" });
          remaining = remaining.slice(keyMatch[0].length);
          continue;
        }
        // ... string, number, boolean matches
      }
      return segments;
    }

When to use it

Reach for this component on developer product landing pages, API documentation sites, or SaaS onboarding pages where showing a live-looking request cycle builds trust faster than a code block alone. It works especially well when your API returns clean JSON and you want to highlight specific endpoints. Skip it on consumer-facing marketing pages where the technical framing would confuse non-developer visitors, and avoid using it as a real HTTP client, it is a presentational demo, not a network layer.

Used by

  • Stripe, Stripe's API reference embeds interactive request/response panels for every endpoint, with colored HTTP method badges and copyable JSON responses.
  • Postman, Postman's web interface popularized the endpoint selector + URL bar + response panel layout that this component distills into an embeddable section.
  • Resend, Resend's documentation uses split-panel API explorers with HTTP method color coding and syntax-highlighted JSON response previews.
  • Supabase, Supabase exposes live API playgrounds in its docs, letting developers fire real requests against their project from the documentation page itself.

FAQ

Does this component make real HTTP requests?

No. The response data is pre-defined in the endpoint props, and the 800ms delay is a setTimeout. Swap it for a real fetch call if you want live requests, but keep the AnimatePresence loading/response state machine, it handles the async cycle cleanly.

How do I add custom HTTP headers or query parameters?

Extend the ApiEndpoint interface with optional headers and params fields, then render them as additional panel sections between the URL bar and the response area. The split-column grid already accommodates extra zones without layout changes.

Can I use a real syntax highlighting library instead of the custom tokenizer?

Yes. Replace the JsonHighlight component and tokenizeLine function with Prism.js, Shiki, or highlight.js. The surrounding layout and AnimatePresence animations remain unchanged, the tokenizer is isolated to those two functions.

How do I show a real status code and response time?

Store performance.now() before the fetch and compute the delta on resolve. Add status and latencyMs to a result state object, then display them in the response header row where the hardcoded '200 OK' and '124ms' strings currently sit.

"use client";

import { useState, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Play, Copy, Check, ChevronDown, Loader2, Braces } from "lucide-react";
import React from "react";

type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";

interface ApiEndpoint {
  method: HttpMethod;
  path: string;
  label: string;
  body?: string;
  response: string;
}

interface DeveloperApiPlaygroundProps {
  title?: string;
  subtitle?: string;
  baseUrl?: string;
  endpoints?: ApiEndpoint[];

Code complet réservé à Pro

Code source intégral, export multi-framework et playground.

Passer en Pro, 9,99€/mois

Reviews

React API Playground Component, Live HTTP Tester UI