### Install Dependencies with npm Source: https://github.com/next-nexus-org/next-nexus/blob/main/CONTRIBUTING.md This command installs all the necessary dependencies for the project. It is a standard Node.js package manager command. ```bash npm install ``` -------------------------------- ### Install next-nexus Package Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Installs the next-nexus package using npm, pnpm, or yarn. This is the first step for integrating next-nexus into your Next.js project. Ensure you have Node.js and a package manager installed. ```bash npm install next-nexus # or pnpm install next-nexus # or yarn add next-nexus ``` -------------------------------- ### Conventional Commits Specification Example Source: https://github.com/next-nexus-org/next-nexus/blob/main/CONTRIBUTING.md An example demonstrating the structure of a commit message adhering to the Conventional Commits specification. This format helps in automating changelog generation and semantic versioning. ```text feat(hooks): add useNexusAction hook for server actions ``` -------------------------------- ### NexusRuntime for Client-Side Initialization Source: https://context7.com/next-nexus-org/next-nexus/llms.txt NexusRuntime must be included once in the root layout to initialize the client-side cache and runtime environment. It is a crucial setup step for client-side functionalities within Next Nexus. ```typescript // app/layout.tsx import { NexusRuntime } from 'next-nexus/client'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` -------------------------------- ### Fetch Data in Next.js Server Component with Nexus Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Illustrates how to fetch data within a Next.js Server Component using the `nexus` function from `next-nexus/server`. This allows data to be fetched on the server and automatically hydrated for client-side rendering. The example shows how to retrieve product data and associated headers, then render them in the component. It also uses `withNexusHydrationBoundary` to wrap the Server Component. ```tsx // app/products/page.tsx (Full Example) import { withNexusHydrationBoundary } from 'next-nexus/server'; import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; import { ProductListClient } from './ProductListClient'; async function ProductsPage() { const { data: products, headers } = await nexus(productDefinition.list); const totalCount = headers.get('x-total-count'); return (

Product List (Server) {totalCount} items


{/* This client component will receive the hydrated data. */}
); } export default withNexusHydrationBoundary(ProductsPage); ``` -------------------------------- ### Use useNexusQuery in Next.js Client Component Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Explains how to utilize the `useNexusQuery` hook within a Next.js Client Component for seamless data fetching and rendering. This hook enables instant rendering with pre-hydrated data from the server, eliminating the need for an additional network request on initial load. The example demonstrates accessing fetched product data and headers, including cached headers like 'x-total-count'. ```tsx // app/products/ProductListClient.tsx 'use client'; import { useNexusQuery } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; export const ProductListClient = () => { // No network request is made on initial render! const { data, isPending, headers } = useNexusQuery(productDefinition.list); const products = data ?? []; const totalCount = headers.get('x-total-count'); // We can get the 'x-total-count' header from the cache because we set it in client.cachedHeaders in the definition. if (isPending && !data) return
Loading...
; return (

Product List (Client) {totalCount} items

); }; ``` -------------------------------- ### Define Reusable Type-Safe API Endpoints with Caching | TypeScript Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Creates reusable, type-safe API definitions with automatic caching configuration for both server and client environments using `createNexusDefinition`. It allows specifying base URL, timeout, retry logic, headers, and caching strategies for server and client components, along with methods like GET, POST, and data payloads. ```typescript import { createNexusDefinition } from 'next-nexus'; // Base definition with common settings const createDefinition = createNexusDefinition({ baseURL: 'https://api.example.com', timeout: 5, retry: { count: 1, delay: 1 }, headers: { 'x-app': 'my-app' }, }); // Product API definitions interface Product { id: string; name: string; price: number; } export const productDefinition = { list: createDefinition({ method: 'GET', endpoint: '/products', server: { cache: 'force-cache', tags: ['products'], revalidate: 1800, }, client: { tags: ['products'], revalidate: 300, cachedHeaders: ['x-total-count'], }, }), get: (id: string) => createDefinition({ method: 'GET', endpoint: `/products/${id}`, server: { tags: ['products', `product:${id}`], revalidate: 600 }, client: { tags: ['products', `product:${id}`], revalidate: 120 }, }), create: (newProduct: Omit) => createDefinition({ method: 'POST', endpoint: '/products', data: newProduct, interceptors: ['auth'], }), }; ``` -------------------------------- ### Run Tests with npm Source: https://github.com/next-nexus-org/next-nexus/blob/main/CONTRIBUTING.md This command executes the test suite for the project. It is crucial for ensuring the stability and correctness of the code. ```bash npm test ``` -------------------------------- ### Infinite Data Fetching with useNexusInfiniteQuery Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Demonstrates how to implement infinite scrolling or pagination in Client Components using the `useNexusInfiniteQuery` hook. This hook manages fetching subsequent pages based on a cursor or page parameter, providing loading and pagination states. ```tsx 'use client'; import { useNexusInfiniteQuery } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; export const InfiniteProductList = () => { const { data, isPending, hasNextPage, revalidateNext } = useNexusInfiniteQuery(productDefinition.infiniteList, { initialPageParam: null, // Start with no cursor for the first page getNextPageParam: lastPage => { // Assuming the API response includes a cursor for the next page. // e.g., { products: [...], nextCursor: 'some-cursor' } return lastPage.nextCursor ?? null; }, }); const allProducts = data?.pages.flatMap(page => page.products) ?? []; return (
{/* ... render allProducts */}
); }; ``` -------------------------------- ### Create Reusable API Definitions with Next Nexus Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.ko.md Demonstrates how to create a reusable API definition using `createNexusDefinition`. This includes setting base configurations like baseURL, timeout, retry logic, and default headers. It also shows how to implement request interceptors to add dynamic headers, such as authorization tokens. ```typescript // src/api/nexusDefinition.ts import { createNexusDefinition, interceptors } from 'next-nexus'; // 공통 설정을 위한 기본 definition export const createDefinition = createNexusDefinition({ baseURL: 'https://api.example.com', timeout: 5, // next-nexus의 definition의 모든 설정은 seconds 단위로 설정됩니다. retry: { count: 1, delay: 1 }, headers: { 'x-app': 'docs' }, }); interceptors.request.use('auth', async config => { const headers = new Headers(config.headers); const token = getToken(); // 사용자 인증을 위한 token을 가져오는 로직 headers.set('authorization', `Bearer ${token}`); return { ...config, headers }; }); ``` -------------------------------- ### Client-Side Data Creation with `useNexusMutation` Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Demonstrates how to use the `useNexusMutation` hook in a Client Component to create new data. It includes handling pending states, revalidating server and client tags on success, and resetting the form. ```tsx 'use client'; import { revalidateServerTags } from 'next-nexus'; import { useNexusMutation, revalidateClientTags } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; import { useState } from 'react'; export const AddProduct = () => { const [name, setName] = useState(''); const { mutate, isPending } = useNexusMutation(productDefinition.create, { onSuccess: async () => { // On success, revalidate the 'products' tag to update the list. await revalidateServerTags(['products']); // revalidateServerTags is a Server Action, so it can be used in Client Components. revalidateClientTags(['products']); setName(''); }, }); const handleSubmit = () => { if (!name) return; mutate({ name }); }; return (
setName(e.target.value)} disabled={isPending} />
); }; ``` -------------------------------- ### API Reference (Subpaths) Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Import modules from the correct subpath based on your environment (universal, server, or client). ```APIDOC ## API Reference by Subpath ### Universal (`next-nexus`) - **`createNexusDefinition`**: Creates an API `definition`. - **`interceptors`**: Adds logic to the global request/response lifecycle. - **`revalidateServerTags`**: Invalidates the Next.js data cache based on tags. ### Server Only (`next-nexus/server`) - **`nexus`**: Requests data in Server Components and registers it for hydration. - **`NexusRenderer`**: A component that enables rendering delegation. - **`NexusHydrationBoundary`**: Wraps a Server Component tree to collect hydration data. - **`withNexusHydrationBoundary`**: An HOC version for pages. ### Client Only (`next-nexus/client`) - **`useNexusQuery`**: A hook for querying data in Client Components. - **`useNexusInfiniteQuery`**: A hook for infinite scrolling and pagination. - **`useNexusMutation`**: A hook for CUD (Create, Update, Delete) operations. - **`useNexusAction` & `useNexusFormAction`**: Wrapper hooks for Server Actions. - **`NexusRuntime`**: Initializes the client runtime and cache. - **`nexusCache`**: A utility for direct access to the client cache. - **`revalidateClientTags`**: Invalidates the client cache based on tags. ### Errors (`next-nexus/errors`) - **`isNexusError`**: A type guard to check if an error is of type `NexusError`. ``` -------------------------------- ### Create API Definitions and Interceptors with Next Nexus Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Demonstrates how to use `createNexusDefinition` for reusable API endpoints and `interceptors` for handling requests and responses. This includes setting up base definitions with common settings like baseURL, timeout, retry, and headers, as well as defining custom interceptors for authentication. It also shows how to create specific endpoint definitions with options for server-side caching and client-side revalidation. ```typescript // src/api/nexusDefinition.ts import { createNexusDefinition, interceptors } from 'next-nexus'; // Base definition for common settings export const createDefinition = createNexusDefinition({ baseURL: 'https://api.example.com', timeout: 5, // All settings in next-nexus definitions are in seconds. retry: { count: 1, delay: 1 }, headers: { 'x-app': 'docs' }, }); interceptors.request.use('auth', async config => { const headers = new Headers(config.headers); const token = getToken(); // Logic to get user authentication token headers.set('authorization', `Bearer ${token}`); return { ...config, headers }; }); // src/api/productDefinition.ts import { createDefinition } from '@/api/nexusDefinition'; export interface Product { id: string; name: string; } export const productDefinition = { list: createDefinition({ method: 'GET', endpoint: '/products', // Cache options for server and client server: { cache: 'force-cache', // Maps to cache option tags: ['products'], // Maps to next.tags option revalidate: 1800, // Maps to next.revalidate option }, client: { tags: ['products'], revalidate: 300, cachedHeaders: ['x-total-count'], // Caches the header. **Only cache safe headers.** }, }), infiniteList: (cursor: string | null) => createDefinition({ method: 'GET', endpoint: cursor ? `/products?cursor=${cursor}` : '/products', client: { tags: ['products', `product:${cursor}`], revalidate: 300, }, }), create: (newProduct: { name: string }) => createDefinition({ method: 'POST', endpoint: '/products', data: newProduct, interceptors: ['auth'], // Uses the interceptor named "auth" defined in src/api/nexusDefinition.ts }), }; ``` -------------------------------- ### useNexusInfiniteQuery for Infinite Scroll and Pagination Source: https://context7.com/next-nexus-org/next-nexus/llms.txt This hook implements infinite scroll and pagination, managing page loading and state automatically. It supports prefetching and options for controlling page behavior. Dependencies include 'next-nexus/client' and the data definition. ```typescript 'use client'; import { useNexusInfiniteQuery } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; interface ProductPage { products: Product[]; nextCursor: string | null; } export function InfiniteProductList() { const { data, isPending, hasNextPage, revalidateNext, prefetchRef } = useNexusInfiniteQuery( (cursor) => productDefinition.infiniteList(cursor), { initialPageParam: null, getNextPageParam: (lastPage) => lastPage.nextCursor, keepPages: 5, prefetchNextOnNearViewport: { rootMargin: '100px', threshold: 0 }, } ); const allProducts = data?.pages.flatMap(page => page.products) ?? []; return (
    {allProducts.map(p =>
  • {p.name}
  • )}
); } ``` -------------------------------- ### useNexusQuery for Client-Side Data Fetching and Hydration Source: https://context7.com/next-nexus-org/next-nexus/llms.txt The useNexusQuery hook enables data querying in Client Components with automatic hydration from the server. It provides loading states, error handling, and revalidation options. Dependencies include 'next-nexus/client' and the data definition. ```typescript 'use client'; import { useNexusQuery } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; export function ProductListClient() { const { data, isPending, isError, error, headers, revalidate } = useNexusQuery( productDefinition.list, { enabled: true, keepStaleData: true, revalidateOnMount: true, revalidateOnWindowFocus: true, select: (products) => products.filter(p => p.price > 10), } ); const totalCount = headers?.get('x-total-count'); if (isPending && !data) return
Loading...
; if (isError) return
Error: {error?.message}
; return (

Products ({totalCount})

    {data?.map(p =>
  • {p.name}
  • )}
); } ``` -------------------------------- ### useNexusMutation: CRUD with Callbacks (TypeScript) Source: https://context7.com/next-nexus-org/next-nexus/llms.txt The useNexusMutation hook facilitates Create, Update, and Delete operations. It provides lifecycle callbacks (onStart, onSuccess, onError, onSettled) and handles state management automatically. It depends on 'next-nexus/client' and potentially 'next-nexus' for server tag revalidation. ```typescript 'use client'; import { useNexusMutation, revalidateClientTags } from 'next-nexus/client'; import { revalidateServerTags } from 'next-nexus'; import { productDefinition } from '@/api/productDefinition'; import { useState } from 'react'; export function AddProduct() { const [name, setName] = useState(''); const [price, setPrice] = useState(0); const { mutate, mutateAsync, isPending, isSuccess, isError, error, reset } = useNexusMutation(productDefinition.create, { onStart: (newProduct) => { console.log('Creating:', newProduct); return { timestamp: Date.now() }; }, onSuccess: async (data, variables, context) => { await revalidateServerTags(['products']); revalidateClientTags(['products']); setName(''); setPrice(0); }, onError: (error, variables, context) => { console.error('Failed:', error); }, onSettled: (data, error, variables, context) => { console.log('Completed at:', context?.timestamp); }, }); return (
setName(e.target.value)} /> setPrice(+e.target.value)} /> {isSuccess &&
Product added!
} {isError &&
Error: {error?.message}
}
); } ``` -------------------------------- ### Server-Side Data Fetching with nexus Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Fetch data within Server Components, leveraging automatic hydration and Next.js caching. ```APIDOC ## nexus() in Server Components ### Description Fetches data in Server Components with automatic hydration and Next.js cache integration. ### Method `nexus(definition, options?)` ### Parameters - **definition** (object) - The API definition created with `createNexusDefinition`. - **options** (object) - Optional. Configuration for the fetch request. - **next** (object) - Next.js fetch options (e.g., `cache`, `revalidate`). - **headers** (object) - Additional headers for the request. ### Request Example ```typescript import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; async function ProductsPage() { try { // Fetches product list using the defined API definition const { data: products, headers, status } = await nexus(productDefinition.list); const totalCount = headers.get('x-total-count'); return (

Products ({totalCount})

    {products.map(p => (
  • {p.name} - ${p.price}
  • ))}
); } catch (error) { // Handle potential errors during data fetching return
Error loading products
; } } ``` ### Response - **data** - The data returned from the API call, typed according to the `createNexusDefinition`. - **headers** - A `Headers` object containing the response headers. - **status** - The HTTP status code of the response. ``` -------------------------------- ### Cache Control Utilities Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Utilities for fine-grained cache control using tags and direct cache access. ```APIDOC ## Tag-Based Revalidation ### Description Invalidate server and client caches based on tags to ensure data consistency. ### Functions - **`revalidateServerTags(tags: string[])`** - **Description**: Revalidates the Next.js data cache on the server. - **Usage**: Can be called from Client Components as it's a Server Action. - **`revalidateClientTags(tags: string[])`** - **Description**: Revalidates the in-memory cache on the client. ## Direct Cache Access (`nexusCache`) ### Description A utility to directly get, set, or invalidate specific cache entries on the client for advanced use cases like optimistic updates. ### Methods - **`nexusCache.get(key: string)`**: Retrieves a cached value. - **`nexusCache.set(key: string, value: any)`**: Sets a cached value. - **`nexusCache.invalidate(key: string)`**: Invalidates a specific cache entry. ``` -------------------------------- ### Server Action Submission with `useNexusFormAction` Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Illustrates using `useNexusFormAction` to submit form data to a Server Action from a Client Component. It provides `pending` and `success` states for managing the form submission UI. ```tsx 'use client'; import { useNexusFormAction } from 'next-nexus/client'; const ProductForm = () => { const { formAction, isPending, isSuccess } = useNexusFormAction( async (formData: FormData) => { 'use server'; // ...server logic return { ok: true }; } ); return (
{isSuccess &&
Saved!
}
); }; ``` -------------------------------- ### Use `useNexusQuery` in Client Components with Next Nexus Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.ko.md Explains how to use the `useNexusQuery` hook in client components for data fetching. This hook leverages server-rendered, hydrated data initially, preventing network requests on the first render. It also shows how to access cached headers. ```tsx // app/products/ProductListClient.tsx 'use client'; import { useNexusQuery } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; export const ProductListClient = () => { // 초기 렌더링 시 네트워크 요청이 발생하지 않습니다! const { data, isPending, headers } = useNexusQuery(productDefinition.list); const products = data ?? []; const totalCount = headers.get('x-total-count'); // definition에서 client.cachedHeaders에 'x-total-count'를 설정했기 때문에 캐시에서 'x-total-count' 헤더를 가져올 수 있습니다. if (isPending && !data) return
로딩 중...
; return (

상품 목록 (클라이언트) {totalCount}개

    {products.map(p => (
  • {p.name}
  • ))}
); }; ``` -------------------------------- ### API Definitions with createNexusDefinition Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Defines reusable, type-safe API endpoints with configurable caching strategies for server and client. ```APIDOC ## POST /products ### Description Creates a new product. ### Method POST ### Endpoint /products #### Request Body - **newProduct** (object) - Required - The product data to create (excluding ID). - **name** (string) - Required - The name of the product. - **price** (number) - Required - The price of the product. ### Request Example ```json { "name": "Example Product", "price": 99.99 } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. #### Response Example ```json { "id": "prod_123", "name": "Example Product", "price": 99.99 } ``` ``` ```APIDOC ## GET /products ### Description Retrieves a list of products. ### Method GET ### Endpoint /products ### Response #### Success Response (200) - **products** (array) - A list of product objects. - **id** (string) - The unique identifier of the product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. - **headers** (object) - Response headers, potentially including 'x-total-count'. #### Response Example ```json { "data": [ { "id": "prod_123", "name": "Example Product 1", "price": 99.99 }, { "id": "prod_456", "name": "Example Product 2", "price": 149.50 } ], "headers": { "x-total-count": "2" } } ``` ``` ```APIDOC ## GET /products/{id} ### Description Retrieves a specific product by its ID. ### Method GET ### Endpoint /products/{id} #### Path Parameters - **id** (string) - Required - The unique identifier of the product to retrieve. ### Response #### Success Response (200) - **id** (string) - The unique identifier of the product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. #### Response Example ```json { "id": "prod_123", "name": "Example Product", "price": 99.99 } ``` ``` -------------------------------- ### Debugging (Dev Only) Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Enable detailed logging for request lifecycles and cache interactions during development. ```APIDOC ## Debugging (Development Only) ### Request Lifecycle Logs Request lifecycle logs (START/SUCCESS/ERROR/TIMEOUT) are printed in development by default. ### Detailed Cache Logs To enable detailed cache logs (HIT/HIT-STALE/MISS/SKIP/MATCH/SET/UPDATE/DELETE), add the following environment variable to your `.env.local` file: ```bash # .env.local NEXT_PUBLIC_NEXUS_DEBUG=true ``` ``` -------------------------------- ### Fetch Data in Server Components with Next Nexus Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.ko.md Shows how to fetch data within Next.js server components using the `nexus` function from `next-nexus/server`. This approach automatically hydrates the data, ensuring the client component receives pre-rendered content. It demonstrates accessing both data and headers from the API response. ```tsx // app/products/page.tsx (전체 예시) import { withNexusHydrationBoundary } from 'next-nexus/server'; import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; import { ProductListClient } from './ProductListClient'; async function ProductsPage() { const { data: products, headers } = await nexus(productDefinition.list); const totalCount = headers.get('x-total-count'); return (

상품 목록 (서버) {totalCount}개

    {products?.map(p => (
  • {p.name}
  • ))}

{/* 이 클라이언트 컴포넌트는 하이드레이션된 데이터를 받게 됩니다. */}
); } export default withNexusHydrationBoundary(ProductsPage); ``` -------------------------------- ### Define Specific API Endpoints with Caching Options Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.ko.md Illustrates defining specific API endpoints like 'list', 'infiniteList', and 'create' by extending a base definition. It shows how to configure server-side caching (`cache`, `tags`, `revalidate`) and client-side caching (`tags`, `revalidate`, `cachedHeaders`), including using interceptors for specific endpoints. ```typescript // src/api/productDefinition.ts import { createDefinition } from '@/api/nexusDefinition'; import type { Product, InfiniteProduct } from '@/types'; export const productDefinition = { list: createDefinition({ method: 'GET', endpoint: '/products', // 서버와 클라이언트를 위한 캐시 옵션 server: { cache: 'force-cache', // cache 옵션으로 매핑 tags: ['products'], // next.tags 옵션으로 매핑 revalidate: 1800, // next.revalidate 옵션으로 매핑 }, client: { tags: ['products'], revalidate: 300, cachedHeaders: ['x-total-count'], // 헤더를 캐시에 저장합니다. **안전한 헤더만 저장하세요.** }, }), infiniteList: (cursor: string | null) => createDefinition({ method: 'GET', endpoint: cursor ? `/products?cursor=${cursor}` : '/products', client: { tags: ['products', `product:${cursor}`], revalidate: 300, }, }), create: (newProduct: { name: string }) => createDefinition({ method: 'POST', endpoint: '/products', data: newProduct, interceptors: ['auth'], // src/api/nexusDefinition.ts에서 정의한 "auth" 이름을 가진 인터셉터를 사용합니다. }), }; ``` -------------------------------- ### useNexusAction: Server Action Wrapper (TypeScript) Source: https://context7.com/next-nexus-org/next-nexus/llms.txt The useNexusAction hook is a client-side wrapper for calling Server Actions. It provides pending states and lifecycle callbacks for the action execution. It depends on 'next-nexus/client'. ```typescript 'use client'; import { useNexusAction } from 'next-nexus/client'; async function createProductAction(name: string, price: number) { 'use server'; const product = await db.products.create({ data: { name, price } }); return product; } export function ProductForm() { const { execute, executeAsync, result, isPending, isSuccess, isError, error, reset } = useNexusAction(createProductAction, { onStart: async (name, price) => { console.log('Starting:', name, price); }, onSuccess: async (result, name, price) => { console.log('Created:', result); }, onError: async (error, name, price) => { console.error('Failed:', error); }, }); return ( ); } ``` -------------------------------- ### Initialize NexusRuntime in Root Layout Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Initializes the NexusRuntime in the root layout of a Next.js application. This component is essential for enabling the client-side cache and its functionalities, including sending client cache metadata to the server for optimized data fetching. It should be placed just before the closing tag. ```tsx // app/layout.tsx import { NexusRuntime } from 'next-nexus/client'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} {/* NexusRuntime initializes the client cache and its functionalities. */} ); } ``` -------------------------------- ### useNexusFormAction: Server Actions in Forms (TypeScript) Source: https://context7.com/next-nexus-org/next-nexus/llms.txt The useNexusFormAction hook simplifies integrating Server Actions with HTML forms. It automatically handles form state management, including pending states and lifecycle callbacks for the form submission. It depends on 'next-nexus/client'. ```typescript 'use client'; import { useNexusFormAction } from 'next-nexus/client'; async function submitProductAction(formData: FormData) { 'use server'; const name = formData.get('name') as string; const price = parseFloat(formData.get('price') as string); const product = await db.products.create({ data: { name, price } }); return product; } export function ProductForm() { const { formAction, isPending, isSuccess, isError, error, result, reset } = useNexusFormAction(submitProductAction, { onStart: async () => { console.log('Submitting form...'); }, onSuccess: async (result) => { console.log('Product created:', result); }, onError: async (error) => { console.error('Form error:', error); }, }); return (
{isSuccess &&
Product saved!
} {isError &&
Error: {error?.message}
}
); } ``` -------------------------------- ### Global Interceptors Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Configure global request and response interceptors for tasks like authentication, logging, or data transformation. ```APIDOC ## Interceptors ### Description Global request/response interceptors for adding authentication, logging, or data transformation. ### Usage ```typescript import { interceptors } from 'next-nexus'; // Add a request interceptor for authentication interceptors.request.use('auth', async (config) => { const headers = new Headers(config.headers); const token = await getAuthToken(); // Assume getAuthToken() is defined elsewhere headers.set('authorization', `Bearer ${token}`); return { ...config, headers }; }); // Add a response interceptor for error logging interceptors.response.use( 'errorLogger', async (response) => { if (!response.ok) { console.error('API Error:', response.status); } return response; }, async (error) => { console.error('Request failed:', error); throw error; } ); // Remove an interceptor interceptors.request.remove('auth'); ``` ``` -------------------------------- ### Extensibility - Interceptors Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Attaches custom logic to the request/response lifecycle. ```APIDOC ## Interceptors ### Description Attach custom logic to the request/response lifecycle. Useful for adding authentication headers, logging, or transforming data. ### Usage Import `interceptors` from `next-nexus` and use it to add custom logic. ### Example ```typescript import { interceptors } from 'next-nexus'; interceptors.push({ beforeRequest: async (options) => { // Add authentication header options.headers.set('Authorization', 'Bearer YOUR_TOKEN'); return options; }, afterResponse: async (response) => { // Log response or transform data console.log('Response received:', response); return response; } }); ``` ``` -------------------------------- ### Optimizing Server Rendering with NexusRenderer Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Illustrates the usage of `NexusRenderer` to optimize server rendering by allowing the client to take over rendering if data is already cached. This involves providing server and client versions of presentation components and the data definition. ```tsx // components/ProductListUI.tsx // Server presentational component import type { Product } from '@/api/productDefinition'; const ProductListUI = ({ data, title }: { data: Product[]; title: string }) => { return (

{title}

    {data.map(p => (
  • {p.name}
  • ))}
); }; export default ProductListUI; ``` ```tsx // components/client-ui/index.ts // Client entry point to re-export the server presentational component as a client one 'use client'; export { default as ProductListUIClient } from '@/components/ProductListUI'; // ... This pattern allows re-exporting more server presentational components as client ones. ``` ```tsx // app/page.tsx // Using NexusRenderer in a Server Component import { NexusRenderer } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; import ProductListUI from '@/components/ProductListUI'; // Import server presentational component import { ProductListUIClient } from '@/client-ui'; // Import client presentational component export default function Page() { return ( ); } ``` -------------------------------- ### withNexusHydrationBoundary HOC Source: https://context7.com/next-nexus-org/next-nexus/llms.txt A Higher-Order Component that enables hydration without requiring a separate layout file. ```APIDOC ## withNexusHydrationBoundary ### Description Higher-Order Component for enabling hydration without a separate layout file. ### Usage ```typescript import { withNexusHydrationBoundary } from 'next-nexus/server'; import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; import { ProductList } from './ProductList'; // Assuming ProductList component exists async function ProductsPage() { // Fetch data directly within the component const { data: products } = await nexus(productDefinition.list); return ; } // Wrap the component with the HOC export default withNexusHydrationBoundary(ProductsPage); ``` ``` -------------------------------- ### Enable Hydration using withNexusHydrationBoundary HOC Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md A convenient Higher-Order Component (HOC) approach to enable hydration for data fetching segments directly within a page.tsx file, avoiding the need for a separate layout.tsx. It wraps the page component, collecting server-fetched data for client hydration. Requires 'next-nexus/server'. ```tsx // app/products/page.tsx import { withNexusHydrationBoundary } from 'next-nexus/server'; import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; async function ProductsPage() { // Data fetched here is automatically collected for hydration. const { data: products } = await nexus(productDefinition.list); return ( // ... JSX using products ); } // Wrap the page with the HOC to enable hydration. export default withNexusHydrationBoundary(ProductsPage); ``` -------------------------------- ### Data Mutation Hooks Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Hooks for performing data operations like Create, Update, Delete (CUD) and calling Server Actions from Client Components. ```APIDOC ## useNexusMutation ### Description A hook for performing CUD (Create, Update, Delete) operations in Client Components. Ideal for when you need to affect data and update the UI. ### Method POST (typically, for CUD operations) ### Endpoint Client Component Hook ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body Depends on the `productDefinition.create` (or other mutation definition) provided. ### Request Example ```typescript // components/AddProduct.tsx 'use client'; import { revalidateServerTags } from 'next-nexus'; import { useNexusMutation, revalidateClientTags } from 'next-nexus/client'; import { productDefinition } from '@/api/productDefinition'; import { useState } from 'react'; export const AddProduct = () => { const [name, setName] = useState(''); const { mutate, isPending } = useNexusMutation(productDefinition.create, { onSuccess: async () => { await revalidateServerTags(['products']); revalidateClientTags(['products']); setName(''); }, }); const handleSubmit = () => { if (!name) return; mutate({ name }); }; return (
setName(e.target.value)} disabled={isPending} />
); }; ``` ### Response #### Success Response (200) Depends on the success response of the mutation. #### Response Example ```json { "message": "Product added successfully" } ``` ## useNexusAction & useNexusFormAction ### Description Convenient wrappers for calling Server Actions from Client Components, complete with `pending` states and lifecycle callbacks. ### Method POST (for Server Actions) ### Endpoint Client Component Hook ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body For `useNexusFormAction`, the form data is automatically handled. For `useNexusAction`, arguments are passed directly to the Server Action. ### Request Example ```typescript 'use client'; import { useNexusFormAction } from 'next-nexus/client'; const ProductForm = () => { const { formAction, isPending, isSuccess } = useNexusFormAction( async (formData: FormData) => { 'use server'; // ...server logic return { ok: true }; } ); return (
{isSuccess &&
Saved!
}
); }; ``` ### Response #### Success Response (200) Depends on the return value of the Server Action. #### Response Example ```json { "ok": true } ``` ``` -------------------------------- ### NexusHydrationBoundary Source: https://context7.com/next-nexus-org/next-nexus/llms.txt A boundary component to wrap Server Components, enabling automatic data hydration to client components. ```APIDOC ## NexusHydrationBoundary ### Description Wraps Server Components to enable automatic data hydration to client components. ### Usage ```typescript import { NexusHydrationBoundary } from 'next-nexus/server'; export default function ProductsLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ``` -------------------------------- ### Enable Hydration using NexusHydrationBoundary in Layout Source: https://github.com/next-nexus-org/next-nexus/blob/main/README.md Enables data hydration for server-fetched data within a specific segment by wrapping its children with NexusHydrationBoundary. This is typically used in a layout.tsx file to ensure data fetched in that layout or its child pages is available on the client, preventing duplicate requests and UI flicker. Requires 'next-nexus/server'. ```tsx // app/products/layout.tsx import { NexusHydrationBoundary } from 'next-nexus/server'; export default function ProductsLayout({ children, }: { children: React.ReactNode; }) { // Data fetched in this layout or its child pages will be collected. return {children}; } ``` -------------------------------- ### Hydrate Server Component Data with HOC | TypeScript Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Provides a Higher-Order Component (`withNexusHydrationBoundary`) for enabling data hydration from Server Components without requiring a separate layout file. This HOC simplifies the integration of hydration logic into existing page components. ```typescript import { withNexusHydrationBoundary } from 'next-nexus/server'; import { nexus } from 'next-nexus/server'; import { productDefinition } from '@/api/productDefinition'; import { ProductList } from './ProductList'; async function ProductsPage() { const { data: products } = await nexus(productDefinition.list); return ; } export default withNexusHydrationBoundary(ProductsPage); ``` -------------------------------- ### Implement Global Request/Response Interceptors | TypeScript Source: https://context7.com/next-nexus-org/next-nexus/llms.txt Configures global request and response interceptors using `interceptors` to add functionality like authentication, logging, or data transformation. It supports adding, removing, and using interceptors for both outgoing requests and incoming responses, including error handling. ```typescript import { interceptors } from 'next-nexus'; // Request interceptor for authentication interceptors.request.use('auth', async (config) => { const headers = new Headers(config.headers); const token = await getAuthToken(); headers.set('authorization', `Bearer ${token}`); return { ...config, headers }; }); // Response interceptor for error handling interceptors.response.use( 'errorLogger', async (response) => { if (!response.ok) { console.error('API Error:', response.status); } return response; }, async (error) => { console.error('Request failed:', error); throw error; } ); // Remove an interceptor interceptors.request.remove('auth'); ```