UNPKG

@dotcms/react

Version:

Official React Components library to render a dotCMS page.

807 lines (601 loc) 34.5 kB
# dotCMS React SDK The `@dotcms/react` SDK is the DotCMS official React library. It empowers React developers to build powerful, editable websites and applications in no time. ## Table of Contents - [Prerequisites & Setup](#prerequisites--setup) - [Get a dotCMS Environment](#get-a-dotcms-environment) - [Create a dotCMS API Key](#create-a-dotcms-api-key) - [Configure The Universal Visual Editor App](#configure-the-universal-visual-editor-app) - [Installation](#installation) - [dotCMS Client Configuration](#dotcms-client-configuration) - [Proxy Configuration for Static Assets](#proxy-configuration-for-static-assets) - [Quickstart: Render a Page with dotCMS](#quickstart-render-a-page-with-dotcms) - [Example Project](#example-project-) - [SDK Reference](#sdk-reference) - [DotCMSLayoutBody](#dotcmslayoutbody) - [DotCMSShow](#dotcmsshow) - [DotCMSBlockEditorRenderer](#dotcmsblockeditorrenderer) - [DotCMSEditableText](#dotcmseditabletext) - [useEditableDotCMSPage](#useeditabledotcmspage) - [useDotCMSShowWhen](#usedotcmsshowwhen) - [useAISearch](#useaisearch) - [Troubleshooting](#troubleshooting) - [Common Issues & Solutions](#common-issues--solutions) - [Debugging Tips](#debugging-tips) - [Version Compatibility](#version-compatibility) - [Still Having Issues?](#still-having-issues) - [Migration from Alpha to 1.0.X](./MIGRATION.md) - [Support](#support) - [Contributing](#contributing) - [Licensing](#licensing) ## Prerequisites & Setup ### Get a dotCMS Environment #### Version Compatibility - **Recommended**: dotCMS Evergreen - **Minimum**: dotCMS v25.05 - **Best Experience**: Latest Evergreen release #### Environment Setup **For Production Use:** - ☁️ [Cloud hosting options](https://www.dotcms.com/pricing) - managed solutions with SLA - 🛠️ [Self-hosted options](https://dev.dotcms.com/docs/current-releases) - deploy on your infrastructure **For Testing & Development:** - 🧑🏻‍💻 [dotCMS demo site](https://demo.dotcms.com/dotAdmin/#/public/login) - perfect for trying out the SDK - 📘 [Learn how to use the demo site](https://dev.dotcms.com/docs/demo-site) - 📝 Read-only access, ideal for building proof-of-concepts **For Local Development:** - 🐳 [Docker setup guide](https://github.com/dotCMS/core/tree/main/docker/docker-compose-examples/single-node-demo-site) - 💻 [Local installation guide](https://dev.dotcms.com/docs/quick-start-guide) ### Configure The Universal Visual Editor App For a step-by-step guide on setting up the Universal Visual Editor, check out our [easy-to-follow instructions](https://dev.dotcms.com/docs/uve-headless-config) and get started in no time! ### Create a dotCMS API Key > [!TIP] > Make sure your API Token has read-only permissions for Pages, Folders, Assets, and Content. Using a key with minimal permissions follows security best practices. This integration requires an API Key with read-only permissions for security best practices: 1. Go to the **dotCMS admin panel**. 2. Click on **System** > **Users**. 3. Select the user you want to create the API Key for. 4. Go to **API Access Key** and generate a new key. For detailed instructions, please refer to the [dotCMS API Documentation - Read-only token](https://dev.dotcms.com/docs/rest-api-authentication#ReadOnlyToken). ### Install Dependencies ```bash npm install @dotcms/react@latest ``` This will automatically install the required dependencies: - `@dotcms/uve`: Enables interaction with the [Universal Visual Editor](https://dev.dotcms.com/docs/uve-headless-config) for real-time content editing - `@dotcms/client`: Provides the core client functionality for fetching and managing dotCMS data ### dotCMS Client Configuration ```typescript import { createDotCMSClient } from '@dotcms/client'; type DotCMSClient = ReturnType<typeof createDotCMSClient>; export const dotCMSClient: DotCMSClient = createDotCMSClient({ dotcmsUrl: 'https://your-dotcms-instance.com', authToken: 'your-auth-token', // Optional for public content siteId: 'your-site-id' // Optional site identifier/name }); ``` ### Proxy Configuration for Static Assets Configure a proxy to leverage the powerful dotCMS image API, allowing you to resize and serve optimized images efficiently. This enhances application performance and improves user experience, making it a strategic enhancement for your project. #### 1. Configure Vite ```ts // vite.config.ts import { defineConfig } from 'vite'; import dns from 'node:dns'; dns.setDefaultResultOrder('verbatim'); export default defineConfig({ server: { proxy: { '/dA': { target: 'your-dotcms-instance.com', changeOrigin: true } } } }); ``` Learn more about Vite configuration [here](https://vitejs.dev/config/). #### 2. Usage in Components Once configured, image URLs in your components will automatically be proxied to your dotCMS instance: >📚 Learn more about [Image Resizing and Processing in dotCMS with React](https://www.dotcms.com/blog/image-resizing-and-processing-in-dotcms-with-angular-and-nextjs). ```typescript // /components/my-dotcms-image.tsx import type { DotCMSBasicContentlet } from '@dotcms/types'; export const MyDotCMSImageComponent = ({ inode, title }: DotCMSBasicContentlet) => { return <img src={`/dA/${inode}`} alt={title} />; } ``` ## Quickstart: Render a Page with dotCMS The following example demonstrates how to quickly set up a basic dotCMS page renderer in your React application. This example shows how to: - Create a standalone component that renders a dotCMS page - Set up dynamic component loading for different content types - Handle both regular page viewing and editor mode - Subscribe to real-time page updates when in the Universal Visual Editor ```tsx // /src/app/pages/dotcms-page.tsx import { useState, useEffect } from 'react'; import { DotCMSLayoutBody, useEditableDotCMSPage } from '@dotcms/react'; import { DotCMSPageResponse } from '@dotcms/types'; import { dotCMSClient } from './dotCMSClient'; import { BlogComponent } from './BlogComponent'; import { ProductComponent } from './ProductComponent'; const COMPONENTS_MAP = { Blog: BlogComponent, Product: ProductComponent }; const MyPage = () => { const [response, setResponse] = useState<DotCMSPageResponse | null>(null); const { pageAsset } = useEditableDotCMSPage(response); useEffect(() => { dotCMSClient.page.get('/').then((response) => { setResponse(response); }); }, []); return <DotCMSLayoutBody page={pageAsset} components={COMPONENTS_MAP} mode="development" />; }; export default MyPage; ``` ### Example Project 🚀 Looking to get started quickly? We've got you covered! Our [Next.js starter project](https://github.com/dotCMS/core/tree/main/examples/nextjs) is the perfect launchpad for your dotCMS + Next.js journey. This production-ready template demonstrates everything you need: 📦 Fetch and render dotCMS pages with best practices 🧩 Register and manage components for different content types 🔍 Listing pages with search functionality 📝 Detail pages for blogs 📈 Image and assets optimization for better performance ✨ Enable seamless editing via the Universal Visual Editor (UVE) ⚡️ Leverage React's hooks and state management for optimal performance > [!TIP] > This starter project is more than just an example, it follows all our best practices. We highly recommend using it as the base for your next dotCMS + Next.js project! ## SDK Reference All components and hooks should be imported from `@dotcms/react`: ### DotCMSLayoutBody `DotCMSLayoutBody` is a component used to render the layout for a DotCMS page, supporting both production and development modes. | Input | Type | Required | Default | Description | | ------------ | ------------------------ | -------- | -------------- | ---------------------------------------------- | | `page` | `DotCMSPageAsset` | ✅ | - | The page asset containing the layout to render | | `components` | `DotCMSPageComponent` | ✅ | `{}` | [Map of content type → React component](#component-mapping) | | `mode` | `DotCMSPageRendererMode` | ❌ | `’production’` | [Rendering mode (‘production’ or ‘development’)](#layout-body-modes) | | `slots` | `Record<string, ReactNode>` | ❌ | `{}` | Pre-rendered server component nodes keyed by contentlet identifier. See [`buildSlots`](#buildslots). | #### Next.js App Router `DotCMSLayoutBody` requires a `"use client"` parent because `components` is a map of React component functions, which React cannot serialize across the server→client boundary. The recommended pattern is to fetch data in the server page and pass the plain result to a client wrapper: ```tsx // page.tsx — server component, fetches data only export default async function Page() { const pageContent = await getDotCMSPage(path); return <PageView pageContent={pageContent} />; } ``` ```tsx // PageView.tsx — "use client", owns components and renders layout ‘use client’; export function PageView({ pageContent }) { const { pageAsset } = useEditableDotCMSPage(pageContent); return <DotCMSLayoutBody page={pageAsset} components={pageComponents} />; } ``` #### Usage ```tsx import type { DotCMSPageAsset } from ‘@dotcms/types’; import { DotCMSLayoutBody } from ‘@dotcms/react’; import { MyBlogCard } from ‘./MyBlogCard’; import { DotCMSProductComponent } from ‘./DotCMSProductComponent’; const COMPONENTS_MAP = { Blog: MyBlogCard, Product: DotCMSProductComponent }; const MyPage = ({ pageAsset }: DotCMSPageResponse) => { return <DotCMSLayoutBody page={pageAsset} components={COMPONENTS_MAP} />; }; ``` #### buildSlots Use `buildSlots` when you have Next.js async server components that need to fetch their own data. Since async server components can’t be called from inside a client component tree, pre-render them on the server and pass the result into the layout via `slots`: ```tsx import { buildSlots, DotCMSLayoutBody } from ‘@dotcms/react’; // BlogListContainer is an async server component that fetches its own data const slots = buildSlots(pageContent.pageAsset.containers, { BlogList: BlogListContainer, }); <DotCMSLayoutBody page={pageAsset} components={pageComponents} slots={slots} /> ``` The layout renders the pre-rendered slot node for a contentlet if one exists, otherwise falls back to the matching entry in `components`. #### Layout Body Modes - `production`: Performance-optimized mode that only renders content with explicitly mapped components, leaving unmapped content empty. - `development`: Debug-friendly mode that renders default components for unmapped content types and provides visual indicators and console logs for empty containers and missing mappings. #### Component Mapping The `DotCMSLayoutBody` component uses a `components` prop to map content type variable names to React components. This allows you to render different components for different content types. Example: ```typescript const DYNAMIC_COMPONENTS = { Blog: MyBlogCard, Product: DotCMSProductComponent }; ``` - Keys (e.g., `Blog`, `Product`): Match your [content type variable names](https://dev.dotcms.com/docs/content-types#VariableNames) in dotCMS - Values: Dynamic imports of your React components that render each content type - Supports lazy loading through dynamic imports - Components must be standalone or declared in a module > [!TIP] > Always use the exact content type variable name from dotCMS as the key. You can find this in the Content Types section of your dotCMS admin panel. ### DotCMSEditableText `DotCMSEditableText` is a component for inline editing of text fields in dotCMS, supporting plain text, text area, and WYSIWYG fields. | Input | Type | Required | Description | | ------------ | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `contentlet` | `T extends DotCMSBasicContentlet` | ✅ | The contentlet containing the editable field | | `fieldName` | `keyof T` | ✅ | Name of the field to edit, which must be a valid key of the contentlet type `T` | | `mode` | `'plain' \| 'full'` | ❌ | `plain` (default): Support text editing. Does not show style controls. <br/> `full`: Enables a bubble menu with style options. This mode only works with [`WYSIWYG` fields](https://dev.dotcms.com/docs/the-wysiwyg-field). | | `format` | `'text' \| 'html'` | ❌ | `text` (default): Renders HTML tags as plain text <br/> `html`: Interprets and renders HTML markup | #### Usage ```tsx import type { DotCMSBasicContentlet } from '@dotcms/types'; import { DotCMSEditableText } from '@dotcms/react'; const MyBannerComponent = ({ contentlet }: { contentlet: DotCMSBasicContentlet }) => { const { inode, title, link } = contentlet; return ( <div className="flex overflow-hidden relative justify-center items-center w-full h-96 bg-gray-200"> <img className="object-cover w-full" src={`/dA/${inode}`} alt={title} /> <div className="flex absolute inset-0 flex-col justify-center items-center p-4 text-center text-white"> <h2 className="mb-2 text-6xl font-bold text-shadow"> <DotCMSEditableText fieldName="title" contentlet={contentlet} /> </h2> <a href={link} className="p-4 text-xl bg-red-400 rounded-sm transition duration-300 hover:bg-red-500"> See more </a> </div> </div> ); }; export default MyBannerComponent; ``` #### Editor Integration - Detects UVE edit mode and enables inline TinyMCE editing - Triggers a `Save` [workflow action](https://dev.dotcms.com/docs/workflows) on blur without needing full content dialog. #### DotCMSBlockEditorRenderer `DotCMSBlockEditorRenderer` is a component for rendering [Block Editor](https://dev.dotcms.com/docs/block-editor) content from dotCMS with support for custom block renderers. | Input | Type | Required | Default | Description | | ----------------- | -------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------- | | `blocks` | `BlockEditorContent` | ✅ | - | The [Block Editor](https://dev.dotcms.com/docs/block-editor) content to render | | `customRenderers` | `CustomRenderers` | ❌ | - | Custom rendering functions for specific [block types](https://dev.dotcms.com/docs/block-editor#BlockTypes) | | `className` | `string` | ❌ | - | CSS class to apply to the container | | `style` | `CSSProperties` | ❌ | - | Inline styles for the container | | `isDevMode` | `boolean` | ❌ | `false` | When `true`, shows a visible error message if the `blocks` data is invalid. When `false` (default), invalid blocks render nothing silently. | #### Usage ```tsx import type { DotCMSBasicContentlet } from '@dotcms/types'; import { DotCMSBlockEditorRenderer } from '@dotcms/react'; import { MyCustomBannerBlock } from './MyCustomBannerBlock'; import { MyCustomH1 } from './MyCustomH1'; const CUSTOM_RENDERERS = { customBannerBlock: MyCustomBannerBlock, h1: MyCustomH1 }; const DetailPage = ({ contentlet }: { contentlet: DotCMSBasicContentlet }) => { return ( <DotCMSBlockEditorRenderer blocks={contentlet['YOUR_BLOCK_EDITOR_FIELD']} customRenderers={CUSTOM_RENDERERS} /> ); }; ``` #### Next.js Server Components `DotCMSBlockEditorRenderer` can be used directly in a Next.js server component — it has no hooks or browser dependencies: ```tsx // app/article/page.tsx — server component import { DotCMSBlockEditorRenderer } from '@dotcms/react'; export default async function ArticlePage() { const { pageAsset } = await getDotCMSPage('/article'); const blocks = pageAsset.containers['...'].contentlets[0].blockEditorContent; return ( <DotCMSBlockEditorRenderer blocks={blocks} isDevMode={process.env.NODE_ENV === 'development'} /> ); } ``` #### Recommendations - Should not be used with [`DotCMSEditableText`](#dotcmseditabletext) - Take into account the CSS cascade can affect the look and feel of your blocks. - `DotCMSBlockEditorRenderer` only works with [Block Editor fields](https://dev.dotcms.com/docs/block-editor). For other fields, use [`DotCMSEditableText`](#dotcmseditabletext). 📘 For advanced examples, customization options, and best practices, refer to the [DotCMSBlockEditorRenderer README](https://github.com/dotCMS/core/tree/master/core-web/libs/sdk/react/src/lib/components/DotCMSBlockEditorRenderer). #### DotCMSShow `DotCMSShow` is a component for conditionally rendering content based on the current UVE mode. Useful for mode-based behaviors outside of render logic. | Input | Type | Required | Description | | ---------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `children` | `ReactNode` | ✅ | Content to be conditionally rendered | | `when` | `UVE_MODE` | ✅ | The `UVE` mode when content should be displayed: <br/> `UVE_MODE.EDIT`: Only visible in edit mode <br/> `UVE_MODE.PREVIEW`: Only visible in preview mode <br/> `UVE_MODE.PUBLISHED`: Only visible in published mode | #### Usage ```tsx import { UVE_MODE } from '@dotcms/types'; import { DotCMSShow } from '@dotcms/react'; const MyComponent = () => { return ( <DotCMSShow when={UVE_MODE.EDIT}> <div>This will only render in UVE EDIT mode</div> </DotCMSShow> ); }; ``` 📚 Learn more about the `UVE_MODE` enum in the [dotCMS UVE Package Documentation](https://dev.dotcms.com/docs/uve). ### useEditableDotCMSPage `useEditableDotCMSPage` is a hook that enables real-time page updates when using the Universal Visual Editor. | Param | Type | Required | Description | | -------------- | -------------------- | -------- | --------------------------------------------- | | `pageResponse` | `DotCMSPageResponse` | ✅ | The page data object from `client.page.get()` | #### Service Lifecycle & Operations When you use the hook, it: 1. Initializes the UVE with your page data 2. Sets up communication channels with the editor 3. Tracks content changes in real-time 4. Updates your page automatically when: - Content is edited inline - Blocks are added or removed - Layout changes are made - Components are moved 5. Cleans up all listeners and connections on destroy #### Usage ```tsx 'use client'; import { useEditableDotCMSPage, DotCMSLayoutBody } from '@dotcms/react'; import type { DotCMSPageResponse } from '@dotcms/types'; const COMPONENTS_MAP = { Blog: BlogComponent, Product: ProductComponent }; export function DotCMSPage({ pageResponse }: { pageResponse: DotCMSPageResponse }) { const { pageAsset } = useEditableDotCMSPage(pageResponse); return <DotCMSLayoutBody pageAsset={pageAsset} components={COMPONENTS_MAP} />; } ``` #### useDotCMSShowWhen `useDotCMSShowWhen` is a hook for conditionally showing content based on the current UVE mode. Useful for mode-based behaviors outside of render logic. | Param | Type | Required | Description | | ------ | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `when` | `UVE_MODE` | ✅ | The `UVE` mode when content should be displayed: <br/> `UVE_MODE.EDIT`: Only visible in edit mode <br/> `UVE_MODE.PREVIEW`: Only visible in preview mode <br/> `UVE_MODE.PUBLISHED`: Only visible in published mode | #### Usage ```tsx import { UVE_MODE } from '@dotcms/types'; import { useDotCMSShowWhen } from '@dotcms/react'; const MyEditButton = () => { const isEditMode = useDotCMSShowWhen(UVE_MODE.EDIT); // returns a boolean if (isEditMode) { return <button>Edit</button>; } return null; }; ``` ### useAISearch `useAISearch` is a hook that enables AI-powered semantic search capabilities for your dotCMS content. It manages search state, handles API calls, and provides real-time status updates. | Param | Type | Required | Description | | ----------- | ----------------------- | -------- | ------------------------------------------------------------------------------ | | `client` | `DotCMSClient` | ✅ | The dotCMS client instance created with `createDotCMSClient()` | | `indexName` | `string` | ✅ | Name of the AI search index to query | | `params` | `DotCMSAISearchParams` | ✅ | Search configuration including query params (limit, offset) and AI config | #### Return Value The hook returns an object with the following properties: | Property | Type | Description | | ---------- | ---------------------------------------- | -------------------------------------------------------------- | | `response` | `DotCMSAISearchResponse<T> \| null` | Full search response including metadata and results | | `results` | `DotCMSAISearchContentletData<T>[] \| undefined` | Array of search results with match scores | | `status` | `DotCMSEntityStatus` | Current state: `IDLE`, `LOADING`, `SUCCESS`, or `ERROR` | | `search` | `(prompt: string) => Promise<void>` | Function to execute a search with a text prompt | | `reset` | `() => void` | Function to reset search state to idle | #### Usage ```tsx 'use client'; import { useState } from 'react'; import { useAISearch } from '@dotcms/react'; import type { DotCMSBasicContentlet } from '@dotcms/types'; import { dotCMSClient } from '@/lib/dotCMSClient'; interface BlogPost extends DotCMSBasicContentlet { body: string; author: string; } const AISearchComponent = () => { const [searchQuery, setSearchQuery] = useState(''); const { results, status, search, reset } = useAISearch<BlogPost>({ client: dotCMSClient, indexName: 'blog-search-index', params: { query: { limit: 10, offset: 0, contentType: 'Blog' }, config: { threshold: 0.5, responseLength: 1024 } } }); const handleSearch = async () => { if (searchQuery.trim()) { await search(searchQuery); } }; const handleReset = () => { setSearchQuery(''); reset(); }; return ( <div className="search-container"> <div className="search-bar"> <input type="text" value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} placeholder="Search with AI..." /> <button onClick={handleSearch} disabled={status.state === 'LOADING'}> {status.state === 'LOADING' ? 'Searching...' : 'Search'} </button> <button onClick={handleReset}>Reset</button> </div> {status.state === 'ERROR' && ( <div className="error"> Error: {status.error.message} </div> )} {status.state === 'SUCCESS' && results && ( <div className="results"> <h2>Found {results.length} results</h2> {results.map((result) => ( <article key={result.identifier}> <h3>{result.title}</h3> <p>Author: {result.author}</p> {result.matches?.map((match, idx) => ( <div key={idx} className="match"> <span>Relevance: {match.distance.toFixed(2)}</span> <p>{match.extractedText}</p> </div> ))} </article> ))} </div> )} </div> ); }; export default AISearchComponent; ``` #### Features - **Automatic State Management**: Handles loading, success, error, and idle states - **Type-Safe Results**: Generic typing ensures type safety for your content types - **Search Validation**: Automatically validates and trims search prompts - **Configurable Parameters**: Support for pagination, thresholds, and AI configuration - **Error Handling**: Provides detailed error information through status state - **Reset Capability**: Easy state reset for clearing search results #### Configuration Options **Query Parameters (`params.query`):** - `limit`: Maximum number of results (default: 1000) - `offset`: Number of results to skip (default: 0) - `siteId`: Filter by specific site - `contentType`: Filter by content type - `languageId`: Filter by language **AI Configuration (`params.config`):** - `threshold`: Minimum similarity score (default: 0.5) - `distanceFunction`: Vector distance algorithm (default: cosine) - `responseLength`: Maximum response text length (default: 1024) ## Troubleshooting ### Common Issues & Solutions #### Universal Visual Editor (UVE) 1. **UVE Not Loading**: Page loads but UVE controls are not visible - **Possible Causes**: - Incorrect UVE configuration - Missing API token permissions - Missing the `DotCMSEditablePageService` call to enable UVE. - **Solutions**: - Verify UVE app configuration in dotCMS admin - Check API token has edit permissions - Ensure `dotcmsUrl` matches your instance URL exactly #### Missing Content 1. **Components Not Rendering**: Empty spaces where content should appear - **Possible Causes**: - Missing component mappings - Incorrect content type variable names - **Solutions**: - Check component registration in `components` prop - Verify content type variable names match exactly - Enable `development` mode for detailed logging 2. **Asset Loading Issues**: Images or files not loading - **Possible Causes**: - Proxy configuration issues - CORS restrictions - **Solutions**: - Verify proxy settings in `vite.config.ts` - Check network tab for CORS errors - Ensure `/dA` path is properly configured #### Development Setup 1. **Build Errors**: `npm install` fails - **Solutions**: - Clear npm cache: `npm cache clean --force` - Delete `node_modules` and reinstall - Verify Node.js version compatibility 2. **Runtime Errors**: Console errors about missing imports or components not rendering - **Solutions**: - Check all imports are from `@dotcms/react` - Verify all peer dependencies are installed - Update to latest compatible versions #### Next.js App Router Integration 1. **Server Component Errors**: Errors about React class components in Server Components - **Possible Causes**: - Using dotCMS components directly in Server Components - Missing 'use client' directive - Incorrect data fetching pattern - **Solutions**: 1. Split your code into Server and Client Components: ```tsx // app/page.tsx (Server Component) import { DotCMSPage } from '@/components/DotCMSPage'; import { dotCMSClient } from '@/lib/dotCMSClient'; export default async function Page() { const pageResponse = await dotCMSClient.page.get('/index'); return <DotCMSPage pageResponse={pageResponse} />; } ``` ```tsx // components/DotCMSPage.tsx (Client Component) 'use client'; import { useEditableDotCMSPage, DotCMSLayoutBody } from '@dotcms/react'; import type { DotCMSPageResponse } from '@dotcms/types'; const COMPONENTS_MAP = { Blog: BlogComponent, Product: ProductComponent }; export function DotCMSPage({ pageResponse }: { pageResponse: DotCMSPageResponse }) { const { pageAsset } = useEditableDotCMSPage(pageResponse); return <DotCMSLayoutBody pageAsset={pageAsset} components={COMPONENTS_MAP} />; } ``` 2. Always fetch data in Server Components for better performance 3. Use Client Components only for rendering dotCMS interactive components ### Debugging Tips 1. **Enable Development Mode** ```typescript <dotcms-layout-body [page]="pageAsset()" [components]="components()" mode="development" /> ``` This will: - Show detailed error messages - Highlight unmapped components - Log component lifecycle events 2. **Check Browser Console** - Check for errors in the browser console - Check for errors in the browser network tab 3. **Network Monitoring** - Use browser dev tools to monitor API calls - Check for 401/403 errors (auth issues) - Verify asset loading paths ### Still Having Issues? If you're still experiencing problems after trying these solutions: 1. Search existing [GitHub issues](https://github.com/dotCMS/core/issues) 2. Ask questions on the [community forum](https://community.dotcms.com/) to engage with other users. 3. Create a new issue with: - Detailed reproduction steps - Environment information - Error messages - Code samples ## Support We offer multiple channels to get help with the dotCMS React SDK: - **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository. - **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions. - **Stack Overflow**: Use the tag `dotcms-react` when posting questions. - **Enterprise Support**: Enterprise customers can access premium support through the [dotCMS Support Portal](https://helpdesk.dotcms.com/support/). When reporting issues, please include: - SDK version you're using - React version - Minimal reproduction steps - Expected vs. actual behavior ## Contributing GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the dotCMS React SDK! If you'd like to contribute, please follow these steps: 1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core) 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request Please ensure your code follows the existing style and includes appropriate tests. ## Licensing dotCMS is available under either the [Business Source License 1.1 (BSL)](https://www.dotcms.com/bsl) or a commercial license. Under the BSL, dotCMS can be used at no cost by individual developers, small businesses or agencies under $5M in total finances, and by larger organizations in non-production environments. Every BSL release automatically converts to GPL v3 four years after its release date. For full terms and FAQs, visit [dotcms.com/bsl](https://www.dotcms.com/bsl) and [dotcms.com/bsl-faq](https://www.dotcms.com/bsl-faq). Production use in larger organizations, along with access to managed cloud, SLAs, support, and enterprise capabilities, is available under a commercial license from dotCMS. For details on commercial plans, features, and support options, see [dotcms.com/pricing](https://www.dotcms.com/pricing).