Using @contember/admin inside Next.js app
By integrating Contember Admin into your Next.js app, you can efficiently manage and update data, delivering seamless user experiences. However, there are a few considerations to keep in mind. Contember Admin is client-side, so server-side rendering (SSR) needs to be disabled for that component. Additionally, a public token is required to access Contember Admin. In this guide, we'll walk through the necessary steps to set up Contember Admin within Next.js, overcoming these limitations.
Also keep in mind, that Contember CSS may collide with other CSS frameworks, like Tailwind.
Also keep in mind, that Contember CSS may collide with other CSS frameworks, like Tailwind.
next.config.js
In next config, we need to transpile the @contember/admin package. Also, we disable react strict mode, as there are currently some issues with some components.
const withTM = require('next-transpile-modules')(['@contember/admin'])/** @type {import('next').NextConfig} */const nextConfig = {reactStrictMode: false,}module.exports = withTM(nextConfig)
components/SubmitGist.tsx
Here is a sample component used in Next.js page. We must first setup some contexts.
import { ContemberClient, CreateScope, I18nProvider, PersistButton, RichTextField, TextField, ToasterProvider } from '@contember/admin'export const SubmitGist = () => {return (<I18nProvider localeCode={undefined} dictionaries={undefined}><ToasterProvider><ContemberClientapiBaseUrl={process.env.NEXT_PUBLIC_CONTEMBER_BASE_URL!}project={process.env.NEXT_PUBLIC_CONTEMBER_PROJECT}stage={process.env.NEXT_PUBLIC_CONTEMBER_STAGE}sessionToken={process.env.NEXT_PUBLIC_CONTEMBER_TOKEN}><CreateScope entity={'Gist'}><TextField field="title" label="Gist title" required /><RichTextField field="contentJson" label="Gist description" /><PersistButton /></CreateScope></ContemberClient></ToasterProvider></I18nProvider>)}
pages/submit.tsx
To force client side rendering, we need to wrap our Contember component like this:
import dynamic from 'next/dynamic'const NoSsrWrapper = dynamic(() => import('../components/SubmitGist').then(it => it.SubmitGist),{ ssr: false },)export default () => {return <><NoSsrWrapper /></>}
pages/_app.tsx
To include @contember/admin CSS, add them to Next application entrypoint
// ....import '@contember/admin/style.css'// ....
style/global.css
Here are some, but not all, fixes to solve compatibility issues with a tailwind.
body, html {display: initial;min-width: initial;}* {border-color: initial;}.cui-textarea-input, .cui-text-input {padding-left: var(--cui-padding-horizontal);padding-right: var(--cui-padding-horizontal);}.gists-submit .cui-repeater-item-container-label {display: none;}.cui-textarea-input {padding-bottom: var(--cui-text-area-padding-vertical);padding-top: var(--cui-text-area-padding-vertical);}
.env.local
Sample env file. Keep in mind that the token will be exposed publicly, so make sure your ACL is correct
NEXT_PUBLIC_CONTEMBER_BASE_URL=http://localhost:1481NEXT_PUBLIC_CONTEMBER_PROJECT=my-projectNEXT_PUBLIC_CONTEMBER_STAGE=liveNEXT_PUBLIC_CONTEMBER_TOKEN=0000000000000000000000000000000000000000