Compatibility

WebShorts is designed to work with any React framework. Learn about specific setup requirements for different frameworks.

⚠️

Next.js App Router

⚠️ CRITICAL: Client Wrappers Required

If you are using Next.js App Router (the /app directory), you MUST use client wrappers for both the WebShortsProvider and ShortcutListener components. This is not optional - you WILL encounter SSR/hydration issues without them.

Setup Instructions

1. Create the Client Provider Wrapper

// components/ClientWebShortsProvider.jsx
'use client';
import { useEffect, useState } from 'react';
import { WebShortsProvider, WebShortsDialog } from '@chrisnski/webshorts';
import { usePathname } from 'next/navigation';
import { Toaster } from 'sonner';

export default function ClientWebShortsProvider({ children, config, className }) {
  const [mounted, setMounted] = useState(false);
  const pathname = usePathname();

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    // Return children without the provider during SSR
    return children;
  }

  return (
    <WebShortsProvider config={config} currentPage={pathname} className={className}>
      {children}
      <WebShortsDialog />
      <Toaster position='bottom-right' richColors />
    </WebShortsProvider>
  );
}

2. Create the App Wrapper

// components/WebShortsProviderWrapper.jsx
'use client';
import ClientWebShortsProvider from './ClientWebShortsProvider';
import webshortsConfig from '../webshorts.config';

export default function WebShortsProviderWrapper({ children, className }) {
  return (
    <ClientWebShortsProvider config={webshortsConfig} className={className}>
      {children}
    </ClientWebShortsProvider>
  );
}

3. Use in Root Layout

// app/layout.js (Server Component)
export const metadata = { 
  title: 'My App',
  description: 'My app description'
};

import WebShortsProviderWrapper from '../components/WebShortsProviderWrapper';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <WebShortsProviderWrapper>
          {children}
        </WebShortsProviderWrapper>
      </body>
    </html>
  );
}

4. Create Client Wrapper for ShortcutListener (REQUIRED)

// components/ClientShortcutListener.jsx
'use client';
import { useEffect, useState } from 'react';
import { ShortcutListener } from '@chrisnski/webshorts';

export default function ClientShortcutListener({ children, keys, action, shortName, description }) {
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    // Return the children without the ShortcutListener wrapper during SSR
    return children;
  }

  return (
    <ShortcutListener 
      keys={keys} 
      action={action} 
      shortName={shortName} 
      description={description}
    >
      {children}
    </ShortcutListener>
  );
}

5. Usage Example

// Instead of using ShortcutListener directly:
<ShortcutListener keys="CTRL + S" action={handleSave} shortName="Save" description="Save content">
  <div>Press CTRL + S to save</div>
</ShortcutListener>

// Use the client wrapper:
import ClientShortcutListener from '@/components/ClientShortcutListener';

<ClientShortcutListener keys="CTRL + S" action={handleSave} shortName="Save" description="Save content">
  <div>Press CTRL + S to save</div>
</ClientShortcutListener>

Why Both Wrappers Are Required

  • Server Components - Next.js App Router uses server components by default
  • Context Providers - WebShortsProvider is a client-side context provider
  • Shortcut Listeners - ShortcutListener components need client-side mounting
  • SSR/Hydration Race - Both components will fail in production without wrappers
  • Guaranteed Issues - This is not optional - you WILL encounter problems without these wrappers

Note: This pattern is required for all context/hook-based libraries in Next.js App Router. See the Next.js docs for more details.

Other React Frameworks

WebShorts works seamlessly with other React frameworks without special configuration.

Create React App

// App.jsx
import { WebShortsProvider, WebShortsDialog } from '@chrisnski/webshorts';
import shortcutsConfig from './webshorts.config.js';

function App() {
  return (
    <WebShortsProvider config={shortcutsConfig} currentPage={pathname}>
      <div className='App'>
        <Header />
        <Main />
        <Footer />
      </div>
      <WebShortsDialog />
    </WebShortsProvider>
  );
}

Vite

// main.jsx
import { WebShortsProvider, WebShortsDialog } from '@chrisnski/webshorts';
import shortcutsConfig from './webshorts.config.js';

function App() {
  return (
    <WebShortsProvider config={shortcutsConfig} currentPage={pathname}>
      <div className='App'>
        <Header />
        <Main />
        <Footer />
      </div>
      <WebShortsDialog />
    </WebShortsProvider>
  );
}

Remix

// app/root.jsx
import { WebShortsProvider, WebShortsDialog } from '@chrisnski/webshorts';
import shortcutsConfig from './webshorts.config.js';

export default function App() {
  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <WebShortsProvider config={shortcutsConfig} currentPage={pathname}>
          <Outlet />
          <WebShortsDialog />
        </WebShortsProvider>
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

Next.js Pages Router

// pages/_app.js
import { WebShortsProvider, WebShortsDialog } from '@chrisnski/webshorts';
import shortcutsConfig from './webshorts.config.js';

export default function App({ Component, pageProps }) {
  return (
    <WebShortsProvider config={shortcutsConfig} currentPage={pathname}>
      <Component {...pageProps} />
      <WebShortsDialog />
    </WebShortsProvider>
  );
}

Browser Compatibility

WebShorts is compatible with all modern browsers that support React.

Supported Browsers

  • • Chrome 90+
  • • Firefox 88+
  • • Safari 14+
  • • Edge 90+

Required Features

  • • ES6+ support
  • • React 16.8+ (hooks support)
  • • Modern DOM APIs
  • • Keyboard event handling

React Version Requirements

Minimum Requirements

  • React 16.8+ - Required for hooks support
  • React DOM 16.8+ - Required for DOM manipulation
  • Modern JavaScript - ES6+ features required

Recommended Versions

  • React 18+ - Latest features and performance improvements
  • React DOM 18+ - Concurrent features support
  • Node.js 16+ - For development and build tools

Common Issues & Solutions

"Module not found" errors

Make sure you've installed all peer dependencies:

npm install @radix-ui/react-dialog sonner react react-dom

Toasts not showing

Ensure Sonner is properly configured in your app:

import { Toaster } from 'sonner';

function App() {
  return (
    <>
      <YourApp />
      <Toaster />
    </>
  );
}

Shortcuts not working

  • • Check that the WebShortsProvider wraps your entire app
  • • Verify key combinations are valid (e.g., "CTRL + S" not "Ctrl + S")
  • • Enable debug mode to see registration and execution feedback
  • • Ensure no other libraries are intercepting keyboard events