npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nuxt-twitch-ext

v0.2.11

Published

Build your Twitch Extension and Extension Backend Service (EBS) in a single Nuxt project.

Readme

nuxt-twitch-ext

npm version npm downloads License

Build your Twitch Extension and Extension Backend Service (EBS) in a single Nuxt project.

Features

  • Manage only one project for the extension and its backend
  • Preview extension pages in Local Test with .html
  • Include the Twitch Extension Helper and type definitions
  • EBS API endpoints with CORS support
  • Client-side utility for EBS calls and public asset paths
  • Server utilities for Twitch JWT verification
  • Package extension environment assets as a ZIP
  • Only extension pages are pre-rendered in the extension build
  • Extension-only pages and assets are excluded from the app build

Quick Setup

  1. Add nuxt-twitch-ext dependency to your project
pnpm add nuxt-twitch-ext
  1. Add the module in your nuxt.config.ts
export default defineNuxtConfig({
  modules: ["nuxt-twitch-ext"],
});

Project Structure

A project structure with default directories might look like this:

app/
├── app.vue                        # Application root
├── pages/
│   ├── index.vue                  # Nuxt main page (Not an extension page)
│   ├── extension/                 # Twitch extension pages
│   │   ├── config.vue
│   │   ├── panel.vue
│   │   ├── mobile.vue
│   │   ├── video_overlay.vue
│   │   └── video_component.vue
│   ├── ...
├── assets/                        # Application assets
│   └── ...
server/
└── api/
    ├── ebs/                       # EBS API endpoints
    │   └── ...
    └── ...

Configuration

| Option | Default | Description | | ---------------------------- | ------------------------------------------------------------------- | ----------------------------------------------- | | helperScript | Twitch's Extension Helper | Script included in extension pages | | filename | 'twitch-ext.zip' | Name of the generated archive | | pages.dirname | 'extension' | Directory name for extension pages | | pages.prerender | ['config', 'panel', 'mobile', 'video_overlay', 'video_component'] | Pages to pre-render for the extension | | ebs.enabled | true | Enable the EBS utilities and CORS handling | | ebs.dirname | 'ebs' | Directory name for EBS API endpoints | | ebs.baseURL | | Production URL used by extFetch | | ebs.preflight.allowMethods | ['GET'] | Methods allowed for EBS CORS preflight requests | | ebs.preflight.allowHeaders | ['Content-Type', 'Authorization'] | Headers allowed for EBS CORS preflight requests |

For example, customize the archive name and CORS settings:

export default defineNuxtConfig({
  modules: ["nuxt-twitch-ext"],
  twitchExt: {
    filename: "my-extension.zip",
    ebs: {
      baseURL: "https://your-app.example.com",
      preflight: {
        allowMethods: ["GET", "POST"],
        allowHeaders: ["Content-Type", "Authorization", "X-Custom-Header"],
      },
    },
  },
});

[!TIP] When the EBS is enabled, twitchExt.ebs.baseURL must be set to the production URL of the Nuxt server, so that extFetch can correctly target the production EBS endpoints.

Environment Variables

Provide the Twitch Extension Client ID and Extension Secret Key as server-only runtime configuration values.

NUXT_TWITCH_EXT_CLIENT_ID=your-extension-client-id
NUXT_TWITCH_EXT_SECRET_KEY=your-extension-secret-key

Extension Pages

The default directory for extension pages is app/pages/extension/. The directory name for extension pages can be changed with twitchExt.pages.dirname.

When navigating between extension pages, use relative paths (./<page>) instead of root-relative paths (/<page>).

<template>
  <NuxtLink to="./another-page">Another Page</NuxtLink>
</template>

I recommend placing extension assets in the app/assets/ folder and referencing them from your extension pages as ~/assets/<file>. For example:

<template>
  <img src="~/assets/images/logo.png" alt="My Logo" />
</template>

Nuxt processes referenced assets for the extension build; unreferenced files in app/assets/ are not included.

For assets that should be available in all environments, place them in public/. Nuxt serves these files as-is in development and production, and the extension build includes them too.

Use the auto-imported extAsset helper for public assets referenced dynamically in an extension page. It keeps root-relative paths in development and resolves them against the extension assets in a Twitch build:

<template>
  <img :src="extAsset('/images/logo.png')" alt="Logo" />
</template>

Development Environment

In development, extension pages are accessible at root level with .html for easy preview during Twitch Extension Local Test status.

For example, app/pages/extension/<page>.vue can be accessed as /<page>.html

Twitch Extension Build

The module CLI runs Nuxt in twitchExt mode (nuxt-twitch-ext). In this mode, the build only includes pages from app/pages/extension/ (or the directory configured by twitchExt.pages.dirname).

For each extension page:

  1. The extension/ directory segment is removed from the route
  2. If the page name matches one of the twitchExt.pages.prerender values, it is pre-rendered as a root-level HTML file.
  3. Nuxt's inline state is extracted into a sibling JavaScript file

For example:

app/pages/extension/panel.vue

is generated as:

panel.html
panel-nuxt-state.js

Regular application pages, such as app/pages/index.vue, are not included in the extension build.

The build also:

  • Includes the Twitch Extension Helper
  • Uses relative URLs for generated assets
  • Ignores Nuxt's default 200.html and 404.html pages
  • Uses twitchExt.ebs.baseURL as the base URL for the extFetch utility

Production App Environment

When Nuxt runs in production (nuxt build), pages under twitchExt.pages.dirname are excluded from the application routes. Unlike development or the twitchExt build, this does not generate extension pages or package an extension ZIP; regular application pages and endpoints remain available.

When EBS is enabled, the module register a middleware for routes under /api/<twitchExt.ebs.dirname>/** that:

  • Adds https://<client-id>.ext-twitch.tv as the allowed origin in CORS responses.
  • Answers OPTIONS preflight requests with the configured allowed methods and headers.

Call verifyTwitchExtension or verifyTwitchTransaction server utilities in EBS route handlers as appropriate.

Auto Imports

Twitch Extension Client:

  • extAsset(path) returns the path for an asset within the Twitch extension, based on the current navigation URL and origin.
  • extFetch(request, options?) instance of $fetch that fetches data from the EBS endpoints, uses the current origin in development and twitchExt.ebs.baseURL in the generated Twitch extension as the base URL for EBS requests.

Server:

  • verifyTwitchExtension(event) verifies the Twitch JWT token for your extension, returning the verified payload or null if the verification fails.
  • verifyTwitchTransaction(event, receipt) verifies a Bits transaction receipt for your extension, returning the verified payload or null if the verification fails.

Working with the EBS

After Twitch authorizes the extension, extFetch automatically adds the current token as a Bearer token in the Authorization header for requests to the EBS origin. Calls made before authorization do not include the token.

[!IMPORTANT] Add the domain of twitchExt.ebs.baseURL to the Allowlist for URL Fetching Domains in your Twitch Extension Capabilities settings. Without it, requests from the extension to the EBS may be blocked.

<script setup lang="ts">
onMounted(() => {
  Twitch.ext.onAuthorized(async () => {
    const data = await extFetch("/api/ebs/data");
  });
});
</script>

Verify the token in the server route before processing the request:

export default defineEventHandler(async (event) => {
  const payload = await verifyTwitchExtension(event);

  if (!payload) {
    throw createError({
      status: 401,
      message: "Invalid authorization",
    });
  }

  return { channelId: payload.channel_id };
});

[!NOTE] You can set twitchExt.ebs to false to disable the EBS entirely.

Build the Extension

Add the following script to your package.json to build the Twitch extension:

"scripts": {
  "build:twitch-ext": "nuxt-twitch-ext"
}

This runs nuxt generate --envName twitchExt and writes .output/twitch-ext.zip by default. Upload that ZIP in your Twitch Extension files tab in the Twitch developer console.

Caveats

  • An index.vue at the root of the extension pages directory and defined in the twitchExt.pages.prerender array does not generate index.html. With the default pages.dirname: "extension", app/pages/extension/index.vue generates /extension.html.
  • Twitch's Extension Content Security Policy (CSP) blocks inline JavaScript, including inline <script> elements. The extension build moves Nuxt's inline state script to a sibling *-nuxt-state.js file, but custom inline scripts are not rewritten. Put custom JavaScript in Vue component scripts or imported .js/.ts files so Nuxt can bundle it.
  • In the twitchExt build, this module disables unsupported modules such as @nuxtjs/color-mode, @nuxthub/core, and @nuxtjs/sitemap.
  • Referencing assets from the public folder without using extAsset may result in incorrect paths within the Twitch extension.