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_abc123def456WARNING
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:
| Strategy | When to Use |
|---|---|
beforeInteractive | Config script - needs to be ready before widget loads |
lazyOnload | Widget script - load after page is fully interactive |
afterInteractive | Alternative - 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
- Use Environment Variables - Never hardcode API keys
- Load Lazily - Use
lazyOnloadstrategy for non-critical third-party scripts - Desktop & Mobile - The widget is responsive by default
- Server Components - Use
next/scriptin server components,useEffectin client components