@competitionlabs/gamification-widget-loader
v1.1.0
Published
Browser-side loader for the CompetitionLabs gamification widget. It retrieves the active widget configuration from the CompetitionLabs gateway, loads the JavaScript and CSS assets declared by that configuration, and mounts the widget in the containers sup
Keywords
Readme
CompetitionLabs Gamification Widget Loader
Browser-side loader for the CompetitionLabs gamification widget. It retrieves the active widget configuration from the CompetitionLabs gateway, loads the JavaScript and CSS assets declared by that configuration, and mounts the widget in the containers supplied by the host application.
The package exposes a singleton at window.clLoaderV3.
Prerequisites
- Node.js 22.16.0 (the version is defined in
.nvmrc) - npm
- A CompetitionLabs space name
- A CompetitionLabs member ID from the host application's authenticated session
- Access to a CompetitionLabs gateway, either directly with the required CORS configuration or through a same-origin backend proxy
- A restricted API key for local testing, or a backend proxy that adds the API key server-side in production
Install and run the project
Clone the repository, select the expected Node.js version, and install the locked dependencies:
nvm use
npm ciStart the Vite development server:
npm run devVite opens the example page at /example/index.html. Update example/example.js with settings for a development environment before testing the widget.
Do not commit real API keys, production credentials, or member data to the example files.
Build
Create the production bundle with:
npm run buildVite writes the following browser assets to dist/:
loader.js— IIFE browser bundleloader.js.gz— gzip-compressed bundleloader.js.br— Brotli-compressed bundle
Project scripts
| Command | Description |
| --- | --- |
| npm run dev | Starts Vite and opens the example page. |
| npm run build | Builds the loader and its precompressed variants into dist/. |
| npm run publish:restricted | Builds and publishes the npm package with restricted access. Requires npm registry authorization. |
| npm test | Placeholder only; automated tests are not currently configured. |
Add the loader to a vanilla JavaScript application
The complete walkthrough is available in docs/GamificationWidgetVanillaJs.md. The essential setup is included below.
1. Install the package
npm install @competitionlabs/gamification-widget-loaderFor an application that uses Vite or another bundler, import the package once in the browser entry point:
import '@competitionlabs/gamification-widget-loader';For a site without a bundler, copy node_modules/@competitionlabs/gamification-widget-loader/dist/loader.js to a public vendor directory and load it before the site's application script:
<script src="/vendor/competitionlabs/loader.js"></script>
<script src="/js/main.js"></script>Do not expose the entire node_modules directory from a production web server.
2. Add the widget containers
Both containers must exist before init() is called:
<body>
<main>
<div id="clv3WidgetMini"></div>
</main>
<div id="clv3Widget"></div>
<script type="module" src="/src/main.js"></script>
</body>3. Configure and initialise the loader
// src/main.js
import '@competitionlabs/gamification-widget-loader';
function initialiseGamificationWidget({
apiKey = '',
spaceName,
memberId,
language = 'en',
themeMode = 'light',
startMinimised = true,
}) {
const loader = window.clLoaderV3;
const expandedContainer = document.getElementById('clv3Widget');
const minimisedContainer = document.getElementById('clv3WidgetMini');
if (!loader) {
throw new Error('CompetitionLabs widget loader was not created');
}
if (!expandedContainer || !minimisedContainer) {
throw new Error('CompetitionLabs widget containers were not found');
}
// This example expects the host application to proxy gateway requests
// through /cl_public and add the API key on the server.
const gatewayDomain = new URL('/cl_public', window.location.origin)
.toString()
.replace(/\/$/, '');
const gatewayWSDomain = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}`;
loader.settings.apiKey = apiKey;
loader.settings.spaceName = spaceName;
loader.settings.memberId = memberId;
loader.settings.uri.gatewayDomain = gatewayDomain;
loader.settings.uri.gatewayWSDomain = gatewayWSDomain;
loader.settings.uomSymbol = '€';
loader.settings.language = language;
loader.settings.themeMode = themeMode;
loader.settings.widgetStatus = 'Live';
loader.settings.isWidgetMinimized = startMinimised;
loader.settings.enableNotifications = false;
loader.settings.bindContainer = expandedContainer;
loader.settings.miniBindContainer = minimisedContainer;
loader.settings.resources = [
'https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,100..900;1,100..900&display=swap',
];
loader.init(() => {
console.log('CompetitionLabs widget initialised');
});
}
initialiseGamificationWidget({
spaceName: 'SPACE_NAME',
memberId: 'MEMBER_ID',
});Replace SPACE_NAME and MEMBER_ID with values from the target environment and authenticated user session. If the integration does not use a same-origin proxy, also set the gateway URLs and supply a restricted API key appropriate for that environment.
The loader requests the active widget configuration, then loads and initialises the script and styles associated with its layout. The gateway must allow the request and return a matching live widget from:
GET {gatewayDomain}/api/v1/{spaceName}/widget?status=Live&startDate<=...&endDate>=...&themeMode=LIGHTSecurity note
An API key embedded in browser JavaScript is visible in page source, developer tools, and network requests. Use a restricted, short-lived non-production key only for local testing. In production, route the request through a backend proxy that adds the API key server-side and leave loader.settings.apiKey empty in the browser.
Optional hosted widget implementation
A compatible self-initialising widget build can be loaded before the loader and application scripts. For the type_2 theme:
<script src="https://assets.competitionlabs.com/gamification-widget/competitionlabs-gamification-widget-v3/themes/type_2/javascript/gamification-ux-package.v3-selfinit.js.gz"></script>
<script src="/vendor/competitionlabs/loader.js"></script>
<script src="/js/main.js"></script>The hosted script provides window._clWidgetV32026SelfInit; it does not replace window.clLoaderV3 or the loader.init() call. When it is not preloaded, the loader uses the gateway configuration to select the correct implementation.
Loader lifecycle
Calling init() again reloads the widget configuration and replaces an existing widget instance. This is useful when the member, language, or theme changes.
To remove the widget completely:
window._clWidgetV32026?.destroy?.();
document.getElementById('clv3Widget')?.replaceChildren();
document.getElementById('clv3WidgetMini')?.replaceChildren();Enable notifications only when the WebSocket or SSE channel is configured and reachable.
Project structure
loader.js Loader entry point and widget lifecycle
ajax.js Browser request helper
sizeof.js Small object/DOM utility
example/ Local Vite example
docs/GamificationWidgetVanillaJs.md Detailed vanilla JavaScript integration guide
vite.config.js Library build and compression configuration
dist/ Generated distribution filesDeployment
The Jenkins pipelines install dependencies, build the bundle, upload dist/ to the configured S3 prefix, attach the correct metadata to gzip and Brotli assets, and invalidate CloudFront for non-dry-run deployments. Deployments require the Jenkins AWS credentials and should first be verified with the DRY_RUN parameter enabled.
License
ISC
