Release notes
2.19.0
⚠️ Upgrade Notes
- Upgrade FlexGrid 3 to 3.4.0 with this release.
@roku-sdk/flex-grid3.1.0–3.3.0 import the removed@roku-sdk/navigation/internalentry point (see Breaking Changes). Move@roku-sdk/flex-gridto 3.4.0 in the same change as the other@roku-sdk/*packages. FlexGrid 2.x is unaffected. - zod 4.
@roku-sdk/aiand@roku-sdk/toolingnow depend on zod^4.6.6.zSkillEntryandzSkillManifestfrom@roku-sdk/aiare zod 4 schemas; code that composes them with zod 3 must move to zod 4. solid-js1.9.17 or later.@roku-sdk/solidnow requiressolid-js^1.9.17. If your app declares its ownsolid-js, raise it to match.- Fractional bounds in
@roku-sdk/device-test-client.parseBoundsandAppUiNode.boundsreturn decimal values instead of a zero rect. Bounds checks on 720p devices (for example899.99994for900) may need a tolerance. - FlexGrid guide anchors changed. Section headings are no longer numbered, so links such as
#6-nested-gridsbecome#nested-grids.
💥 Breaking Changes
@roku-sdk/navigation/internalis removed. Use@roku-sdk/navigation/focus-relay, which exportsuseFocusRelayTarget,createFocusRelay,FocusRelayProviderand theFocusRelayandFocusRelayTargettypes. ReplaceFocusBoundaryContext.ProviderwithFocusRelayProvider. Seersg-sdk/external/packages/navigation/BREAKING_CHANGES.md.@roku-sdk/device-test-client/internal/*moves to./support/*. Change/internal/deploy,/internal/constantsand/internal/pathsto/support/....ARTIFACT_FILEis now exported from the package root.- CLI-only config types move to
@roku-sdk/tooling.BuildConfig,StartDevConfig,BuildConfigType,CliOptionVariantandtemplateFuncare no longer exported from@roku-sdk/sdk-config. Type pipeline hooks againstCommonBuildConfig. Apps that only useRokuConfigneed no change.
🗑️ Deprecations
These are removed in the next minor release.
@roku-sdk/navigation:focusIdLabel,createKeyPressCaptureRegistry,createBoundaryState,BoundaryStateOptions,RegisteredHandlersandKeyPressCaptureRegistry. UseFocusBoundary,useFocusableanduseFocusActions.@roku-sdk/sdk-config:InternalRokuManifestEntries. UseRokuManifestEntries.
✨ New Features
@roku-sdk/text-layout(new package): line breaking, word wrapping and ellipsis for labels, given a width function. ExportslayoutLabel,layoutLabelInFont,wrapText,ellipsizeTextandscalesFor.- Font readiness.
whenFontReady(font, { signal })resolves when a<font>can be measured;createFontReady(fontAccessor, key?)is the reactive form. Both are in@roku-sdk/runtime/fontand@roku-sdk/rsg-ts/runtime, and replace timer-based waits before measuring text. rk dev --watchreloads config. Savingroku-config.tsorroku-dev-config.tsrebuilds and reinstalls with the new settings, without a restart. Changes tooutDirstill need a restart.rk dev --watchrebuild key. Pressrfor a full rebuild (clean, build and install). This also works whenrk devruns throughrk server.- Faster repeat builds.
rk buildandrk devtype-check incrementally and skip unchanged XML type generation, about 20–25% faster on repeat release builds. - Video track callbacks. Typed
onAvailableAudioTracks,onCurrentAudioTrack,onAvailableSubtitleTracksandonCurrentSubtitleTrackprops, withIVideoAudioTrackandIVideoSubtitleTrackpayload types. hasReturnFootprint.useFocusable()anduseFocusActions()report the item focus will return to when its boundary becomes active again.- Effect gradient warnings. Development builds warn when Effect gradient colors or stops are invalid, instead of silently not rendering.
RkClient.holdKey(key, holdMs)in@roku-sdk/device-test-clientholds a key for a set time.
🐛 Bug Fixes
this,argumentsandsupernow work inside loop bodies whose loop variable is captured by a closure.rkreports installer error pages returned with HTTP 200 as a failed deploy, instead of claiming success and relaunching the previous build.- FlexGrid 3: tapping the opposite direction during the settle after a released hold now takes effect instead of being overridden.
@roku-sdk/device-test-client: more reliable app readiness detection, retries for sideloads that fail to start, and recovery from a stalled log stream.- Dependency updates (
solid-js, zod,express,body-parser) clear the outstandingpnpm auditadvisories.
📚 Examples
focus-boundaryadds a Focus Footprint demo forhasReturnFootprint.runtime-showcaseand the Cowboy TV FlexGrid example use the new font-readiness APIs.
📚 Documentation
- Docs revised against the Roku documentation style guide, with many guides restructured.
- Getting started now walks through the
two-cowboysexample, and the overview covers migrating a BrightScript app to TypeScript incrementally. rkreference pages show option defaults, allowed values and examples.
Note: the SDK's XML FocusBoundaryBase is renamed FocusBoundaryBaseShim. On firmware with a native FocusBoundaryBase, the native component is used; otherwise the shim is swapped in at runtime.
2.18.0
⚠️ Upgrade Notes
RemoteKeyName now autocompletes known keys. The type was RemoteKey | string, which collapsed to string and gave no autocomplete or typo checking. It is now KnownRemoteKeyName | RemoteKeyNameCompat, where KnownRemoteKeyName is RemoteKey | \${RemoteKey}`. The deprecated RemoteKeyNameCompat (string & ) keeps arbitrary strings compiling for now, so existing code is unaffected. A future major release will remove the compatibility alias and make RemoteKeyNamethe closed union, so start usingRemoteKeymembers or known key literals.@roku-sdk/interfacesalso exports a newRemoteKeyEvent ({key: RemoteKeyName; press: boolean}), which the packages and examples now use in place of ad hoc {key: string; press: boolean}` types.
Focus-path context types were renamed. In @roku-sdk/navigation, FocusPathCtx is now FocusPathContext and FocusPathContextValue is now IFocusPathContext, matching the ScreenControllerContext / IScreenControllerContext pattern. The old names remain exported as deprecated aliases and will be removed in 3.0. On @roku-sdk/navigation/internal, FocusBoundaryCtx is a deprecated alias for FocusBoundaryContext; the former FocusBoundaryContext interface has no alias because that name is now the context value, and the type is IFocusBoundaryContext. Apps do not normally read or provide this context. See rsg-sdk/external/packages/navigation/BREAKING_CHANGES.md.
@roku-sdk/flex-grid-3 deprecates implementation-only exports. The store helpers, engine and navigation controller factories, plugin-resolution helpers, Bob geometry helpers and the legacy root FocusHighlightConfig remain available throughout 3.x but are scheduled for removal in the next major release. The geometry helpers (buildUniformCumX, buildCumY, computeScrollYForRow and related) move to @roku-sdk/flex-grid/geometry; import them from there. _resetGlobalHooksForTest from @roku-sdk/flex-grid/perf is deprecated as a test-only export. Use createFlexGrid, FlexGridHandle, the public focus strategies and the plugin factories instead. The pool-size helpers (computeUniformPoolSize, computeVariablePoolSize, computeDataRow, PoolSizeResult) are no longer exported. See rsg-sdk/external/packages/flex-grid-3/BREAKING_CHANGES.md.
rk validates build and dev options more strictly. Conflicting or unknown options to rk build and rk dev are now rejected before the server fast path is used, with consistent exit codes and wording across presets. The rk server build and dev routes reject a raw --config or --build-type that repeats a structured field, has no value, or conflicts with it, returning 400 VALIDATION_ERROR. Scripts that relied on the old, silently accepted combinations will see errors.
rk refuses to clean unsafe output directories. cleanOutDir now rejects an output directory that is a symlink or has a symlinked parent, and requires a root directory for cleanup. Symlinks to empty directories inside the output are handled correctly. If your outDir is reached through a symlink, point it at the real path.
The @roku-sdk/runtime ./art-mode export is removed. Its source never shipped in the package, so the entry resolved to a missing file.
💥 Breaking Changes
<tween> follows the native Tween contract. toY and delay are removed from the <tween> intrinsic (ITweenProps, ITweenCoreProps) and from the @roku-sdk/flex-grid Tween wrapper (TweenProps). Pass targetVector={[x, y]} instead of targetValue plus toY. delay has no replacement; write the target from a timer if you need the wait. onAnimationState on the intrinsic now receives one [state, value] tuple, where value is a number or Vector2D; the FlexGrid Tween wrapper keeps its (state, value) callback.
axis="both" is removed; use axis="all". Vector settlement now chooses one whole [x, y] candidate from proposedStops and applies it to every component the axis owns, so a diagonal glide lands on both coordinates instead of leaving the minor axis where it was. For a vector field under "all", proposedStops is [number, number][]; float fields and "x"/"y" keep number[]. Entries of the wrong shape are skipped and logged. In FlexGrid, GridPluginInternals.focus.settleStop() now returns [number, number][] (including the focused row's Y offset) so it can be passed straight to proposedStops.
Migration details are in @roku-sdk/components and @roku-sdk/flex-grid BREAKING_CHANGES.md and the new Tween value-shape contract page under core concepts.
✨ New Features
Tween moves to @roku-sdk/components, with native node support
Tween moves to @roku-sdk/components, with native node supportTween now lives in @roku-sdk/components; @roku-sdk/flex-grid re-exports it, so existing FlexGrid imports keep working. On firmware that reports the tween feature (hasFeature("tween")), <tween> renders the native Tween node. Elsewhere, the new @roku-sdk/compat package, injected by the build, supplies a BrightScript stand-in with the same field contract. With app.compat: false, creating <tween> on firmware without the feature throws an error naming it. No current firmware reports the feature yet, so devices use the stand-in for now.
@roku-sdk/runtime — hasFeature and Heap Graph Capture
@roku-sdk/runtime — hasFeature and Heap Graph CapturehasFeature(key) reports whether the firmware supports a feature, caching each answer for the app's lifetime. It returns false for unknown keys and where roku.hasFeature is unavailable, including older firmware and non-device environments. Feature strings are defined in firmware.
perfetto.captureHeapGraph?.() captures a heap graph snapshot into the active Perfetto trace session. It is optional for backward compatibility, does nothing when no trace session is active, requires Roku OS 16.1 and is not supported on Liberty devices.
rk — Hermes Bytecode Sideload Warning
rk — Hermes Bytecode Sideload Warningrk sideload, rk dev, the sideload_app MCP tool and the sideload build plugin now warn when the manifest's ts_path points at Hermes bytecode (.hbc), which devices do not run as a debuggable bundle. The warning is reported as a warning, not an error.
Other Additions
rk cdpbreakpoints and source retrieval accept absolute, project-relative or working-directory-relative paths. An unmapped line is now distinguished from a file outside the bundle ("no compiled code at or after this line").rk server stopfinds the running server through.roku/rk-server.jsoninstead of assuming the derived port, and reports a stale port file rather than dialling a port that now belongs to another process.rk server start,stopandstatusreject unknown options.rk mcp --helpprints help instead of starting the stdio server.RK_DEVICE_IPalone is enough for@roku-sdk/device-test-client: the device is looked up in the stored devices by that IP and its stored password is used.RK_DEVICE_PASSWORDwithout an IP is still an error.rk dev --hostnow honoursROKU_DEV_PASSWORD, and target-device password resolution is validated consistently.@roku-sdk/dev-toolsJest setup logs high memory use only whenJEST_LOG_MEMORYis set, and no longer prints per-file peak memory lines.
🐛 Bug Fixes
- FlexGrid 3 row posters no longer overlap the row title or the Bob-in-the-middle area, and
setRowHeighttreats a missing row height ascellSize[1]. rkMCP no longer starts a stdio session when only help was requested.@roku-sdk/toolingpackage.jsonmain/typesnow point at files that ship, so legacy (node10-style) resolution finds the types.- Slideshow's internal animation component is renamed
SlideshowTween, so it no longer collides with the nativeTweennode name.
📚 Examples
All examples now invoke rk directly in their package.json scripts instead of npx rk, removing "Unknown env config" warnings under pnpm. The FlexGrid, FocusBoundary, showcase, pitfalls and slideshow examples use RemoteKeyEvent.
pooled-item-row drops its private tween component and uses the shared Tween. Fantasy TV's scale tweens use targetVector.
📚 Documentation
The rk reference is now generated from command specs and route registries covering build, dev, server, mcp, cdp, dap, debug, logs, perfetto, device, create, setup, decode-stack, package, gen-types and version, including HTTP route pages (with SSE streams and error envelopes) and an environment-variable page. Hand-written option tables now link to it. Getting-started, overview, tutorial and example pages were consolidated into the standing documentation (guides, core concepts, advanced) and the directory-layout page was rewritten for registry installs. Packages that had empty npm pages (@roku-sdk/common, @roku-sdk/dev-tools, @roku-sdk/flex-grid, @roku-sdk/interfaces, @roku-sdk/native, @roku-sdk/sdk-config, @roku-sdk/solid, @roku-sdk/testing-library, @roku-sdk/tooling, @roku-sdk/ts-core) gained READMEs.
A new Tween value-shape contract page under core concepts documents target and proposedStops shapes per field type and axis.
Updated about 6 hours ago