Skip to content

About

Adapter for NextJS demo

Resources

Contributing

Stars

4 stars

Watchers

5 watching

Forks

Repository files navigation

Enonic NextJS Adapter

NextJS adapter with Guillotine support and basic views

Requires Enonic XP 8.1+ with Guillotine 9.

Installation

npm i --save @enonic/nextjs-adapter

Usage

All functions and views are split into 4 categories by usage:

  • @enonic/nextjs-adapter -- can be used both on server and client sides
  • @enonic/nextjs-adapter/server -- can only be used on server side
  • @enonic/nextjs-adapter/client -- can only be used on client side
  • @enonic/nextjs-adapter/views/... -- views folder, every view has its own file with a default export

Here's the usage example in your project:

// server-side functions are accessible at /server
import {fetchContent} from "@enonic/nextjs-adapter/server";

// views are placed in a folder called `views` and are default exports in files
import MainView from "@enonic/nextjs-adapter/views/MainView"

// ...
const props = await fetchContent({
    contentPath: '/content/path',
    locale: 'en',
});
// ...

return <MainView {...props}/>

API

Server-side only functions

They are available at @enonic/nextjs-adapter/server


fetchContent(context: Context) => Promise<FetchContentResult>

Fetches the content/component by path with component queries optimization, page structure as well as runtime info calculation. This is the main method for querying content.

Argument Description
context Execution context

Usage:

import {fetchContent} from '@enonic/nextjs-adapter/server';
import {headers} from 'next/headers';

const context = {
    contentPath: '/current/content/path',
    locale: 'en',
    headers: headers(),
};

const response = fetchContent(context);

Response type:

type FetchContentResult = {
    error?: {
        code: string,
        message: string
    } | null;
    data: Record<string, any> | null,       // Result of the content query
    common: Record<string, any> | null,     // Result of the common query
    meta: MetaData,                         // Runtime information
    page: PageComponent | null,             // The structure of the page (not present when rendering single component)
};

fetchGuillotine(contentApiUrl: string, options?: FetchOptions) => Promise<GuillotineResult>

Makes a custom request to Guillotine. Used by fetchContent() method.

Argument Description
contentApiUrl Guillotine API URL
options Request and Next.js config options (Optional)

Usage:

import {fetchGuillotine} from '@enonic/nextjs-adapter/server';

const apiUrl = 'http://domain:8080/api/com.enonic.app.guillotine:graphql';

const body = {
    query: 'qraphql query as string',
    variables: {
        foo: 'bar',
    },
};

const headers = {
    'custom-header': 'header-value',
};

const opts = {
    body,
    headers,
    method: 'POST',
    next: {
        revalidate: 60,
        tags: ['tag1', 'tag2'],
    }
};

const result = fetchGuillotine(apiUrl, opts);

Response type:

type GuillotineResult = {
    error?: {
        code: string,
        message: string
    } | null;
    [dataKey: string]: any;
};

fetchFromApi(apiUrl: string, options?: FetchOptions) => Promise<GuillotineResponseJson>

Makes custom third-party service request. Used by the fetchGuillotine() method.

Argument Description
apiUrl Service API URL
options Request and Next.js config options (Optional)

Usage:

import {fetchFromApi} from '@enonic/nextjs-adapter/server';

const apiUrl = 'http://domain:8000/graphql/api';

const body = {
    query: 'qraphql query as string',
    variables: {
        foo: 'bar',
    },
}

const headers = {
    'custom-header': 'header-value',
}

const opts = {
    body,
    headers,
    method: 'POST',
    next: {
        revalidate: 60,
        tags: ['tag1', 'tag2'],
    }
};

const result = fetchFromApi(apiUrl, opts);

fetchContentPathsForAllLocales(query?: string, countPerLocale?: number) => Promise<ContentPathItem[]>

Loads all content paths for all locales. Generally used for static site generation.

Argument Description
query Custom GraphQL query (Optional) *
countPerLocale Max result count per locale (Optional, defaults to 999)

* Default query gets up to countPerLocale results, sorts them by modifiedTime and excludes following content types:

"base:shortcut", 
"portal:fragment", 
"portal:template-folder", 
"portal:page-template", 
"media:*"

Usage:

import {fetchContentPathsForAllLocales} from '@enonic/nextjs-adapter/server';

const contentPaths = fetchContentPathsForAllLocales('custom graphql query', 1001);

fetchContentPathsForLocale(mapping: LocaleMapping, query?: string, count?: number) => Promise<ContentPathItem[]>

Loads all content paths for the current locale. Generally used for static site generation. Used by fetchContentPathsForAllLocales()

Argument Description
mapping Mapping locale to project
query Custom GraphQL query (Optional, default value here)
count Max result count (Optional, defaults to 999)

Usage:

import {fetchContentPathsForLocale} from '@enonic/nextjs-adapter/server';
import {getLocaleMapping} from '@enonic/nextjs-adapter';

const mapping = getLocaleMapping({
    contentPath: '/current/content/path',
});

const contentPaths = fetchContentPathsForLocale(mapping, 'custom graphql query', 1001);

Client-side only functions

They are available at @enonic/nextjs-adapter/client


<LocaleContextProvider locale="en">

Create a React.js context that allows child elements to access and modify current locale as well as localize static texts for current locale. See useLocaleContext() method for example.

Argument Type Description
locale String Set the initial locale value

Usage:

import {LocaleContextProvider} from '@enonic/nextjs-adapter/client';

<LocaleContextProvider locale="en"> ...child elements... </LocaleContextProvider>

useLocaleContext() => LocaleContextType

Methods to access and modify current locale as well as localize static texts, where LocaleContextType is:

interface LocaleContextType {
    dictionary: Dict
    locale: string
    localize: (key: string, ...args: any[]) => string
    setLocale: (locale: string) => Promise<Dict>
}

Usage:

'use client';

import {useLocaleContext} from '@enonic/nextjs-adapter/client';

export default function ClientSideComponent() {
    const {locale, localize, setLocale} = useLocaleContext();
    console.log(`Current locale: ${locale}`);
    
    const localizedText = localize('text.key');
    
    setLocale('en').then((dict) => {
        console.log(`New locale: ${locale}`);
    });
    // ...
}

Both client and server-side functions

They are available at @enonic/nextjs-adapter


Guillotine URL helpers

Every Guillotine *Url field comes with two functions: *UrlQuery(args) builds the GraphQL selection for the field, and *Url(result) turns the returned object into the final URL string.

Field Query builder String function
imageUrl imageUrlQuery(args: ImageUrlArgs) imageUrl(data, meta)
mediaUrl mediaUrlQuery(args?: MediaUrlArgs) mediaUrl(data, meta)
attachmentUrl attachmentUrlQuery(args?: MediaUrlArgs) attachmentUrl(data, meta)
pageUrl pageUrlQuery(args?: PageUrlArgs) pageUrl(data, meta)

The query builders accept the same arguments as the Guillotine field (scale, quality, background, format, filter for imageUrl; download for mediaUrl/attachmentUrl; params for pageUrl) and select every field of the returned object: path, queryString, context, id, fingerprint, name, plus scale for images and intent for media and attachments (pageUrl has baseUrl, path and queryString). Media functions use meta.branch to return the authenticated /api/media proxy path for draft content and an absolute XP media URL (ENONIC_MEDIA_CDN, defaulting to ENONIC_API) for live content. pageUrl returns a relative path for the Next.js router, prefixed with the locale unless it is the default locale (meta.locale vs meta.defaultLocale). meta is the runtime data returned by fetchContent. Pass {locale} alone to pageUrl to always prefix, e.g. for revalidatePath. The string functions take that object (ImageUrl, AttachmentUrl or PageUrl from the adapter types) and return undefined when given undefined; All four append queryString to path and need only path (queryString is optional), so links without a Guillotine object can pass a bare {path}, e.g. pageUrl({path: '/'}, meta) for the site root.

Usage:

import {imageUrlQuery, pageUrlQuery, imageUrl, pageUrl} from '@enonic/nextjs-adapter';

const query = `
  photos {
    ... on media_Image {
      ${imageUrlQuery({scale: 'width(500)'})}
    }
  }
  parent {
    ${pageUrlQuery()}
  }`;

<img src={imageUrl(photo.imageUrl, meta)}/>
<Link href={pageUrl(parent.pageUrl, meta)}>Back</Link>

localizeMappings(mappings: UrlMappingRule[], mapping: LocaleMapping) => UrlMappingRule[] prefixes /api/mappings targets with the mapping's locale unless it is the default one, leaving sources untouched.


richTextQuery(fieldName: string, options?: RichTextQueryOptions) => string

This is a utility function for querying for RichTextData needed for RichTextView. It creates a graphql query string for HTML area input type with given field name.

NOTE! On the server the adapter reads ENONIC_API, ENONIC_MEDIA_CDN, ENONIC_APP_NAME and ENONIC_MAPPINGS. In the browser it reads the NEXT_PUBLIC_ENONIC_API, NEXT_PUBLIC_ENONIC_MEDIA_CDN, NEXT_PUBLIC_ENONIC_APP_NAME and NEXT_PUBLIC_ENONIC_MAPPINGS copies, so define the ones your client components need (e.g. NEXT_PUBLIC_ENONIC_API=$ENONIC_API for imageUrl() in a client component, NEXT_PUBLIC_ENONIC_APP_NAME when _mappings.ts is imported client-side). Without them media URLs stay relative and the locale helpers throw in the browser.

The macro configs, links and images are selected through the named fragments RichTextMacros, RichTextLinks and RichTextImages, so a document with many rich text fields stays small. fetchGuillotine() (and therefore fetchContent()) appends the fragment definitions once per document. If you send such a query with your own HTTP client, append richTextFragments() to it yourself, or pass the document through withRichTextFragments(query).

Argument Description
fieldName HTML area field name
options Optional per-field image settings passed to Guillotine's processHtml input. Each omitted setting independently retains its current behavior.

RichTextQueryOptions is exported by the adapter:

Option Type Default when omitted
imageWidths number[] [400, 800, 1200] for responsive srcset candidates.
imageSizes string "(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px" for the HTML sizes attribute.
imageSrcWidth number Not sent; Guillotine retains its default primary image width of 768px.

Passing an empty array or string is an explicit override, not an omitted option. These settings apply at query time, not as rendering props. Different fields in the same document can use different settings while sharing the same fragment definitions.

import {richTextQuery, type RichTextQueryOptions} from '@enonic/nextjs-adapter';

// Only the primary source width changes; responsive widths and sizes keep their defaults.
const bioQuery = richTextQuery('bio', {imageSrcWidth: 640});

const imageOptions: RichTextQueryOptions = {
    imageWidths: [320, 640, 960],
    imageSizes: '(max-width: 640px) 100vw, 640px',
    imageSrcWidth: 640
};
const textQuery = richTextQuery('text', imageOptions);

Usage:

import {richTextQuery} from '@enonic/nextjs-adapter';

const query = `query($path:ID!, $scopeKey:String, $project:String, $branch:String){
    guillotine(scopeKey: $scopeKey, project: $project, branch: $branch) {
        get(key:$path) {
            _path
            type
            ${richTextQuery('htmlField')}
        }
    }
}`;

validateData(props: FetchContentResult) => void

Utility method to validate data returned by fetchContent() method. Throws an error or calls Next.js notFound() if data is invalid. Also prevents shortcut content types from being rendered in preview/edit modes.

Argument Description
props FetchContentResult object

Usage:

import {fetchContent} from '@enonic/nextjs-adapter/server';
import {validateData} from '@enonic/nextjs-adapter';

const data = await fetchContent({
    contentPath: '/path/to/content',
    locale: 'en',
});

validateData(data);

getContentBranch(context?: Context) => string

Resolves the Enonic XP branch (master or draft) for the current request based on its render mode. Returns master for LIVE and NEXT render modes, and draft otherwise (e.g. EDIT, PREVIEW, INLINE).

Argument Description
context Context object (Optional)

Usage:

import {getContentBranch} from '@enonic/nextjs-adapter';

const branch = getContentBranch({
    contentPath: '/current/content/path',
    locale: 'en',
});

encryptParams(params: Record<string, any>, secret: string) => string

Symmetrically encrypts a params object into a base64url string using AES-256-GCM. The secret is hashed with SHA-256 to derive the key, so any string length works. Pair with decryptParams() to read the value back.

Argument Description
params Plain object to encrypt
secret Secret string used to derive the encryption key

Usage:

import {encryptParams} from '@enonic/nextjs-adapter';

const blob = encryptParams({userId: '123', role: 'editor'}, process.env.ENONIC_API_TOKEN);

decryptParams(blob: string, secret: string) => Record<string, any> | null

Decrypts a base64url string produced by encryptParams(). Returns null if the input is malformed, tampered with, or was encrypted with a different secret.

Argument Description
blob Base64url string produced by encryptParams
secret Same secret used during encryption

Usage:

import {decryptParams} from '@enonic/nextjs-adapter';

const params = decryptParams(blob, process.env.ENONIC_API_TOKEN);
if (params) {
    // use params.userId, params.role, ...
}

ComponentRegistry

Registry containing definitions of all components (i.e. pages, parts, layouts, macros, etc. ). It is used in the runtime by nextjs-adapter to make component queries and render components. It has several public methods:


static setCommonQuery(query: SelectedQueryMaybeVariablesFunc): void

Sets up a common query that is going to be executed along with component queries and passed to every component on the page.

Argument Description
query Common query definition

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const query = {
    query: 'graphql query',
    variables: ({path, scopeKey, branch, project}, context, config) => {
        return {
            path: path + '/some/processing',
            scopeKey,
            branch,
            project,
        };
    }
}

ComponentRegistry.setCommonQuery(query);

static getCommonQuery(): SelectedQueryMaybeVariablesFunc

Gets the common query definition.

Response type:

interface GlobalVariables {
    path: string;
    scopeKey: string;
    branch: string;
    project: string;
}

type QueryGetter = (vars: GlobalVariables, context?: Context, config?: any) => string;

type VariablesGetter = (vars: GlobalVariables, context?: Context, config?: any) => GlobalVariables & Record<string, any>;

type SelectedQueryMaybeVariablesFunc =
    string |
    QueryGetter |
    {
        query: string | QueryGetter,
        variables: VariablesGetter
    } |
    [string | QueryGetter, VariablesGetter];

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const query = ComponentRegistry.getCommonQuery();

static getByComponent(component: PageComponent): ComponentDefinition | undefined

Gets component definition from the ComponentRegistry.

Argument Description
component Page component to get definition for

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const definition = ComponentRegistry.getByComponent(component);

Response type:

interface ComponentDefinition {
    catchAll?: boolean; // set automatically depending on the binding
    query?: SelectedQueryMaybeVariablesFunc,
    configQuery?: string,
    processor?: DataProcessor,
    view?: React.FunctionComponent<any>
}

static addMacro(name: string, obj: ComponentDefinitionParams): void

static addPart(name: string, obj: ComponentDefinitionParams): void

static addLayout(name: string, obj: ComponentDefinitionParams): void

static addPage(name: string, obj: ComponentDefinitionParams): void

static addContentType(name: string, obj: ComponentDefinitionParams): void

static addComponent(name: string, obj: ComponentDefinitionParams): void

Saves the component definition in ComponentRegistry by name.

NOTE: addComponent is used for defining general types of Enonic XP components by nextjs-adapter so you don't need to do it manually. Overriding default setup may break Enonic XP integration!

Argument Description
name Component name
obj Component definition

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const definition = {}

ComponentRegistry.addMacro('macro-name', definition);

static getMacro(name: string): ComponentDefinition | undefined

static getPart(name: string): ComponentDefinition | undefined

static getLayout(name: string): ComponentDefinition | undefined

static getPage(name: string): ComponentDefinition | undefined

static getContentType(name: string): ComponentDefinition | undefined

static getComponent(name: string): ComponentDefinition | undefined

Gets the component definition stored in ComponentRegistry by its name.

NOTE: Read addComponent note before using getComponent.

Argument Description
name Component name

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const definition = ComponentRegistry.getMacro('macro-name');

Response type: component definition


static getMacros(): [string, ComponentDefinition][]

static getParts(): [string, ComponentDefinition][]

static getLayouts(): [string, ComponentDefinition][]

static getPages(): [string, ComponentDefinition][]

static getContentTypes(): [string, ComponentDefinition][]

static getComponents(): [string, ComponentDefinition][]

Gets all component entries ([name, definition] tuples) stored in ComponentRegistry.

NOTE: Read addComponent note before using getComponents.

Usage:

import {ComponentRegistry} from '@enonic/nextjs-adapter';

const macros = ComponentRegistry.getMacros();

Response type: list of [name, ComponentDefinition] tuples � see component definition.


Enonic XP locale mapping functions

In order to create association between locale and Enonic XP project, ENONIC_MAPPINGS environment variable should be set. Functions for reading those mappings are available at @enonic/nextjs-adapter.


getLocaleMapping(context: Context): LocaleMapping

Argument Description
context Context object

Usage:

import {getLocaleMapping} from '@enonic/nextjs-adapter';

const mapping = getLocaleMapping({
    contentPath: '/current/content/path',
    locale: 'en',
});

Response type:

export interface LocaleMapping {
    default: boolean
    project: string
    site: string
    locale: string
}

getLocaleMappingByProjectId(projectId?: string, useDefault = true): LocaleMapping

Argument Description
projectId Enonic project ID (Optional)
useDefault Use default locale as fallback (Optional, default: true)

Usage:

import {getLocaleMappingByProjectId} from '@enonic/nextjs-adapter';

const mapping = getLocaleMappingByProjectId('project-id', true);

Response type


getLocaleMappingByLocale(locale?: string, useDefault = true): LocaleMapping

Argument Description
locale locale ID (Optional)
useDefault Use default locale as fallback (Optional, default: true)

Usage:

import {getLocaleMappingByLocale} from '@enonic/nextjs-adapter';

const mapping = getLocaleMappingByLocale('en', true);

Response type


getRequestLocaleInfo(context: Context): LocaleInfo

Attempts to get the locale info from the request. Along with that it also returns the default locale and all configured locales.

Argument Description
context Context object

Usage:

import {getRequestLocaleInfo} from '@enonic/nextjs-adapter';

const mapping = getRequestLocaleInfo({
    contentPath: '/current/content/path',
    locale: 'en',
});

Response type:

interface LocaleInfo {
    locale: string,
    locales: string[],
    defaultLocale: string
}

I18n localization functions

These functions can be used both on server and client sides, but it is recommended to use native React.js context classes for client-side localization.


static I18n.setLocale(locale: string): Promise<Dict>

Sets the current locale and returns the dictionary for it.

Argument Description
locale Locale id, i.e. en

Usage:

import {I18n} from '@enonic/nextjs-adapter';

const dict = await I18n.setLocale('en');

Response type:

interface Dict {
    [key: string]: string
}

static I18n.localize(key: string, ...args: any[]): string

Localizes the static text by key and replaces placeholders with provided arguments.

Argument Description
key text key
...args template arguments

Usage:

import {I18n} from '@enonic/nextjs-adapter';

const localizedText = I18n.localize('text.key', 'value1', 'value2');

static I18n.getLocale(): string

Returns the current locale.

Usage:

import {I18n} from '@enonic/nextjs-adapter';

const locale = I18n.getLocale();

static I18n.getDictionary(): Dict

Returns dictionary for the current locale.

Usage:

import {I18n} from '@enonic/nextjs-adapter';

const dict = I18n.getDictionary();

Response type


Utility functions

There is also a number of utility constants and functions available at @enonic/nextjs-adapter.


All of the following are exported from @enonic/nextjs-adapter:

IS_DEV_MODE;                // True if current mode == development

APP_NAME;                   // Name of the app defined in .env files

APP_NAME_UNDERSCORED;       // APP_NAME with underscores instead of dots

APP_NAME_DASHED;            // APP_NAME with dashes instead of dots

CATCH_ALL;                  // Catch all component name

PORTAL_COMPONENT_ATTRIBUTE; // Portal component attribute name

PORTAL_REGION_ATTRIBUTE;    // Portal region attribute name

JSESSIONID_HEADER;          // JSESSIONID header name

PROJECT_ID_HEADER;          // Project ID header name

RENDER_MODE_HEADER;         // Render mode header name

XP_BASE_URL_HEADER;         // XP base URL header name

enum XP_REQUEST_TYPE {      // Enum for XP request types
    COMPONENT = 'component',
    TYPE = 'type',
    PAGE = 'page',
}

enum RENDER_MODE {          // Enum for render modes
    INLINE = 'inline',
    EDIT = 'edit',
    PREVIEW = 'preview',
    LIVE = 'live',
    ADMIN = 'admin',
    NEXT = 'next',
}

enum XP_COMPONENT_TYPE {    // Enum for XP component types
    PART = 'part',
    LAYOUT = 'layout',
    TEXT = 'text',
    FRAGMENT = 'fragment',
    PAGE = 'page',
}

// Sanitizes text according to graphql naming spec http://spec.graphql.org/October2021/#sec-Names
const sanitizeGraphqlName = (text: string) => string;

See also: getContentBranch, encryptParams, decryptParams.

Views

They are located in @enonic/nextjs-adapter/views folder. Each view is a default export in the corresponding file.


<MainView common="common" data="data" page="page" meta="meta">

The main view of the application. It accepts the result of fetchContent method and is intended to be used as a view for your next.js route

Argument Type Description
common Record<string, any> &#124; null Result of the common query
data Record<string, any> &#124; null Result of the graphql query
page PageComponent &#124; null Page structure
meta MetaData Runtime info

Usage:

import MainView from '@enonic/nextjs-adapter/views/MainView';
import {fetchContent} from '@enonic/nextjs-adapter/server';

export async function getServerSideProps(context: Context) {
    const props = await fetchContent({
        contentPath: '/content/path',
        locale: 'en',
    });
    return {
        props
    }
}

export default MainView;

<StaticContent condition={true} element="div">

Tag for disabling client side hydration if the condition is true. This will remove interactivity from children.

Argument Type Description
condition = true Boolean Condition to trigger static output
element = 'div' String Html tag to use for static output

Usage:

import StaticContent from '@enonic/nextjs-adapter/views/StaticContent';

<StaticContent condition={true} element="div"> ...child elements... </StaticContent>

<DraftModeIndicator label="Draft">

Floating badge in the bottom-right corner, styled like the Next.js dev indicator, for leaving Next.js draft mode. It renders only when draftMode().isEnabled is true, and hides itself inside iframes (i.e. in Content Studio). The label defaults to Draft, is followed by a ✕ glyph, and can be localized by the caller, e.g. with I18n.localize(). Clicking it runs a Server Action that calls draftMode().disable() and then reloads the page without the xp query parameter (the Content Studio preview marker, which would otherwise make the proxy re-enable draft mode), so content is served from the master branch again. The badge ships its own CSS module; its colors can be overridden through the --draft-mode-* custom properties set on the button.

Argument Type Description
label = 'Draft' String Badge text, e.g. a localized phrase

Usage:

import {I18n, IS_DEV_MODE} from '@enonic/nextjs-adapter';
import DraftModeIndicator from '@enonic/nextjs-adapter/views/DraftModeIndicator';

// Root layout: render it conditionally (here: only under `next dev`) directly inside <body>,
// not inside <StaticContent> (which disables hydration)
<body>
    {children}
    {IS_DEV_MODE && <DraftModeIndicator label={I18n.localize('draft-mode')}/>}
</body>

Requires transpilePackages: ['@enonic/nextjs-adapter'] in next.config.js so that Next.js compiles the bundled Server Action.


<RichTextView className="css-class" tag="section" data={data} meta={meta} customReplacer={customReplacerFn}>

Tag for displaying contents of html area input types. Takes care of processing macros, URLs and images inside.

RichTextData, LinkData, ImageData, MacroData, and MacroConfig are shared with and re-exported from @enonic/react-components. Rich-text URL values can be strings (used unchanged) or URL parts (resolved by the adapter using its locale and media configuration). The adapter renders the original reference entries without rewriting their data.

Argument Type Description
data RichTextData Rich text data
meta MetaData Runtime data returned by fetchContent method.
customReplacer Replacer Function to do custom element processing. Not invoked for image, link and macro nodes. Optional
className String Class name to add to the root html element. Optional
tag = 'section' ElementType Element to use as a root. An html tag name, a component, or Fragment to render no root element at all. Optional

TIP! There is a utility function richTextQuery(fieldName) generating part of the graphql query to obtain RichTextData for html area input types.

Usage:

import RichTextView from '@enonic/nextjs-adapter/views/RichTextView';

<RichTextView data={richTextData} meta={meta} tag="section" className="rich-text-view"></RichTextView>

To render the rich text without any wrapping element, pass Fragment as the tag. Note that className has nowhere to go in that case and is ignored, so apply styling to a surrounding element instead.

import {Fragment} from 'react';
import RichTextView from '@enonic/nextjs-adapter/views/RichTextView';

<RichTextView data={richTextData} meta={meta} tag={Fragment}></RichTextView>

<Regions page={page} meta={meta} name="main" common={common}>

Tag for rendering page regions. It is useful when implementing custom page views. All necessary data can be acquired by running fetchContent()

Argument Type Description
page PageData &#124; null; Page structure
meta MetaData Runtime info
name String Render only this region. Optional
common any Result of common query. Optional

Usage:

import Regions from '@enonic/nextjs-adapter/views/Region';

<Regions page={page} meta={meta} name="main" common={common}/>

About

Adapter for NextJS demo

Resources

Contributing

Stars

4 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages