Use this checklist before you release a feature built with the Dadan Record SDK. Each item explains what to check and why it matters.
Allowlist your production origins
Link to section: Allowlist your production originsIn Account & Settings, then Developers, edit your public app and add every origin where the recorder runs in production, such as https://app.example.com, plus any staging origins you test on. Only the exact origins on the list can start a recording with your public app ID.
Keep the list short. Remove development and preview origins you no longer use, and avoid allowlisting origins you do not control. The allowlist stops other websites from using your public app ID in a browser, but it is not a login: anyone who loads your allowlisted pages can record, so put the recorder behind your own sign-in where that matters.
Keep secrets on your server
Link to section: Keep secrets on your server- Use
publicAppIdin the browser only. It is designed to be public, and it is not a password. - Never pass your Dadan API key to the SDK or ship it in frontend code. If it receives a value that looks like a Dadan API key, the SDK throws an error instead of starting.
- Never log upload tokens, and do not include them in support requests.
Check browser support before showing the button
Link to section: Check browser support before showing the buttonHide or disable recording where it cannot work, instead of letting people hit an error:
import {
isModeSupported,
isSupported,
} from "@dadan-io/record-sdk/is-supported";
const canRecord = (await isSupported()).supported;
const canRecordScreen =
canRecord && (await isModeSupported("screen")).supported;The @dadan-io/record-sdk/is-supported entry point weighs less than 1 KB, so you can run the check on page load without loading the recorder.
| Platform | Available modes |
|---|---|
| Chrome, Edge, Firefox and Safari on desktop (current versions) | both, screen, camera, audio |
| Mobile browsers, including iOS Safari and Android Chrome | camera, audio |
Recording only works on secure pages: HTTPS in production, http://localhost during development.
Load the recorder only when it is needed
Link to section: Load the recorder only when it is neededMeasured for version 1.0 with a minified production build:
| What you import | Size (gzipped) |
|---|---|
@dadan-io/record-sdk/is-supported | Under 1 KB |
DadanRecorder from @dadan-io/record-sdk | About 31 KB |
The built-in studio (@dadan-io/record-sdk-ui) with React 18 | About 90 KB |
If most visitors never record, load the studio when they first show intent, for example on the first click:
const button = document.querySelector<HTMLButtonElement>("#record-button")!;
button.addEventListener(
"click",
async () => {
button.disabled = true;
const { createInstance } = await import("@dadan-io/record-sdk-ui");
const studio = await createInstance({
mode: "custom",
publicAppId: import.meta.env.VITE_DADAN_PUBLIC_APP_ID,
});
studio
.configureButton({ element: button })
.on("insert-click", (video) => console.info(video.sharedUrl));
button.disabled = false;
studio.open();
},
{ once: true },
);In React, use React.lazy or next/dynamic around the component that renders the recorder.
Allow the SDK in your Content Security Policy
Link to section: Allow the SDK in your Content Security PolicyIf your site sends a CSP header, add these sources:
style-src 'self' 'nonce-YOUR_NONCE'
connect-src 'self' https://app.dadan.io https://upload.dadan.io https://upload-direct.dadan.io https://video.bunnycdn.com
media-src 'self' blob:
frame-src https://app.dadan.iostyle-src: the studio adds its stylesheet as a<style>element. Pass the same per-request nonce to the SDK and you do not need'unsafe-inline'. UsestyleNonceincreateInstance,sdk.styleNoncein the React and Vue components, thestyleNonceprop on Vue’sDadanRecorderHost, or thenonceattribute on<dadan-recorder>.connect-src:app.dadan.iohandles sessions, video records, downloads and oEmbed. Uploads go to the address Dadan returns when the video record is created, currently one of the upload hosts listed. Confirm the list with Dadan support before you enforce a strict policy.media-src: the live preview and the review screen play fromblob:URLs.frame-src: only needed if you embed the Dadan player.
Test the policy in report-only mode first (Content-Security-Policy-Report-Only) and record a full take, including the upload, before enforcing it.
Handle errors by code
Link to section: Handle errors by code- Show people a short, helpful message and log the
code. The error reference lists every code. - Offer a retry when an error is
recoverableor the code isupload_failed. - Never display the
detailfield. It can contain raw server text.
Clean up when the view goes away
Link to section: Clean up when the view goes awayRecorders hold the camera, the microphone and network connections. Release them when the component or page that owns them is removed:
| Integration | How to clean up |
|---|---|
DadanRecorder | recorder.destroy() |
createInstance | studio.teardown() |
<dadan-recorder> | Remove the element from the page |
| React and Vue components | Automatic on unmount |
Angular DadanRecorderService | Automatic when its injector is destroyed, or call teardown() |
Forgetting this is the most common cause of a camera light that stays on after leaving a page.
Explain recording and storage to your users
Link to section: Explain recording and storage to your users- Ask for consent where needed. Tell people what will be recorded, especially in
screenandbothmodes, where anything visible on the shared screen ends up in the video. - Mention Dadan in your privacy notice. Recordings are uploaded to and stored by Dadan.
- Unsent recordings stay in the browser. If an upload fails or the page is closed, the take is kept in the browser’s IndexedDB (in a store named
dadan-sdk-pending-take) for up to 24 hours, then deleted automatically. It is linked to your public app ID and never leaves the device unless the person chooses to upload it. - Restoring is opt-in. The built-in studio asks the person before restoring a pending take. To turn the offer off, set
config.features.restorePendingTaketofalse. Custom recorders decide for themselves withpersistPendingTake,recoverPendingTakeanddiscardPendingTake.
Test the real flows
Link to section: Test the real flowsBefore release, record and upload a full take in each situation your users will meet:
- Every mode you offer, in Chrome, Edge, Firefox and Safari on desktop.
- Camera and audio on iOS Safari and Android Chrome.
- Permission denied for the camera, the microphone and the screen, then allowed again.
- Stopping screen sharing from the browser’s own Stop sharing button.
- A network drop during upload, then a retry.
- A recording that reaches
maxDurationSeconds, if you set one. - Leaving the page during a recording: the camera light must turn off.
Keep the packages in step
Link to section: Keep the packages in stepInstall the same version of every @dadan-io package you use, and update them together. Mixing versions of the core, UI and framework packages can lead to type errors or two copies of the core in your bundle.