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
classNameand thecn()utility for all static styling (layout, colors, spacing, typography). - Use inline
styleonly 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 manualreadFile. - Use
.ttfor.otffonts 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:
| Element | Purpose |
|---|---|
div | Container / layout (default display: flex) |
span | Inline text container |
p | Paragraph text |
img | Images (requires width and height) |
svg | Inline SVG for icons and gauges |
All elements use props/styles interpreted by the renderer rather than by a browser layout engine.