> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Livepeer Developer Portal

> Welcome To The Developer Portal: Explore, Build, Create

export const Starfield = ({density = 1.1, className = "", style = {}, ...rest}) => {
  const canvasRef = useRef(null);
  const readThemeColor = (tokenName, fallback) => {
    if (typeof window === "undefined") return fallback;
    const value = getComputedStyle(document.documentElement).getPropertyValue(tokenName).trim();
    return value || fallback;
  };
  const brightenHex = (hexColor, amount) => {
    const normalized = String(hexColor || "").replace("#", "");
    const expanded = normalized.length === 3 ? normalized.split("").map(char => `${char}${char}`).join("") : normalized;
    if (!(/^[0-9a-fA-F]{6}$/).test(expanded)) {
      return hexColor;
    }
    const channels = expanded.match(/.{2}/g).map(chunk => Number.parseInt(chunk, 16));
    const adjusted = channels.map(channel => Math.max(0, Math.min(255, Math.round(channel + (255 - channel) * amount))));
    return `#${adjusted.map(channel => channel.toString(16).padStart(2, "0")).join("")}`;
  };
  const isDarkMode = () => {
    if (typeof window === "undefined") return false;
    return document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
  };
  const getColorPalette = () => {
    const accent = readThemeColor("--accent", "#5DD662");
    const accentDark = readThemeColor("--accent-dark", accent);
    return isDarkMode() ? [accent, accent, accentDark, brightenHex(accent, 0.18)] : [brightenHex(accent, 0.22), brightenHex(accent, 0.22), brightenHex(accent, 0.38), brightenHex(accent, 0.52)];
  };
  const SIZE_BUCKETS = [{
    scale: 0.3,
    weight: 0.50
  }, {
    scale: 0.5,
    weight: 0.20
  }, {
    scale: 0.9,
    weight: 0.15
  }, {
    scale: 1.3,
    weight: 0.10
  }, {
    scale: 1.8,
    weight: 0.05
  }];
  const pickScale = () => {
    const r = Math.random();
    let acc = 0;
    for (const b of SIZE_BUCKETS) {
      acc += b.weight;
      if (r <= acc) return b.scale;
    }
    return 0.25;
  };
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || typeof window === "undefined" || typeof document === "undefined" || typeof Image === "undefined") {
      return;
    }
    const ctx = canvas.getContext("2d");
    if (!ctx) {
      console.warn("[Starfield] Canvas 2D context unavailable");
      return;
    }
    let rafId;
    let stars = [];
    let tintedCache = new Map();
    let cancelled = false;
    const COLORS = Array.isArray(getColorPalette()) ? getColorPalette().filter(Boolean) : [];
    if (COLORS.length === 0) {
      console.warn("[Starfield] Missing color palette");
      return;
    }
    const logo = new Image();
    logo.src = "/snippets/assets/logos/Livepeer-Logo-Symbol-Light.svg";
    const makeTinted = color => {
      if (tintedCache.has(color)) return tintedCache.get(color);
      const off = document.createElement("canvas");
      const octx = off.getContext("2d");
      if (!octx) {
        return null;
      }
      const base = 32;
      off.width = base;
      off.height = base;
      octx.clearRect(0, 0, base, base);
      octx.drawImage(logo, 0, 0, base, base);
      octx.globalCompositeOperation = "source-in";
      octx.fillStyle = color;
      octx.fillRect(0, 0, base, base);
      octx.globalCompositeOperation = "source-over";
      tintedCache.set(color, off);
      return off;
    };
    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      const rect = canvas.getBoundingClientRect();
      if (!rect.width || !rect.height) {
        return;
      }
      canvas.width = rect.width * dpr;
      canvas.height = rect.height * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const count = Math.floor(rect.width * rect.height / 16000 * density);
      stars = Array.from({
        length: count
      }).map(() => {
        const color = COLORS[Math.floor(Math.random() * COLORS.length)];
        return {
          x: Math.random() * rect.width,
          y: Math.random() * rect.height,
          scale: pickScale(),
          base: Math.random() * 0.45 + 0.25,
          speed: Math.random() * 0.015 + 0.003,
          phase: Math.random() * Math.PI * 2,
          color,
          rotation: Math.random() * Math.PI * 2,
          rotSpeed: Math.random() * 0.002 - 0.001
        };
      });
    };
    const draw = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (const s of stars) {
        s.phase += s.speed;
        s.rotation += s.rotSpeed;
        const alpha = s.base + Math.sin(s.phase) * 0.25;
        const size = 10 * s.scale;
        ctx.globalAlpha = Math.max(0, Math.min(1, alpha));
        const tinted = makeTinted(s.color);
        if (!tinted) {
          continue;
        }
        ctx.save();
        ctx.translate(s.x, s.y);
        ctx.rotate(s.rotation);
        ctx.drawImage(tinted, -size / 2, -size / 2, size, size);
        ctx.restore();
      }
      rafId = requestAnimationFrame(draw);
    };
    logo.onload = () => {
      if (cancelled) {
        return;
      }
      const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      resize();
      if (prefersReducedMotion) {
        draw();
        return;
      }
      draw();
      window.addEventListener("resize", resize);
    };
    logo.onerror = () => {
      console.warn("[Starfield] Failed to load logo asset");
    };
    return () => {
      cancelled = true;
      cancelAnimationFrame(rafId);
      window.removeEventListener("resize", resize);
      logo.onload = null;
      logo.onerror = null;
    };
  }, [density]);
  return <canvas ref={canvasRef} aria-hidden="true" className={className} style={{
    position: "absolute",
    inset: 0,
    width: "100%",
    height: "100%",
    pointerEvents: "none",
    zIndex: 0,
    ...style
  }} {...rest} />;
};

export const BlinkingIcon = ({icon = 'terminal', size = 16, color, className = '', style = {}, ...rest}) => {
  const resolvedColor = color || 'var(--lp-color-accent)';
  return <span className={className} style={{
    display: 'inline-flex',
    ...style
  }} {...rest}>
      <style>{`
        @keyframes blink {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.3; }
        }
        @media (prefers-reduced-motion: reduce) {
          * { animation: none !important; }
        }
      `}</style>
      <span style={{
    display: 'inline-flex',
    animation: 'blink 3s ease-in-out infinite'
  }}>
        <Icon icon={icon} size={size} color={resolvedColor} />
      </span>
    </span>;
};

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const P = ({children, icon, iconSize = 16, iconColor, align = "left", gap = "var(--lp-spacing-2)", className = "", style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || "var(--p-icon-color)";
  const containerStyle = {
    display: icon ? "flex" : "block",
    alignItems: "center",
    gap: icon ? gap : 0,
    justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start",
    textAlign: align
  };
  const paragraphStyle = {
    margin: 0,
    color: "var(--lp-color-text-secondary)",
    opacity: 1
  };
  return <div className={className} style={{
    ...containerStyle,
    ...style
  }} {...rest}>
      {icon && <Icon icon={icon} size={iconSize} color={resolvedIconColor} />}
      <p style={paragraphStyle}>{children}</p>
    </div>;
};

export const H5 = ({children, icon, iconSize = 18, iconColor, align = "left", gap = "var(--lp-spacing-2)", className = "", style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || "var(--lp-color-accent)";
  const containerStyle = {
    display: icon ? "flex" : "block",
    alignItems: "center",
    gap: icon ? gap : 0,
    justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start",
    textAlign: align,
    marginBottom: "var(--lp-spacing-2)"
  };
  const headingStyle = {
    margin: 0,
    fontSize: "1.125rem",
    fontWeight: "bold",
    color: "var(--lp-color-text-primary)",
    opacity: 1
  };
  return <div className={className} style={{
    ...containerStyle,
    ...style
  }} {...rest}>
      {icon && <Icon icon={icon} size={iconSize} color={resolvedIconColor} />}
      <h5 style={headingStyle}>{children}</h5>
    </div>;
};

export const H2 = ({children, icon, iconSize = 28, iconColor, align = "left", gap = "var(--lp-spacing-3)", className = "", style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || "var(--lp-color-accent)";
  const containerStyle = {
    display: icon ? "flex" : "block",
    alignItems: "center",
    gap: icon ? gap : 0,
    justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start",
    textAlign: align,
    marginBottom: "var(--lp-spacing-4)"
  };
  const headingStyle = {
    margin: 0,
    fontSize: "1.875rem",
    fontWeight: "bold",
    color: "var(--lp-color-text-primary)",
    opacity: 1
  };
  return <div className={className} style={{
    ...containerStyle,
    ...style
  }} {...rest}>
      {icon && <Icon icon={icon} size={iconSize} color={resolvedIconColor} />}
      <h2 style={headingStyle}>{children}</h2>
    </div>;
};

export const H1 = ({children, icon, iconSize = 32, iconColor, align = "left", gap = "var(--lp-spacing-3)", className = "", style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || "var(--lp-color-accent)";
  const containerStyle = {
    display: icon ? "flex" : "block",
    alignItems: "center",
    gap: icon ? gap : 0,
    justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start",
    textAlign: align
  };
  const headingStyle = {
    margin: "2rem 0 1rem 0",
    fontSize: "2.5rem",
    fontWeight: "bold",
    lineHeight: "1.2",
    color: "var(--lp-color-text-primary)",
    opacity: 1
  };
  return <div className={className} style={{
    ...containerStyle,
    ...style
  }} {...rest}>
      {icon && <Icon icon={icon} size={iconSize} color={resolvedIconColor} />}
      <h1 style={headingStyle}>{children}</h1>
    </div>;
};

export const PortalContentContainer = ({children, className = "", style = {}, ...rest}) => {
  return <div className={["frame-mode-container", className].filter(Boolean).join(" ")} style={style} {...rest}>
            <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "var(--lp-spacing-4)"
  }}>   
                {children}
            </div>
        </div>;
};

export const PortalCardsHeader = ({children, title, className = "", style = {}, ...rest}) => {
  return <div className={className} style={{
    alignContent: "center",
    justifyContent: "center",
    ...style
  }} {...rest}>
        <H2 icon="signs-post" iconSize={32}>
            {title}
        </H2>

        <div style={{
    display: "flex",
    alignItems: "center",
    gap: "var(--lp-spacing-2)",
    marginBottom: "0.1rem"
  }}>
                <span style={{
    lineHeight: "1",
    color: "var(--text-primary)",
    opacity: 1,
    fontStyle: "italic",
    fontSize: "1.2rem"
  }}>
                    Choose Your Mission:
                </span>
                {children}
        </div>
    </div>;
};

export const HeroSectionContainer = ({children, minHeight = "fit-content", className = "", style = {}, ...rest}) => {
  return <div className={["frame-mode-hero-full", className].filter(Boolean).join(" ")} style={{
    minHeight: minHeight,
    marginBottom: "var(--lp-spacing-2)",
    ...style
  }} {...rest}>
      {children}
      {}
      {}
    </div>;
};

export const HeroContentContainer = ({children, className = "", style = {}, ...rest}) => {
  return <div className={["frame-mode-container", className].filter(Boolean).join(" ")} style={{
    position: "relative",
    zIndex: 1,
    height: "100%",
    marginBottom: 0,
    ...style
  }} {...rest}>
      <div style={{
    position: "relative",
    height: "100%"
  }}>{children}</div>
    </div>;
};

export const LogoHeroContainer = ({src = "/snippets/assets/logos/Livepeer-Logo-Full-Theme.svg", alt = "Livepeer Logo", width = "100%", margin = "1rem auto 0 auto", imgHeight = "20px", imgWidth = "auto", objectFit = "contain", children, className = "", style = {}, ...rest}) => {
  return <div className={className} style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    margin: margin,
    width: width,
    paddingBottom: children ? "3.5rem" : "0",
    ...style
  }} {...rest}>
      <div style={{
    position: "relative",
    display: "inline-block"
  }}>
        <img src={src} alt={alt} style={{
    height: imgHeight,
    width: imgWidth,
    objectFit: objectFit,
    display: "block"
  }} />
        {children && <div style={{
    position: "absolute",
    top: "100%",
    right: "0",
    fontSize: "2rem",
    color: "var(--lp-color-accent)",
    fontWeight: "500",
    lineHeight: "1",
    paddingTop: "var(--lp-spacing-2)"
  }}>
            {children}
          </div>}
      </div>
    </div>;
};

export const HeroImageBackgroundComponent = ({children, className = "", style = {}, ...rest}) => {
  return <div className={className} style={{
    position: "absolute",
    inset: 0,
    overflow: "hidden",
    zIndex: 0,
    ...style
  }} {...rest}>
      {children}
      {}
    </div>;
};

export const PortalHeroContent = ({zIndex = true, title = "Portal Page", subtitle = "Build - Explore - Create", subtitleIcon = "/snippets/assets/logos/Livepeer-Logo-Symbol-Green-Theme.svg", description, refCardLink, overview, divider = true, callout = null, titleColor, subtitleColor, children, className = "", style = {}, ...rest}) => {
  return <div className={className} style={{
    position: "relative",
    zIndex: 1,
    ...style
  }} {...rest}>
      <div style={{
    textAlign: "center",
    marginTop: "var(--lp-spacing-8)",
    marginBottom: "var(--lp-spacing-4)"
  }}>
        <H1 align="center">
          {title}
        </H1>
        {subtitle && <div style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "var(--lp-spacing-2)"
  }}>
            {subtitleIcon && <span style={{
    marginRight: "var(--lp-spacing-2)"
  }}>
                <Icon icon={subtitleIcon} size={20} />
              </span>}
            <h2 style={{
    fontSize: "1.5rem",
    fontWeight: "500",
    opacity: 1,
    color: subtitleColor || "var(--lp-color-accent)"
  }}>
              {subtitle} {}
              {subtitleIcon && <span style={{
    display: "inline-block",
    transform: "scaleX(-1)",
    marginLeft: "var(--lp-spacing-2)"
  }}>
                  <Icon icon={subtitleIcon} size={20} />
                </span>}
            </h2>
          </div>}
        {description && <div style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    flexDirection: "column",
    gap: "1rem 0",
    width: "80%",
    margin: "0 auto",
    fontSize: "1.1rem",
    color: "var(--lp-color-text-secondary)",
    paddingTop: "3rem"
  }}>
            {description}
          </div>}
        {refCardLink && <div style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    width: "fit-content",
    margin: "0 auto",
    marginTop: "var(--lp-spacing-4)"
  }}>
            {refCardLink}
          </div>}
         <div style={{
    width: "80%",
    margin: "0 auto",
    paddingBottom: "var(--lp-spacing-4)"
  }}>
          {callout && callout}
          {divider ? <CustomDivider /> : null}
          {}
        </div>
        {overview && <div style={{
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    flexDirection: "column",
    gap: "1rem 0",
    width: "80%",
    margin: "0 auto",
    fontSize: "1.1rem",
    color: "var(--lp-color-text-secondary)"
  }}>
            {overview}
          </div>}
        <div style={{
    width: "80%",
    margin: "0 auto",
    paddingTop: "var(--lp-spacing-6)",
    paddingBottom: "0.1rem"
  }}>
          {children ? <>{children}<CustomDivider /></> : <CustomDivider />}
        </div>
        </div>
      {}
    </div>;
};

<HeroSectionContainer>
  {/* HeroImageBackgroundComponent: Full-width Starfield Background - fills entire content area */}

  <HeroImageBackgroundComponent>
    <Starfield />
  </HeroImageBackgroundComponent>

  <HeroContentContainer>
    <LogoHeroContainer height="20px" />

    <PortalHeroContent
      title="Build on Livepeer"
      subtitle="Build - Create - Innovate"
      refCardLink={
      <Card
        title="awesome-livepeer"
        href="https://github.com/livepeer/awesome-livepeer"
        icon="github"
        arrow
        horizontal
      />
    }
      overview={
    <>
    Make custom AI pipelines with specialised Livepeer pipelines like BYOC and ComfyStream. Find guides for livestreaming and integrate with Livepeer's video AI infrastructure.
    <br/>
    <br/>
    Run Agents, AI Video, Live-Stream and embed real-time interactive AI video experiences in your social platforms, apps and more.
    </>
  }
    >
      {/* <YouTubeVideo embedUrl="https://www.youtube.com/embed/t9jhLn2fZcc?si=AM29wXYZwFJWw3UN" title="Discover Daydream" /> */}
    </PortalHeroContent>
  </HeroContentContainer>
</HeroSectionContainer>

<PortalContentContainer>
  <PortalCardsHeader title="Developer Portal">
    <BlinkingIcon icon="circle-play" size={20} />
  </PortalCardsHeader>

  <Columns cols={2}>
    <Card title="Get Started with Video" icon="video-camera" href="/v2/developers/build/video/transcoding-direct-quickstart" arrow>
      Build livestreaming, playback, and video upload workflows on Livepeer.
    </Card>

    <Card title="Get Started with AI" icon="user-robot" href="/v2/developers/build/ai-and-agents/ai-jobs-direct-quickstart" arrow>
      Call Livepeer AI endpoints first, then move into SDK, BYOC, and ComfyStream workflows.
    </Card>

    <Card title="Discover Developer Platforms" icon="laptop-code" href="/v2/solutions/portal" arrow>
      Discover Developer Platforms that make it Integrate Real-time Video AI into your ideas.
    </Card>

    <Card title="Build on Livepeer" icon="rocket" href="/v2/developers/navigator" arrow tag="Developer Level Up">
      Build your own applications on Livepeer by choosing the right AI, video, or contributor path.
    </Card>

    <Card title="Contribute to the Ecosystem" icon="hands-holding-circle" href="/v2/developers/resources/grants-and-programmes" arrow>
      Contribute to the Livepeer Ecosystem and find opportunities to earn rewards through grants, RFPs, and more.
    </Card>

    <Card title="Developer Guides & Resources" icon="laptop-file" href="/v2/developers/guides/overview" arrow>
      Browse implementation guides, tutorials, reference pages, and knowledge-hub resources.
    </Card>
  </Columns>

  <br />
</PortalContentContainer>
