Skip to content

Next.js Integration

Integrate the Lingu widget into your Next.js application using the next/script component for optimal loading.

App Router (Next.js 13+)

Root Layout Integration

Add the widget to your root layout for site-wide availability:

tsx
// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        {children}
        
        {/* Lingu Widget Configuration */}
        <Script id="lingu-config" strategy="beforeInteractive">
          {`
            window.linguConfig = {
              apiKey: '${process.env.NEXT_PUBLIC_LINGU_API_KEY}',
              autoOpen: false
            };
          `}
        </Script>
        
        {/* Lingu Widget Script */}
        <Script 
          src="https://widget.uselingu.app/widget.js"
          strategy="lazyOnload"
        />
      </body>
    </html>
  );
}

Pages Router

Using _app.tsx

tsx
// pages/_app.tsx
import type { AppProps } from 'next/app';
import Script from 'next/script';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      
      {/* Lingu Widget Configuration */}
      <Script id="lingu-config" strategy="beforeInteractive">
        {`
          window.linguConfig = {
            apiKey: '${process.env.NEXT_PUBLIC_LINGU_API_KEY}',
            autoOpen: false
          };
        `}
      </Script>
      
      {/* Lingu Widget Script */}
      <Script 
        src="https://widget.uselingu.app/widget.js"
        strategy="lazyOnload"
      />
    </>
  );
}

Using _document.tsx

For more control, add to your custom document:

tsx
// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
        
        <script
          dangerouslySetInnerHTML={{
            __html: `
              window.linguConfig = {
                apiKey: '${process.env.NEXT_PUBLIC_LINGU_API_KEY}',
                autoOpen: false
              };
            `,
          }}
        />
        <script 
          src="https://widget.uselingu.app/widget.js"
          defer
        />
      </body>
    </Html>
  );
}

Environment Variables

Create environment variables for your API key:

bash
# .env.local
NEXT_PUBLIC_LINGU_API_KEY=lingu_abc123def456

WARNING

Variables prefixed with NEXT_PUBLIC_ are exposed to the browser. This is required for the widget to work.

Script Loading Strategies

Choose the right strategy based on your needs:

StrategyWhen to Use
beforeInteractiveConfig script - needs to be ready before widget loads
lazyOnloadWidget script - load after page is fully interactive
afterInteractiveAlternative - load after page hydration

Conditional Loading

Only load the widget on specific pages:

tsx
// app/layout.tsx
import { headers } from 'next/headers';
import Script from 'next/script';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const headersList = headers();
  const pathname = headersList.get('x-pathname') || '';
  
  // Don't show widget on admin pages
  const showWidget = !pathname.startsWith('/admin');

  return (
    <html lang="en">
      <body>
        {children}
        
        {showWidget && (
          <>
            <Script id="lingu-config" strategy="beforeInteractive">
              {`
                window.linguConfig = {
                  apiKey: '${process.env.NEXT_PUBLIC_LINGU_API_KEY}'
                };
              `}
            </Script>
            <Script 
              src="https://widget.uselingu.app/widget.js"
              strategy="lazyOnload"
            />
          </>
        )}
      </body>
    </html>
  );
}

Client Component Approach

Alternatively, use a client component:

tsx
// components/LinguWidget.tsx
'use client';

import { useEffect } from 'react';

export function LinguWidget() {
  useEffect(() => {
    window.linguConfig = {
      apiKey: process.env.NEXT_PUBLIC_LINGU_API_KEY!,
      autoOpen: false
    };

    const script = document.createElement('script');
    script.src = 'https://widget.uselingu.app/widget.js';
    script.async = true;
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
      const container = document.getElementById('lingu-widget-root');
      if (container) container.remove();
    };
  }, []);

  return null;
}
tsx
// app/layout.tsx
import { LinguWidget } from '@/components/LinguWidget';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <LinguWidget />
      </body>
    </html>
  );
}

TypeScript Types

Add type declarations:

typescript
// types/global.d.ts
declare global {
  interface Window {
    linguConfig?: {
      apiKey: string;
      autoOpen?: boolean;
      baseURL?: string;
    };
  }
}

export {};

Best Practices

  1. Use Environment Variables - Never hardcode API keys
  2. Load Lazily - Use lazyOnload strategy for non-critical third-party scripts
  3. Desktop & Mobile - The widget is responsive by default
  4. Server Components - Use next/script in server components, useEffect in client components

Powered by Lingu