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

# Connect With the Livepeer Community

> Where to find the Livepeer community - forums, Discord, Telegram, social media, and recurring community calls.

export const DynamicTableV2 = ({tableTitle = null, headerList = [], itemsList = [], monospaceColumns = [], columnWidths = {}, columnConfig = {}, showSeparators = false, margin, className = '', style = {}, ...rest}) => {
  if (!headerList.length) {
    return <div>No headers provided</div>;
  }
  const tableRef = useRef(null);
  const [measuredColumnWidths, setMeasuredColumnWidths] = useState({});
  const measureFitColumns = () => {
    const tableElement = tableRef.current;
    if (!tableElement) {
      return;
    }
    const nextWidths = headerList.reduce((accumulator, header, index) => {
      const config = columnConfig?.[header] || ({});
      if (!config.fitContent) {
        return accumulator;
      }
      const contentNodes = tableElement.querySelectorAll(`[data-docs-column-key="${index}"] [data-docs-fit-content]`);
      let maxContentWidth = 0;
      contentNodes.forEach(node => {
        const width = Math.ceil(node.getBoundingClientRect().width);
        if (width > maxContentWidth) {
          maxContentWidth = width;
        }
      });
      if (maxContentWidth > 0) {
        accumulator[header] = `${maxContentWidth + 16}px`;
      }
      return accumulator;
    }, {});
    setMeasuredColumnWidths(currentWidths => {
      const currentEntries = Object.entries(currentWidths);
      const nextEntries = Object.entries(nextWidths);
      if (currentEntries.length === nextEntries.length && nextEntries.every(([header, width]) => currentWidths[header] === width)) {
        return currentWidths;
      }
      return nextWidths;
    });
  };
  useLayoutEffect(() => {
    measureFitColumns();
  }, [headerList, itemsList, columnConfig]);
  useEffect(() => {
    const tableElement = tableRef.current;
    if (!tableElement || typeof ResizeObserver === 'undefined') {
      return undefined;
    }
    const resizeObserver = new ResizeObserver(() => {
      measureFitColumns();
    });
    resizeObserver.observe(tableElement);
    if (tableElement.parentElement) {
      resizeObserver.observe(tableElement.parentElement);
    }
    return () => {
      resizeObserver.disconnect();
    };
  }, [headerList, itemsList, columnConfig]);
  const fitHeaders = headerList.filter(header => columnConfig?.[header]?.fitContent);
  const hasMeasuredFitColumns = fitHeaders.length === 0 || fitHeaders.every(header => Boolean(measuredColumnWidths[header]));
  const getColumnStyle = (header, isMonospace = false) => {
    const config = columnConfig?.[header] || ({});
    const fitContent = Boolean(config.fitContent);
    const fluid = Boolean(config.fluid);
    const nowrap = Boolean(config.nowrap) || fitContent || isMonospace;
    const preferredWidth = columnWidths[header];
    const measuredWidth = measuredColumnWidths[header];
    return {
      ...fitContent && measuredWidth ? {
        width: measuredWidth,
        minWidth: measuredWidth,
        maxWidth: measuredWidth
      } : {},
      ...!fitContent && !fluid && preferredWidth ? {
        minWidth: preferredWidth
      } : {},
      ...nowrap ? {
        whiteSpace: 'nowrap'
      } : {
        wordWrap: 'break-word',
        overflowWrap: 'break-word'
      }
    };
  };
  const getColumnTrackStyle = header => {
    const config = columnConfig?.[header] || ({});
    const fitContent = Boolean(config.fitContent);
    const fluid = Boolean(config.fluid);
    const preferredWidth = columnWidths[header];
    const measuredWidth = measuredColumnWidths[header];
    if (fitContent && measuredWidth) {
      return {
        width: measuredWidth,
        minWidth: measuredWidth,
        maxWidth: measuredWidth
      };
    }
    if (fluid) {
      return {};
    }
    if (preferredWidth) {
      return {
        width: preferredWidth
      };
    }
    return {};
  };
  const renderCellContent = (header, content) => {
    const config = columnConfig?.[header] || ({});
    if (!config.fitContent) {
      return content;
    }
    return <div data-docs-fit-content style={{
      display: 'inline-flex',
      alignItems: 'center',
      whiteSpace: 'nowrap',
      width: 'max-content',
      maxWidth: 'none'
    }}>
        {content}
      </div>;
  };
  return <div className={className} style={style} {...rest}>
      {tableTitle && <div style={{
    fontStyle: 'italic',
    margin: 0
  }}>
          <strong>{tableTitle}</strong>
        </div>}
      <div style={{
    overflowX: 'auto',
    ...margin != null && ({
      margin
    })
  }} role="region" tabIndex={0} aria-label={tableTitle ? `Scrollable table: ${tableTitle}` : 'Scrollable table'}>
        <table ref={tableRef} data-docs-dynamic-table-v2 style={{
    width: '100%',
    tableLayout: hasMeasuredFitColumns ? 'fixed' : 'auto',
    borderCollapse: 'collapse',
    fontSize: '0.9rem',
    marginTop: 0
  }}>
          <colgroup>
            {headerList.map((header, index) => <col key={index} style={getColumnTrackStyle(header)} />)}
          </colgroup>
          <thead>
            <tr style={{
    backgroundColor: 'var(--lp-color-accent)',
    color: 'var(--lp-color-on-accent)',
    borderBottom: '1px solid var(--lp-color-border-default)'
  }}>
              {headerList.map((header, index) => <th key={index} data-docs-column-key={index} style={{
    padding: '10px 8px',
    textAlign: 'left',
    fontWeight: '600',
    color: 'var(--lp-color-on-accent)',
    verticalAlign: 'top',
    ...getColumnStyle(header)
  }}>
                  {renderCellContent(header, header)}
                </th>)}
            </tr>
          </thead>
          <tbody>
            {itemsList.filter(item => showSeparators || !item?.__separator).map((item, rowIndex) => item?.__separator ? <tr key={rowIndex} style={{
    backgroundColor: 'var(--lp-color-accent)',
    color: 'var(--lp-color-on-accent)',
    borderBottom: '1px solid var(--lp-color-accent)'
  }}>
                    <td colSpan={headerList.length} style={{
    padding: '6px 8px',
    fontWeight: '700',
    color: 'var(--lp-color-on-accent)',
    letterSpacing: '0.01em'
  }}>
                      {(item[headerList[0]] ?? item.Category) ?? 'Category'}
                    </td>
                  </tr> : <tr key={rowIndex} style={{
    borderBottom: '1px solid var(--lp-color-border-default)'
  }}>
                    {headerList.map((header, colIndex) => {
    const value = (item[header] ?? item[header.toLowerCase()]) ?? '-';
    const isMonospace = monospaceColumns.includes(colIndex);
    return <td key={colIndex} data-docs-column-key={colIndex} style={{
      padding: '8px 8px',
      fontFamily: isMonospace ? 'monospace' : 'inherit',
      verticalAlign: 'top',
      ...getColumnStyle(header, isMonospace)
    }}>
                          {renderCellContent(header, isMonospace ? <code>{value}</code> : value)}
                        </td>;
  })}
                  </tr>)}
          </tbody>
        </table>
      </div>
    </div>;
};

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

Connect with Livepeer's vibrant community across multiple channels - from in-depth discussions on the Forum, real-time coordination on Discord, multilingual support on Telegram, to updates on X/Twitter and GitHub. Whether you're a developer, Delegator, or just curious about Livepeer, there's a place for you to engage, learn, and contribute. This guide outlines the key platforms and how to get involved in each.

<CustomDivider />

## Livepeer Forum

[forum.livepeer.org](https://forum.livepeer.org) is the primary venue for long-form discussion, governance proposals, treasury activity, and ecosystem announcements. Readable without an account - post with a free email or wallet login.

<CardGroup cols={2}>
  <Card title="Governance" icon="building-columns" href="https://forum.livepeer.org/c/governance/17">
    LIPs, parameter changes, GovWorks updates, and meta-governance discussion. Central hub for proposals before they go on-chain.
  </Card>

  <Card title="Treasury & SPEs" icon="coins" href="https://forum.livepeer.org/c/treasury/18">
    SPE pre-proposals, funding requests, and treasury discussions. Post your Pre-Proposal here at least 7 days before going on-chain.
  </Card>

  <Card title="Advisory Boards" icon="users-gear" href="https://forum.livepeer.org/c/advisory-boards/20">
    Strategy outputs, Tactical Recommendations, and Workstream coordination posts from the Foundation's four advisory boards (added 2025).
  </Card>

  <Card title="Help: Getting Started" icon="circle-question" href="https://forum.livepeer.org/c/help-getting-started/5">
    Questions from new participants, troubleshooting, and onboarding support. Monitored by community contributors and GovWorks.
  </Card>
</CardGroup>

**Key recurring posts to follow:**

* [Livepeer Governance Process guide](https://forum.livepeer.org/t/livepeer-governance-process/2767) - the definitive SPE proposal walkthrough (February 2025)
* Active governance threads - monitor [/c/governance/17](https://forum.livepeer.org/c/governance/17) for open pre-proposals and parameter discussions

<CustomDivider />

## Discord

The [Livepeer Discord](https://discord.com/invite/livepeer) (\~19,500 members) is the primary real-time platform - used for governance coordination, technical support, ecosystem updates, and community calls.

**Key channels:**

<DynamicTableV2
  headerList={["Channel", "Purpose"]}
  itemsList={[
{ Channel: "#announcements", Purpose: "Official network and Foundation announcements" },
{ Channel: "#governance", Purpose: "Real-time governance discussion; tag @Orchestrator for active proposals" },
{ Channel: "#developers", Purpose: "SDK, API, and integration questions" },
{ Channel: "#ai", Purpose: "ComfyStream, AI-runner, BYOC, and real-time video AI inference" },
{ Channel: "#orchestrators", Purpose: "Node operation, GPU setup, transcoding, and monitoring" },
{ Channel: "#support", Purpose: "General troubleshooting and onboarding questions" },
{ Channel: "Language channels", Purpose: "Moderated by Live Pioneers - see below" }
]}
  monospaceColumns={[0]}
/>

**Recurring Discord calls:**

<DynamicTableV2
  headerList={["Call", "Cadence", "Who it's for"]}
  itemsList={[
{ Call: "Dev Call", Cadence: "Bi-weekly", "Who it's for": "Developers, SPE teams, core contributors" },
{ Call: "Water Cooler", Cadence: "Weekly", "Who it's for": "Open - ecosystem updates and early-stage proposal discussion" },
{ Call: "Treasury Talk", Cadence: "Bi-weekly", "Who it's for": "Proposal authors, delegators, orchestrators; governance-focused" }
]}
/>

<Note>
  Discord channel names and structure evolve. For the current moderation rules and channel list, see the [Rules & Moderation thread](https://forum.livepeer.org/t/rules-moderation-of-livepeer-discord/2640) on the Forum (last updated November 2024).
</Note>

<CustomDivider />

## Telegram - Multilingual Community

Live Pioneers moderates Telegram groups for the Livepeer Delegator community in **8+ languages**, making the protocol accessible to non-English-speaking participants globally.

Supported languages include Chinese, German, Russian, Spanish, French, Italian, Japanese, and Portuguese, with more added through their Ambassador Programme.

Visit livepioneers.app to find your language group and connect with regional community members. Live Pioneers also produces weekly ecosystem recaps, Know Your Orchestrator interviews, and educational content in each supported language.

<CustomDivider />

## X / Twitter

Follow **[@LivepeerNetwork](https://x.com/LivepeerNetwork)** for ecosystem updates, governance announcements, SPE approvals, and network news.

The Livepeer Foundation also posts updates via the Foundation account - check the Foundation site (Livepeer.foundation) for their social links.

<CustomDivider />

## GitHub

All Livepeer source code, documentation, and governance proposals are open source.

<CardGroup cols={2}>
  <Card title="livepeer/docs" icon="github" href="https://github.com/livepeer/docs">
    The documentation repository. Raise an Issue to flag inaccuracies, or submit a Pull Request with changes. Contribution workflow in `contribute/CONTRIBUTING/`.
  </Card>

  <Card title="livepeer/LIPs" icon="github" href="https://github.com/livepeer/LIPs">
    Livepeer Improvement Proposals - the formal process for protocol changes. Current framework defined by LIP-89 through LIP-92.
  </Card>

  <Card title="livepeer/go-livepeer" icon="github" href="https://github.com/livepeer/go-livepeer">
    Core Go implementation of the Livepeer Protocol node. Issues, PRs, and release notes.
  </Card>

  <Card title="livepeer/awesome-livepeer" icon="github" href="https://github.com/livepeer/awesome-livepeer">
    Community-maintained list of ecosystem tools, SDKs, tutorials, and projects. Open to community contributions.
  </Card>
</CardGroup>

<CustomDivider />

## YouTube

Past community calls, governance discussions, protocol demos, and educational content are available on the [Livepeer YouTube channel](https://www.youtube.com/@livepeer).

Live Pioneers also produces video content in multiple languages - find their channel via livepioneers.app.

<CustomDivider />
