> ## 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.

# Streamplace Changelog

> Release history for Streamplace – open-source decentralised video layer on Livepeer.

export const CustomCardTitle = ({icon, title, variant = "card", iconSize, style = {}, className = "", ...rest}) => {
  const variants = {
    card: {
      display: 'flex',
      alignItems: 'center',
      gap: "var(--lp-spacing-2)",
      marginBottom: "var(--lp-spacing-3)",
      color: 'var(--lp-color-text-primary)',
      fontSize: '1rem',
      fontWeight: 600
    },
    accordion: {
      display: 'inline-flex',
      alignItems: 'center',
      gap: "var(--lp-spacing-2)"
    },
    tab: {
      display: 'inline-flex',
      alignItems: 'center',
      gap: '0.4rem',
      fontSize: '0.875rem'
    }
  };
  const sizes = {
    card: 20,
    accordion: 18,
    tab: 14
  };
  const size = iconSize || sizes[variant] || 20;
  const baseStyle = variants[variant] || variants.card;
  return variant === 'card' ? <div className={className} style={{
    ...baseStyle,
    ...style
  }} {...rest}>
      {typeof icon === 'string' ? <Icon icon={icon} size={size} color="var(--lp-color-accent)" /> : icon}
      {title}
    </div> : <span className={className} style={{
    ...baseStyle,
    ...style
  }} {...rest}>
      {typeof icon === 'string' ? <Icon icon={icon} size={size} color="var(--lp-color-accent)" /> : icon}
      {title}
    </span>;
};

export const Subtitle = ({style = {}, text, children, variant = 'default', fontSize = '', fontWeight = '', fontStyle = '', marginTop = '', marginBottom = '', color = '', className = '', ...rest}) => {
  const renderInlineCode = (value, keyPrefix) => {
    return value.split(/(`[^`]+`)/g).map((segment, index) => {
      if (segment.startsWith('`') && segment.endsWith('`')) {
        return <code key={`${keyPrefix}-code-${index}`}>{segment.slice(1, -1)}</code>;
      }
      return segment;
    });
  };
  const renderInlineMarkup = (value, keyPrefix = 'subtitle') => {
    if (typeof value !== 'string') {
      return value;
    }
    return value.split(/(\*\*[\s\S]+?\*\*)/g).map((segment, index) => {
      if (segment.startsWith('**') && segment.endsWith('**')) {
        const inner = segment.slice(2, -2);
        return <strong key={`${keyPrefix}-strong-${index}`}>
            {renderInlineCode(inner, `${keyPrefix}-strong-${index}`)}
          </strong>;
      }
      return renderInlineCode(segment, `${keyPrefix}-${index}`);
    });
  };
  const renderContent = (value, keyPrefix) => {
    if (Array.isArray(value)) {
      return value.map((item, index) => renderContent(item, `${keyPrefix}-${index}`));
    }
    return renderInlineMarkup(value, keyPrefix);
  };
  const variants = {
    default: {
      fontSize: '1rem',
      fontStyle: 'italic',
      color: 'var(--lp-color-accent)',
      marginBottom: 0
    },
    changelog: {
      fontSize: '0.8rem',
      fontStyle: 'normal',
      fontWeight: 700,
      color: 'var(--lp-color-text-primary)',
      marginBottom: 0
    }
  };
  const base = variants[variant] || variants.default;
  return <span className={className} style={{
    ...base,
    ...fontSize ? {
      fontSize
    } : {},
    ...fontWeight ? {
      fontWeight
    } : {},
    ...fontStyle ? {
      fontStyle
    } : {},
    ...marginTop ? {
      marginTop
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...color ? {
      color
    } : {},
    ...style
  }} {...rest}>
      {renderContent(text, 'text')}
      {renderContent(children, 'children')}
    </span>;
};

export const BorderedBox = ({children, variant = "default", padding = "var(--lp-spacing-4)", borderRadius = "var(--lp-spacing-px-8)", margin = "", accentBar = "", style = {}, className = "", ...rest}) => {
  const variants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    accent: {
      border: "1px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    muted: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "transparent"
    }
  };
  const accentBarColors = {
    accent: "var(--lp-color-accent)",
    positive: "var(--green-9)"
  };
  return <div data-docs-bordered-box="" data-accent-bar={accentBarColors[accentBar] ? "" : undefined} className={className} style={{
    ...variants[variant],
    padding: padding,
    borderRadius: borderRadius,
    ...margin ? {
      margin
    } : {},
    ...accentBarColors[accentBar] ? {
      position: "relative",
      '--accent-bar-color': accentBarColors[accentBar]
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const LazyLoad = ({children, height = "200px", offset = "200px", fadeDuration = 400, className = "", style = {}, ...rest}) => {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  const [ready, setReady] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setVisible(true);
        observer.disconnect();
      }
    }, {
      rootMargin: offset
    });
    observer.observe(el);
    return () => observer.disconnect();
  }, []);
  useEffect(() => {
    if (!visible) return;
    const frameId = requestAnimationFrame(() => {
      setReady(true);
    });
    return () => cancelAnimationFrame(frameId);
  }, [visible]);
  const placeholder = <div ref={ref} className={className} style={{
    minHeight: height,
    ...style
  }} {...rest} />;
  if (!visible) return placeholder;
  return <div ref={ref} className={className} style={{
    opacity: ready ? 1 : 0,
    transition: `opacity ${fadeDuration}ms ease-in`,
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const ScrollBox = ({children, maxHeight = 300, showHint = true, ariaLabel = "Scrollable content", style = {}, className = "", ...rest}) => {
  const contentRef = useRef(null);
  const [isOverflowing, setIsOverflowing] = useState(false);
  useEffect(() => {
    const checkOverflow = () => {
      if (contentRef.current) {
        const maxHeightPx = typeof maxHeight === "number" ? maxHeight : parseInt(maxHeight, 10) || 300;
        setIsOverflowing(contentRef.current.scrollHeight > maxHeightPx);
      }
    };
    checkOverflow();
    window.addEventListener("resize", checkOverflow);
    return () => window.removeEventListener("resize", checkOverflow);
  }, [maxHeight, children]);
  return <div className={className} style={{
    position: "relative",
    ...style
  }} {...rest}>
      <div ref={contentRef} role="region" tabIndex={0} aria-label={ariaLabel} style={{
    maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
    overflowY: "auto",
    paddingRight: 4
  }} onScroll={e => {
    const el = e.target;
    const atBottom = el.scrollHeight - el.scrollTop <= el.clientHeight + 10;
    const hint = el.parentNode.querySelector("[data-scroll-hint]");
    if (hint) hint.style.opacity = atBottom ? "0" : "1";
  }}>
        {children}
      </div>
      {showHint && isOverflowing && <div data-scroll-hint style={{
    fontSize: 11,
    color: "var(--lp-color-text-muted)",
    textAlign: "center",
    marginTop: 8,
    transition: "opacity 0.2s"
  }}>
          Scroll for more ↓
        </div>}
    </div>;
};

export const DoubleIconLink = ({label = '', labelColor, href = '#', text = '', iconLeft = 'github', iconLeftColor, iconRight = 'arrow-up-right', iconRightColor = 'var(--lp-color-accent)', className = '', style = {}, ...rest}) => {
  return <span className={className} style={{
    whiteSpace: 'nowrap',
    display: 'inline-flex',
    alignItems: 'center',
    gap: "var(--lp-spacing-1)",
    marginLeft: '0.3rem',
    ...style
  }} {...rest}>
      {text && <span style={{
    marginRight: 8
  }}>{text}</span>}
      <Icon icon={iconLeft} color={iconLeftColor} />
      <a href={href} style={{
    color: {
      labelColor
    }
  }}>
        {label}
      </a>
      <div style={{
    marginRight: '0.3rem'
  }}>
        <Icon icon={iconRight} size={12} color={iconRightColor} />
      </div>
    </span>;
};

export const LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

export const InlineDivider = ({margin = "0.75rem 0", padding = "0", color = "var(--lp-color-border-default)", opacity = 0.4, height = "1px", className = "", style = {}, ...rest}) => <hr role="separator" className={className} style={{
  border: "none",
  margin,
  padding,
  height,
  backgroundColor: color,
  opacity,
  ...style
}} {...rest} />;

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>;
};

<Tip>
  This page is an automated workflow.
  <Subtitle variant="changelog" style={{fontSize: "0.95rem", marginTop: "0.25rem"}}>Subscribe to this changelog's <LinkArrow label="RSS Feed" href="/v2/solutions/streamplace/changelog/rss.xml" newline={false} /></Subtitle>
</Tip>

<CustomDivider style={{margin: "-0.5rem 0 -1.5rem 0"}} />

Track releases for Streamplace on <LinkArrow label="GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases" newline={false} /> and <LinkArrow label="GitHub" href="https://github.com/streamplace/streamplace/releases" newline={false} />.

<LazyLoad height="600px">
  <Update label="v0.10.34" tags={["Release"]} rss={{ title: "Streamplace v0.10.34", description: "v0.10.34 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.34

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.34" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.33" tags={["Release"]} rss={{ title: "Streamplace v0.10.33", description: "v0.10.33 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.33

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.33" iconLeft="gitlab" />
  </Update>
</LazyLoad>

<LazyLoad height="600px">
  <Update label="v0.10.32" tags={["Release"]} rss={{ title: "Streamplace v0.10.32", description: "v0.10.32 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.32

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.32" iconLeft="gitlab" />
  </Update>
</LazyLoad>

<LazyLoad height="600px">
  <Update label="v0.10.31" tags={["Release"]} rss={{ title: "Streamplace v0.10.31", description: "v0.10.31 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.31

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.31" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.29" tags={["Release"]} rss={{ title: "Streamplace v0.10.29", description: "v0.10.29 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.29

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.29" iconLeft="gitlab" />
  </Update>
</LazyLoad>

<LazyLoad height="600px">
  <Update label="v0.10.28" tags={["Release"]} rss={{ title: "Streamplace v0.10.28", description: "v0.10.28 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.28

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.28" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.27" tags={["Release"]} rss={{ title: "Streamplace v0.10.27", description: "v0.10.27 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.27

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.27" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.26" tags={["Release"]} rss={{ title: "Streamplace v0.10.26", description: "v0.10.26 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.26

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.26" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.25" tags={["Release"]} rss={{ title: "Streamplace v0.10.25", description: "v0.10.25 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.25

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.25" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.24" tags={["Release"]} rss={{ title: "Streamplace v0.10.24", description: "v0.10.24 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.24

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.24" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.23" tags={["Release"]} rss={{ title: "Streamplace v0.10.23", description: "v0.10.23 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.23

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.23" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.22" tags={["Release"]} rss={{ title: "Streamplace v0.10.22", description: "v0.10.22 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.22

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.22" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.20" tags={["Release"]} rss={{ title: "Streamplace v0.10.20", description: "v0.10.20 release" }} description={<Subtitle variant="changelog">May 2026</Subtitle>}>
    ## v0.10.20

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.20" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.19" tags={["Release"]} rss={{ title: "Streamplace v0.10.19", description: "v0.10.19 release" }} description={<Subtitle variant="changelog">April 2026</Subtitle>}>
    ## v0.10.19

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.19" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.18" tags={["Release"]} rss={{ title: "Streamplace v0.10.18", description: "v0.10.18 release" }} description={<Subtitle variant="changelog">April 2026</Subtitle>}>
    ## v0.10.18

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.18" iconLeft="gitlab" />
  </Update>
</LazyLoad>

<LazyLoad height="600px">
  <Update label="v0.10.12" tags={["Release"]} rss={{ title: "Streamplace v0.10.12", description: "v0.10.12 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
    ## v0.10.12

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.12" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.11" tags={["Release"]} rss={{ title: "Streamplace v0.10.11", description: "v0.10.11 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
    ## v0.10.11

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.11" iconLeft="gitlab" />
  </Update>

  <Update label="v0.10.10" tags={["Release"]} rss={{ title: "Streamplace v0.10.10", description: "v0.10.10 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
    ## v0.10.10

    <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.10" iconLeft="gitlab" />
  </Update>
</LazyLoad>

<Update label="v0.10.9" tags={["Release"]} rss={{ title: "Streamplace v0.10.9", description: "v0.10.9 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.9

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### Bug fixes

  * **Director status updates** – Resolved an issue where the director continued to update status after sending a notification.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.9" iconLeft="gitlab" />
</Update>

<Update label="v0.10.8" tags={["Release"]} rss={{ title: "Streamplace v0.10.8", description: "v0.10.8 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.8

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Playback Router** – Added a new component that intelligently routes playback requests.

  ### Updates

  * **CORS** – Playback requests now always include CORS headers.

  ### Bug fixes

  * **Playback Router** – The playback router now correctly handles cases where no worker is configured.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.8" iconLeft="gitlab" />
</Update>

<Update label="v0.10.7" tags={["Release"]} rss={{ title: "Streamplace v0.10.7", description: "v0.10.7 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.7

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Pinned chat messages** – Moderators can now pin messages in the chat.
  * **Federated view counts** – Aggregate view counts across federated servers using ATProto.

  ### Updates

  * **Mobile layout improvements** – Improved styling and layout for mobile devices, including landscape mode and safe area adjustments.
  * **Web UI overlay** – The web UI now displays over the video.

  ### Bug fixes

  * **OG image fix** – Fixed an issue with OG image generation using a webp encoder.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.7" iconLeft="gitlab" />
</Update>

<Update label="v0.10.6" tags={["Release"]} rss={{ title: "Streamplace v0.10.6", description: "v0.10.6 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.6

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### Updates

  * **Navigation** – Improved navigation performance in some cases.

  ### Bug fixes

  * **Stability** – Addressed a potential crash scenario.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.6" iconLeft="gitlab" />
</Update>

<Update label="v0.10.5" tags={["Release"]} rss={{ title: "Streamplace v0.10.5", description: "v0.10.5 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.5

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Chat popout** – You can now pop out the chat into a separate window.

  ### Updates

  * **Login prompt** – Improved login prompt for a smoother user experience.
  * **Oatproxy** – Updated to a version with improved rate limit handling.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.5" iconLeft="gitlab" />
</Update>

<Update label="v0.10.3" tags={["Release"]} rss={{ title: "Streamplace v0.10.3", description: "v0.10.3 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.3

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Fullscreen shortcut** – Added "f" key and double-click shortcuts to toggle fullscreen mode.

  ### Bug fixes

  * **Error handling** – Implemented an error boundary to prevent crashes in the facet component.
  * **Loading spinner** – Enabled click-through functionality on the loading spinner.
  * **Title input** – Fixed an issue where the title input would reset when the livestream updates.
  * **Bottom bar** – Enabled the bottom bar on non-wide web layouts.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.3" iconLeft="gitlab" />
</Update>

<Update label="v0.10.2" tags={["Release"]} rss={{ title: "Streamplace v0.10.2", description: "v0.10.2 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.2

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### Updates

  * **OAuth client** – Upgraded the underlying OAuth client for improved compatibility.
  * **Rate limiting** – Improved handling of rate limits in the oatproxy component.

  ### Bug fixes

  * **DPoP keys** – Added a migration path for users with old DPoP keys.
  * **Livestream records** – The director now fetches a fresh record for livestreams.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.2" iconLeft="gitlab" />
</Update>

<Update label="v0.10.0" tags={["Release"]} rss={{ title: "Streamplace v0.10.0", description: "v0.10.0 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.10.0

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Segment retention policy** – Implemented a default policy for retaining stored segments.
  * **Live dashboard** – Ingest fields are now customizable.

  ### Updates

  * **Image library** – Migrated from `react-native Image` to `expo-image`.

  ### Bug fixes

  * **Mobile UI** – Fixed bottom icons on Android.
  * **Mobile UI** – Improved header title display on non-iOS platforms.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.10.0" iconLeft="gitlab" />
</Update>

<Update label="v0.9.15" tags={["Release"]} rss={{ title: "Streamplace v0.9.15", description: "v0.9.15 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.9.15

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Live dashboard ingest customisation** – Ingest fields can now be customised in the live dashboard.
  * **Segment retention policy** – Implemented a default segment retention policy for storage.

  ### Bug fixes

  * **Broadcast routing** – Fixed an issue where broadcast origins were not being routed correctly.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.9.15" iconLeft="gitlab" />
</Update>

<Update label="v0.9.13" tags={["Release"]} rss={{ title: "Streamplace v0.9.13", description: "v0.9.13 release" }} description={<Subtitle variant="changelog">March 2026</Subtitle>}>
  ## v0.9.13

  <Icon icon="user-robot" size={14} /> *AI Summary*

  ### New features

  * **Webhook events** – Added support for `stream.ended` and `stream.started` webhook events.

  ### Updates

  * **User roles** – Expanded user roles to include "editor" with elevated permissions.

  ### Bug fixes

  * **Mobile layout** – Improved layout on small screens for mobile devices.

  <InlineDivider margin="1rem 0" />

  <DoubleIconLink label="View release on GitLab" href="https://git.stream.place/streamplace/streamplace/-/releases/v0.9.13" iconLeft="gitlab" />
</Update>
