Skip to main content
The player and widget components let you embed short-form video outside the full-screen feed. Use the player for a single video (hero sections, product pages, inline previews) and the widget for a horizontal carousel or vertical grid of video cards (home screens, dashboards, discovery surfaces). Both components require content fetched via fetchContent().
Flutter: Single player and widget components are coming soon for the Flutter SDK. For now, use the full-screen feed via ShortKitFeed.

Fetching content

Before displaying videos, fetch ContentItem objects from the ShortKit API:
fetchContent(limit:filter:) returns an array of resolved ContentItem objects with streaming URLs, metadata, and captions. limit defaults to 10. Pass a FeedFilter to restrict results by tags, section, author, content type, or custom metadata. For full model definitions see the Content Types guide.

Single player

PlayerConfig

Embedding a player

ViewController.swift

Activate and deactivate

The player does not manage its own visibility lifecycle. Call activate() when the player is on screen and deactivate() when it leaves. This gives you full control over playback in scroll views, tab bars, and navigation stacks. On React Native, use the active prop instead of method calls. It defaults to the value of config.autoplay (which is true by default). Set it to false to pause and true to resume.

Widget

The widget displays a horizontal carousel or vertical grid of video cards with muted autoplay. Tapping a card opens the feed by default.

WidgetConfig

Layout

WidgetConfig.layout controls whether the widget renders as a horizontal carousel or a vertical grid. Grid parameters: Two helper methods on WidgetConfig make it easier to size the container when using a non-scrollable embedded grid:
gridCellHeight returns nil for carousel layouts. preferredGridHeight returns nil for carousel layouts and for scrollable grid layouts (where total height is unbounded).

Playback mode

WidgetConfig.playbackMode controls how the widget activates preview playback across its cells. The startSide parameter on gridAlternating controls which column plays in the first row:
GridSide values: .left (default), .right.

WidgetInput

WidgetInput describes a video by its playback ID. Pass an array of these to configure(with:) or appendItems(_:).
Because ContentItem.playbackId is optional, use compactMap when converting from fetchContent() results:

Embedding a widget

ViewController.swift

Widget properties and callbacks

These properties are set on the widget component after initialization.
Set these directly on your ShortKitWidgetViewController instance:setFeedItems(_ inputs: [FeedInput]) supplies an optional seed list of items for the full-screen feed that opens when a card is tapped. The widget’s own cards are always prepended so the tapped clip is the opening item; the seed items follow. FeedInput accepts the same inputs as the full-screen feed — see Embedding a Feed for details.

Embedding a grid

Use WidgetLayout.grid to replace the carousel with a vertical grid. The example below embeds a scrollable standalone grid that fills its assigned frame:
ViewController.swift

Embedded (non-scrollable) grid

When the grid sits inside a host-managed scroll view alongside other content — for example, a home screen with a carousel above and a grid below — set scrollable: false. The grid expands to fit all of its content and lets the parent scroll view handle scrolling. Three additional steps are required:
  1. Resize the container as items load. Subscribe to onContentHeightChange and update your height constraint whenever the grid’s content height changes.
  2. Forward scroll events. Call parentScrollViewDidScroll(_:) from the parent scroll view delegate so the widget can correctly score which grid cells are visible.
  3. Append items for pagination. Call appendItems(_:) to load additional items without a full reload.
ViewController.swift
To size the grid container before items load, use preferredGridHeight(forContainerWidth:itemCount:):

Appending items

Call appendItems(_:) to add more items to the grid without a full reload — for example, when the user scrolls near the bottom:
appendItems is a no-op on an empty input array. It works on both scrollable and non-scrollable grid layouts, inserting items incrementally without a full reload. On carousel layouts it triggers a full reload instead.

Auto-rotation

Auto-rotation applies to carousel layout only (WidgetLayout.carousel). Grid layouts use the playbackMode setting to control preview activation instead.
When autoplay is true (the default), the carousel widget automatically advances through cards. How advancement is triggered differs by platform:
  • iOS — advancement is driven by the preview reaching its end (singleVisibleRotating mode). Each card plays until its preview clip finishes, then the carousel moves to the next card. rotationInterval has no effect on iOS.
  • Android and React Native — advancement is timer-based: the carousel advances to the next card after rotationInterval elapses, regardless of playback position.
On all platforms, when the carousel reaches the last card it wraps back to the first. Rotation pauses while the user is actively swiping and resumes once the gesture ends.
The rotationInterval unit differs across platforms. Android and React Native expect milliseconds (e.g. 10_000 / 10000). The property is ignored on iOS.

Click actions

Both PlayerConfig.clickAction and WidgetConfig.clickAction accept the same values: