Setup & Installation

Using SmartVideo with JavaScript frameworks (Angular, React, Vue)

Updated October 5, 2026

SmartVideo runs in any web app, including single-page apps built with Angular, React, or Vue. The main things to know are which embed form to use inside a framework, where to load the snippet, and a few gotchas around re-rendering, server-side rendering, and iOS.

Use the <div class="smartvideo"> form

Use the <div class="smartvideo"> form in a framework. In Angular, use this form rather than <smartvideo>: CUSTOM_ELEMENTS_SCHEMA permits dash-case custom-element names and does not recognize the undashed SmartVideo tag. In Vue, <smartvideo> can also be used if your template compiler’s isCustomElement option recognizes it.

  • Angular and Vue: put the smartvideo div inside a wrapper element in a component that owns one video and disposes its player on unmount/destroy (see below). Put v-if/*ngIf and keys on the video-owning component. Dispose initialized players in Vue’s onBeforeUnmount or Angular’s ngOnDestroy; Vue’s onUnmounted runs after unmounting. Bind src and the other attributes on the smartvideo div only when it is created. To play a different video, recreate the component (for example with :key in Vue) instead of changing src afterward; a src on the outer wrapper does nothing, and changing it on an embed SmartVideo has already replaced does not update playback.
  • React: render an empty wrapper in JSX and create the smartvideo div inside it after mount, as shown below.

Drop the video in wherever you want it to appear, using the same attributes you’d put on the tag. In an HTML template (Angular, Vue):

<div>
  <div class="smartvideo swarm-fluid"
       src="https://your-video.example.com/file.mp4"
       width="1280" height="720" controls>
  </div>
</div>

In React, render an empty wrapper and create the embed after mount:

import { useEffect, useRef } from "react";

export function SmartVideo({ src }) {
  const wrapperRef = useRef(null);
  useEffect(() => {
    const wrapper = wrapperRef.current;
    const embed = document.createElement("div");
    embed.className = "smartvideo swarm-fluid";
    embed.setAttribute("src", src);
    embed.setAttribute("width", "1280");
    embed.setAttribute("height", "720");
    embed.setAttribute("controls", "");
    wrapper.appendChild(embed);
    return () => {
      wrapper.querySelector(".video-js")?.player?.dispose();
      wrapper.replaceChildren();
    };
  }, [src]);
  return <div ref={wrapperRef} />;
}

The React example disposes players that have already initialized, but it does not cancel initialization still in progress. On iOS, and in browsers without Media Source Extensions that play HLS natively, initialization can wait for a network request; changing src or unmounting during that wait can leave a player that is never disposed.

Our player scans for both the <smartvideo> tag and the smartvideo class and treats them identically, so you lose nothing by using the div. The attributes match the tag - see Basic SmartVideo tag options. For a Library video, copy its Source URL from Media Details and use it as src; uploads use a swarmify:// reference, while URL Imports retain their source URL. The SmartVideo head snippet must still be installed on the page. For an external source, the URL must return the video bytes to an anonymous HTTP GET without a login or cookies - not localhost or an auth-gated page. A link that expires can stop working when Swarmify needs to fetch it again.

Load the snippet once, in your root HTML

Add your SmartVideo snippet to the <head> of your app’s root HTML file (for example index.html in Angular CLI, Vite, or Create React App), not inside a component that mounts and unmounts. It only needs to load once for the whole app. You can grab the snippet from the Configuration tab in your dashboard; the non-WordPress setup guide walks through where it goes.

Server-rendered frameworks (Next.js, Nuxt, Angular with SSR): load the snippet once through your framework’s script-loading mechanism. Create the video embed only in the browser, after the containing component has hydrated, so the player cannot replace server-rendered markup before the framework hydrates it. Keep the root script configuration outside route components.

If your app sends a Content-Security-Policy, these are the default Swarmify origins to account for:

  • script-src: https://assets.swarmcdn.com, plus authorization for your inline configuration snippet using your policy’s nonce or hash.
  • connect-src: wss://hornets.swarmcdn.com, https://video-node.swarmcdn.com, and https://video-node2.swarmcdn.com.
  • media-src: https://video-node.swarmcdn.com, https://video-node2.swarmcdn.com, and blob: for MediaSource playback.
  • img-src: https://assets.swarmcdn.com, both video-node origins for generated posters, and data: for the player’s built-in icons, plus any custom poster origin.
  • style-src: https://assets.swarmcdn.com for the player stylesheet. The player also inserts styles and sets inline dimensions, so a policy that blocks inline styling needs separate integration testing.
  • font-src: data: for the player’s icon font.

This is not a complete policy to paste over your app’s existing one. External video sources and optional integrations can need additional origins. Check the browser’s CSP violations while loading and playing a video, and add only the permissions your setup uses.

Videos that appear after navigation

In a single-page app, video elements can be added after the first load when a route changes or a component renders. SmartVideo uses a MutationObserver on the document to trigger rescans when nodes are added. Newly inserted SmartVideo embeds are picked up automatically; you do not need a manual initialization call after React, Vue, or Next.js client-side navigation. Set the source and other attributes before inserting the embed.

When SmartVideo initializes an element it replaces it with a Video.js player and removes the smartvideo class. Keep an outer wrapper owned by your framework, but let SmartVideo own everything inside it. In React, create the embed imperatively inside that wrapper after mount, as in the example above. For Vue and Angular, use a video-owning component with an outer wrapper, avoid changing the original embed’s attributes after SmartVideo replaces it, and dispose initialized players during the appropriate cleanup hook. Test the framework’s mount, update, and removal paths. For React, see the guidance on safely modifying DOM managed by React.

Clean up initialized players: Dispose initialized players during cleanup using the captured wrapper (wrapper.querySelector(".video-js")?.player?.dispose()), as in the React example above. React’s useEffect cleanup runs after the component is removed from the DOM; Vue users who need cleanup before removal should use onBeforeUnmount. This does not cancel pending initialization, as noted above. Don’t import a separate copy of Video.js to look the player up; it won’t know about SmartVideo’s players. Video.js documents player removal and disposal. Disposal also tears down SmartVideo’s Swarm registration when that playback tech is active. Simply removing the DOM node is not a substitute for disposal. When returning to a route, create a fresh embed inside a fresh wrapper; do not reuse the already-replaced embed or add the smartvideo class back to the initialized player.

A note on mobile apps

SmartVideo is a browser-based player. If your mobile app is a web or hybrid app - for example one built with Ionic or Capacitor, which run your web app inside a web view - the same embed works. Two iOS notes: test on a real device rather than browser device-emulation (emulated iOS can falsely report video support - see Why is SmartVideo not working in an emulated iOS browser), and for inline, non-fullscreen playback make sure your native shell allows inline media playback, which Capacitor and Ionic can configure. If your app has fully native screens (Swift or Kotlin) that don’t use a web view, those screens can’t run the browser embed; play from your original video source there instead.

See also

If you hit a snag wiring SmartVideo into your framework, email support@swarmify.com and we’ll help.

Keywords: Angular, React, Vue, Next.js, Nuxt, JavaScript framework, single-page app, SPA, server-side rendering, hydration, className, custom element, div class smartvideo, route change, cleanup, dispose, CSP, Ionic, Capacitor, web view, native app

Get SmartVideo live on your site

Set it up on WordPress, Shopify, Squarespace, or any platform in a few minutes.

14-day free trial · Card required, no charge until day 15