# Web Component - Sportsbook Integration Guide

## Introduction

The **NSoft Sportsbook** is a full-featured micro-frontend that provides a complete betting interface with event browsing, betslip management, live betting, and customizable routing. It’s built as a standalone Web Component and can be integrated into any host application.

This guide contains all information necessary to integrate, configure, and customize the Sportsbook component for your specific use case.

### About Micro-Frontends&#xD;

Micro-frontends are independent, self-contained frontend applications that can be deployed separately and composed together in a larger application. They enable teams to develop, test, and deploy frontend features independently while maintaining a cohesive user experience.

The Sportsbook is built as a Web Component, a standard browser API that allows you to:

* Define custom HTML elements with encapsulated functionality
* Use the component in any JavaScript framework, vanilla HTML or even in native applications via WebViews
* Deploy and update the component independently
* Maintain clear boundaries between the component and host application

About the Tooling

All **NSoft Sportsbook** micro-frontends share a consistent architecture and deployment model.

### Distribution Model&#xD;

* **CDN-only**: Components are distributed exclusively via CDN to ensure users always receive the latest stable version without managing local builds
* **ES Module**: Distributed as ES modules (type="module"), compatible with all modern browsers and modern build systems
* **Environment-specific**: Separate builds are published for staging and production environments
* **Dependency-free**: Each component is self-contained with all dependencies bundled. Tree-shakeable and optimized for minimal payload size, with no external npm dependencies required.

### Technology Stack&#xD;

* **TypeScript**: Full type safety for better development experience
* **Web Components API**: Standard browser APIs for custom elements

### Component Registration Pattern&#xD;

All **NSoft Sportsbook** micro-frontends follow a consistent registration pattern:

```javascript
import { registerComponentName } from 'https://staging.nsftx-sports-web.nsoft.app/nsftx-sports-web.js'

registerComponentName({
  // Configuration options (component-specific)
})
```

Each component exports a registration function that:

* Validates the provided configuration using Zod schemas
* Defines the custom element in the browser’s element registry
* Sets up internal state management and routing (if applicable)

This pattern ensures consistency across all components while allowing component-specific configuration.

## Installation

The Sportsbook is distributed exclusively via CDN as an ES module. This ensures you always receive the latest stable version without managing local builds.

### CDN URLs

<table><thead><tr><th width="130.25">Environment</th><th>Primary CDN</th><th>Secondary CDN (Fallback)</th></tr></thead><tbody><tr><td>Production</td><td><a href="https://nsftx-sports-web.nsoft.app/nsftx-sports-web.js"><code>https://nsftx-sports-web.nsoft.app/nsftx-sports-web.js</code></a></td><td><a href="https://nsftx-sports-web.7platform.net/nsftx-sports-web.js"><code>https://nsftx-sports-web.7platform.net/nsftx-sports-web.js</code></a></td></tr><tr><td>Staging</td><td><a href="https://staging.nsftx-sports-web.nsoft.app/nsftx-sports-web.js"><code>https://staging.nsftx-sports-web.nsoft.app/nsftx-sports-web.js</code></a></td><td><a href="https://staging.nsftx-sports-web.7platform.net/nsftx-sports-web.js"><code>https://staging.nsftx-sports-web.7platform.net/nsftx-sports-web.js</code></a></td></tr></tbody></table>

{% hint style="info" %}
We recommend implementing a fallback mechanism that attempts to load from the primary CDN first, then falls back to the secondary CDN if the primary is unavailable.
{% endhint %}

## Registration

To register the Sportsbook component, import the registration function and call it with your configuration:

```javascript
const PRIMARY_CDN = 'https://nsftx-sports-web.nsoft.app/nsftx-sports-web.js'
const SECONDARY_CDN = 'https://nsftx-sports-web.7platform.net/nsftx-sports-web.js'

let registerSportsbookMicroFrontend

try {
  ;({ registerSportsbookMicroFrontend } = await import(PRIMARY_CDN))
} catch (error) {
  console.warn('Primary CDN failed, attempting secondary CDN...', error)

  try {
    ;({ registerSportsbookMicroFrontend } = await import(SECONDARY_CDN))
  } catch (error) {
    console.error('Both CDNs failed to load', error)
    throw error
  }
}

registerSportsbookMicroFrontend({
  basePath: '/sportsbook',
  routeMappings: {
    homepage: 'home',
    sports: 'desporto',
    live: 'directo'
  }
})
```

\
Then add the component to your HTML:

```html
<main>
  <nsftx-sports-web id="sportsbook" />
</main>
```

{% hint style="info" %}
The `id` attribute is required by the iGnite script for parent-to-child communication.
{% endhint %}

### Configuration Options&#xD;

<table><thead><tr><th width="146.75">Option</th><th width="86.75">Type</th><th width="410.75">Description</th><th width="106.75">Required</th></tr></thead><tbody><tr><td><code>basePath</code></td><td>string</td><td>The base path for the component’s router. Defaults to <code>/</code>. Essential for subpath deployments.</td><td>No</td></tr><tr><td><code>routeMappings</code></td><td>object</td><td>Custom route names for navigation routes (homepage, sports, live). All properties are optional.</td><td>No</td></tr><tr><td><code>tag</code></td><td>string</td><td>Custom Web Component tag name. Defaults to <code>nsftx-sports-web</code>.</td><td>No</td></tr></tbody></table>

Configuration Details

### Base Path&#xD;

Because the Sportsbook includes an internal router, it relies on a base URL to resolve relative paths correctly. This is crucial for proper routing, especially in environments where the component is mounted under a subpath.

By default, the base path is set to `/`. If omitted, relative navigation may break or result in incorrect route resolution.

```javascript
// Example: Component mounted at https://example.com/my-app/betting/
registerSportsbookMicroFrontend({
basePath: '/my-app/betting'
})
```

{% hint style="warning" %}
If no base path is provided, `/` will be used as the default, which may not be appropriate for all integration contexts.
{% endhint %}

### Route Mappings&#xD;

The Sportsbook provides three main routes that can be customized through route mappings. Since the host and the web component share the same browser history context, the host can provide custom route names that will be used consistently in the routing history.

This ensures better alignment between the host application and the component’s navigation.

### Available Routes&#xD;

<table><thead><tr><th width="184">Route Key</th><th width="183.25">Default Name</th><th>Purpose</th></tr></thead><tbody><tr><td><code>homepage</code></td><td><code>home</code></td><td>Main landing page with featured events and recommendations</td></tr><tr><td><code>sports</code></td><td><code>sports</code></td><td>Sports catalog and event listings</td></tr><tr><td><code>live</code></td><td><code>live</code></td><td>Live betting events and in-play markets</td></tr></tbody></table>

### Example: Localized Route Names&#xD;

```javascript
registerSportsbookMicroFrontend({
  basePath: '/sportsbook',
  routeMappings: {
    homepage: 'inicio',    // Portuguese: Start
    sports: 'desportos',   // Portuguese: Sports
    live: 'ao-vivo'        // Portuguese: Live
  }
})
```

All route properties in `routeMappings` are optional. If a property is not provided, the component will use its default route name.

Styling and Layout

The Sportsbook includes features to ensure proper integration with your page layout, particularly when dealing with fixed or sticky positioned elements.

### Handling Sticky/Fixed Positioned Elements&#xD;

When embedding the component in a page with sticky or fixed-positioned elements (headers, navigation bars, etc.), you should account for their heights to prevent content overlap.

Define CSS custom properties on the `:root` element:<br>

```css
:root {
  --parent-offset: 4rem;            /* Top offset (e.g., header height) */
  --parent-bottom-offset: 3.125rem; /* Bottom offset (e.g., footer height) */
}
```

These variables tell the component to adjust its internal layout dynamically.

{% hint style="warning" %}
For desktop version, set a **fixed** height on the component’s container. This is necessary because the desktop component includes multiple scrollable areas (sidebar, offer panel, betslip/last bets). On mobile, use a relative height so the `<body>` element can adjust dynamically based on total visible content, accounting for browser UI changes like the address bar showing/hiding.
{% endhint %}

### Accounting for Component’s Fixed Elements&#xD;

The Sportsbook includes fixed UI elements such as the navigation bar, betslip bar, and notifications. These expose a CSS variable called `--bottom-ui-height` that represents their combined height.

Use this variable to adjust the page layout and prevent content from being hidden:

```css
body {
  padding-bottom: var(--bottom-ui-height);
}
```

Advanced Customization: Using Native Slots

### Customizing the Footer with the nsftxFooter Slot&#xD;

The Sportsbook web component does not provide its own footer. Instead, it exposes a native slot named `nsftxFooter` so that host applications can inject their own custom footer content if desired. If you do not provide content for this slot, no footer area will be rendered by default.

This is useful if you want to add your own branding, links, or widgets to the bottom of the Sportsbook interface, but is entirely optional and controlled by the host.

To use the slot, place your custom HTML as a child of the `<nsftx-sports-web>` element and set the `slot` attribute to `nsftxFooter`:

```html
<nsftx-sports-web id="sportsbook">
  <footer slot="nsftxFooter">
    <!-- Your custom footer content -->
    <div class="my-footer">
      Custom Footer © 2026
    </div>
  </footer>
</nsftx-sports-web>
```

You can use any valid HTML or framework-specific components inside the slot. The web component will render your custom content in the designated footer area if present, but will not render any footer by default.

## Advanced Customization: Using Game Options

This section documents each game option supported by the Sportsbook micro-frontend, including how it works when set on initialization and when updated at runtime. For the overall structure of `gameOptions`, refer to the provided iGnite documentation.

### Theme

Controls the color theme of the Sportsbook interface.

{% hint style="warning" %}
To avoid conflicts with the punter’s selection, the punter theme selection must be disabled through the **Sportsbook CMS**. This allows the host to fully control theming in the **Sportsbook** component using game options.
{% endhint %}

**Values**: `'dark'`, `'light'`

**On Initialization**: Set the initial theme by passing the `theme` property in `gameOptions`:

```javascript
{
  frameId: 'sportsbook',
  childId: 'sportsbook',
  gameOptions: {
    theme: 'dark',
  }
}
```

**At Runtime**: Change the theme dynamically using `updateGameOptions`:

```javascript
integrator.updateGameOptions({
  action: 'UPDATE_THEME',
  theme: 'light'
})
```

**Effect**: Updates the Sportsbook to use the selected theme immediately.

Troubleshooting

### Routes Not Resolving Correctly&#xD;

**Problem**: Routes are returning 404 or navigation isn’t working.

**Solution**: Ensure the `basePath` matches your application’s routing structure exactly. If the component is served at [`https://example.com/betting/`](https://example.com/betting/), set `basePath: '/betting'` (without trailing slash in most cases).

```javascript
// Correct
registerSportsbookMicroFrontend({ basePath: '/betting' })

// Incorrect - won't match /betting/sports
registerSportsbookMicroFrontend({ basePath: '/betting/' })
```

### Content Hidden Behind Fixed Elements&#xD;

**Problem**: The component’s content is being covered by headers or footers.

**Solution**: Set the `--parent-offset` and `--parent-bottom-offset` CSS variables to match the heights of your fixed elements.

```css
:root {
  --parent-offset: 80px;        /* Your header height */
  --parent-bottom-offset: 60px; /* Your footer height */
}
```

Best Practices

* **Always set `basePath`**: Don’t rely on the default `/` unless your component is at the root
* **Test in isolation**: Test the component in a standalone page before integrating

Additional Resources

* [Web Components - Using Custom Elements](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) - MDN documentation on Web Components

Integration Examples

You can find a GitHub project showcasing integration of the Sportsbook micro-frontend in multiple JavaScript frameworks (Vanilla JS, Vue, Next.js, Svelte) here:<br>

* [NSoft Sportsbook Micro-Frontends Integration Examples](https://github.com/nsftx/nxg-sports-micro-frontends-example)
