Skip to main content

IntrigLayout

The IntrigLayout is the foundational server-side layout component for integrating Intrig into Next.js applications. It wraps the IntrigProvider and manages server-side state hydration, providing seamless integration between server and client components.

Overview

IntrigLayout serves as the Next.js-specific entry point for all Intrig functionality, managing:

  • Server-side state hydration from headers
  • Global network state initialization for client components
  • Provider configuration with server-aware defaults
  • Integration with Next.js App Router patterns
  • Seamless transition from server-rendered content to client-side interactivity

Props

IntrigLayoutProps

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeYes-Child components that will have access to Intrig context
configsDefaultConfigsNoundefinedConfiguration object for API sources (server-side compatible)

DefaultConfigs

The DefaultConfigs interface extends Axios's CreateAxiosDefaults with additional Intrig-specific options:

PropertyTypeDescription
baseURLstringBase URL for API requests
timeoutnumberRequest timeout in milliseconds
headersRecord<string, string>Default headers for requests
debounceDelaynumberDelay in milliseconds for debouncing requests
requestInterceptor(config: InternalAxiosRequestConfig) => Promise<InternalAxiosRequestConfig>Custom request interceptor function
responseInterceptor(config: AxiosResponse<any>) => Promise<AxiosResponse<any>>Custom response interceptor function

Basic Usage

App Router Layout Setup

// app/layout.tsx
import { IntrigLayout } from '@intrig/next';
import { ReactNode } from 'react';

interface RootLayoutProps {
children: ReactNode;
}

export default function RootLayout({ children }: RootLayoutProps) {
return (
<html lang="en">
<body>
<IntrigLayout
configs={{
baseURL: process.env.NEXT_PUBLIC_API_URL,
timeout: 5000,
headers: {
'Content-Type': 'application/json',
},
}}
>
{children}
</IntrigLayout>
</body>
</html>
);
}

Environment-Based Configuration

// app/layout.tsx
import { IntrigLayout } from '@intrig/next';

export default function RootLayout({ children }: { children: React.ReactNode }) {
const configs = {
baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api',
timeout: parseInt(process.env.NEXT_PUBLIC_API_TIMEOUT || '5000'),
headers: {
'Content-Type': 'application/json',
'X-App-Version': process.env.NEXT_PUBLIC_APP_VERSION || '1.0.0',
},
};

return (
<html lang="en">
<body>
<IntrigLayout configs={configs}>
{children}
</IntrigLayout>
</body>
</html>
);
}

Conditional Configuration

// app/layout.tsx
import { IntrigLayout } from '@intrig/next';

export default function RootLayout({ children }: { children: React.ReactNode }) {
const isDevelopment = process.env.NODE_ENV === 'development';

const configs = {
baseURL: isDevelopment
? 'http://localhost:8080/api'
: process.env.NEXT_PUBLIC_API_URL,
timeout: isDevelopment ? 10000 : 5000,
headers: {
'Content-Type': 'application/json',
...(isDevelopment && { 'X-Debug': 'true' }),
},
};

return (
<html lang="en">
<body>
<IntrigLayout configs={configs}>
{children}
</IntrigLayout>
</body>
</html>
);
}

Server-Side Features

Hydration Management

IntrigLayout automatically handles server-side state hydration:

// The layout reads hydrated responses from headers
// and passes them to IntrigProvider as initState
async function IntrigLayout({ children, configs }) {
let headersData = await headers();
let hydratedResponsesStr = headersData.get('INTRIG_HYDRATED');
let hydratedResponses = hydratedResponsesStr ? JSON.parse(hydratedResponsesStr) : {};

return (
<IntrigProvider configs={configs} initState={hydratedResponses}>
{children}
</IntrigProvider>
);
}

This means server-side function results are automatically available to client components without additional fetching.

Integration with Middleware

IntrigLayout works seamlessly with Intrig middleware for header injection:

// middleware.ts
import { createIntrigMiddleware } from '@intrig/next';

export const middleware = createIntrigMiddleware(async (request) => {
return {
'Authorization': `Bearer ${await getAuthToken()}`,
'X-User-ID': request.headers.get('x-user-id') || '',
};
});

// app/layout.tsx - configs will automatically use injected headers
<IntrigLayout configs={{ baseURL: process.env.NEXT_PUBLIC_API_URL }}>
{children}
</IntrigLayout>

Key Differences from IntrigProvider

FeatureIntrigProvider (React)IntrigLayout (Next.js)
ContextClient-side onlyServer-aware, client-ready
State HydrationManual initializationAutomatic from headers
ConfigurationMultiple API sources supportedSingle configuration object
Middleware IntegrationNo built-in supportSeamless header injection
Server ComponentsN/ACompatible with SSR/SSG

Best Practices

1. Environment Configuration

// Use environment variables for different deployment stages
const configs = {
baseURL: process.env.NEXT_PUBLIC_API_URL,
timeout: parseInt(process.env.NEXT_PUBLIC_API_TIMEOUT || '5000'),
};

2. Layout Placement

// Place IntrigLayout in your root layout for app-wide availability
// app/layout.tsx
export default function RootLayout({ children }) {
return (
<IntrigLayout configs={...}>
{children}
</IntrigLayout>
);
}

3. Server Component Compatibility

// IntrigLayout is server-compatible and handles hydration automatically
// No additional setup needed for server components using Intrig functions

4. Error Boundary Integration

// app/layout.tsx
import { IntrigLayout } from '@intrig/next';
import ErrorBoundary from './components/ErrorBoundary';

export default function RootLayout({ children }) {
return (
<IntrigLayout configs={configs}>
<ErrorBoundary>
{children}
</ErrorBoundary>
</IntrigLayout>
);
}

Advanced Usage

Dynamic Configuration

// app/layout.tsx with dynamic config based on headers
import { headers } from 'next/headers';
import { IntrigLayout } from '@intrig/next';

export default async function RootLayout({ children }) {
const headersList = await headers();
const userRegion = headersList.get('x-user-region') || 'us';

const configs = {
baseURL: `https://api-${userRegion}.example.com`,
timeout: 5000,
headers: {
'X-Region': userRegion,
},
};

return (
<IntrigLayout configs={configs}>
{children}
</IntrigLayout>
);
}

Integration with Authentication

// app/layout.tsx
import { IntrigLayout } from '@intrig/next';
import { cookies } from 'next/headers';

export default async function RootLayout({ children }) {
const cookieStore = await cookies();
const authToken = cookieStore.get('auth-token')?.value;

const configs = {
baseURL: process.env.NEXT_PUBLIC_API_URL,
headers: {
'Content-Type': 'application/json',
...(authToken && { 'Authorization': `Bearer ${authToken}` }),
},
};

return (
<IntrigLayout configs={configs}>
{children}
</IntrigLayout>
);
}