@fcannizzaro/streamdeck-react

Limitations & Trade-offs

Known limitations of the current renderer and @fcannizzaro/streamdeck-react architecture.

Styling Constraints

Rendered UI is not a browser DOM. Keep layouts simple and explicit.

  • Prefer Tailwind classes via className and the cn() utility for all static styling (layout, colors, spacing, typography).
  • Use inline style only for dynamic values computed at runtime (animation outputs, size.scale(), data-driven colors).
  • Prefer flexbox layout (flex, flex-col, items-center, gap-*) over absolute positioning.
  • Prefer fixed sizes, percentages, and straightforward flex layouts.
  • Load every font you plan to render explicitly via googleFont() or manual readFile.
  • Use .ttf or .otf fonts for maximum compatibility across backends.

Performance

  • Fast repeated updates still trigger real image renders.
  • Dial rotation can emit many events in a short burst, so high-frequency UIs should stay visually simple.

No Animated GIF/Video

Stream Deck hardware does not support animated images. Each setImage call is a static frame. Animation is achieved through rapid setImage calls using useTick for manual frame loops, or the higher-level useSpring and useTween hooks for physics-based and easing-based value animation. All approaches are limited by render throughput.

One React Root Per Visible Instance

This is a deliberate trade-off for isolation:

  • Cost: memory scales linearly with visible action count; no shared React state between roots.
  • Benefit: complete isolation, no cross-instance bugs, clean lifecycle.

Use the built-in Action Coordinator (coordinator: true), external state managers (Zustand, Jotai), or the wrapper API to share state. See Sharing State.

Font Bundle Size

Fonts are loaded into the plugin runtime. Each font weight/style is a separate file, so shipping many variants increases bundle size and startup cost.

No Dedicated Touch Surface Renderer

Touch input is available through useTouchTap(), but docs should treat the current API as input-first rather than a separate rendered touch surface API.

No Interactivity Within Render

The rendered image is static -- there are no clickable regions within a key image. All interaction comes through hardware events (key press, dial rotate, touch tap). This is a Stream Deck hardware limitation.

Supported JSX Elements

Use simple HTML/SVG primitives and the built-in components where possible:

ElementPurpose
divContainer / layout (default display: flex)
spanInline text container
pParagraph text
imgImages (requires width and height)
svgInline SVG for icons and gauges

All elements use props/styles interpreted by the renderer rather than by a browser layout engine.

On this page