After modelling out content, and using Tina's API for data-fetching, we can add TinaCMS to our site's frontend and add contextual editing.


To make data editable live on your site, you'll need to set up the TinaCMS context. The default import from tinacms is a context provider which sets up everything for you. You'll notice we're using a render prop pattern to pass livePageProps into your component.

// pages/_app.js
import TinaCMS from 'tinacms'

const App = ({ Component, pageProps }) => {
  return (
      // Required: The query from your `getStaticProps` request
      // Required: The variables from your `getStaticProps` request
      variables={pageProps.variables} // Variables used in your query
      // Required: The data from your `getStaticProps` request
      // Optional: Set to true when working with the local API
      // Optional: When using Tina Cloud, specify the git branch
      // Optional: Your identifier when connecting to Tina Cloud
      // Optional: A callback for altering the document creator plugin
      documentCreatorCallback={args => {
        onNewDocument: args =>
      {livePageProps => <Component {...livePageProps} />}

export default App

<EditState />

We can leverage Next.js dynamic imports to avoid bundling TinaCMS with your production build:

// pages/_app.js
import dynamic from 'next/dynamic'
import { TinaEditProvider } from 'tinacms/dist/edit-state'
const TinaCMS = dynamic(() => import('tinacms'), { ssr: false })

const App = ({ Component, pageProps }) => {
  return (
          <TinaCMS {...pageProps}>
            {livePageProps => <Component {...livePageProps} />}
        <Component {...pageProps} />

export default App

You can enter and exit edit mode by tapping into the useEditState hook, a common pattern is to place this hook on an "admin" page, which simply puts you into edit mode and sends you back to the page you were on:

// pages/admin.js
import { useEffect } from 'react'
import { useRouter } from 'next/router'

import { useEditState } from 'tinacms/dist/edit-state'

const GoToEditPage = () => {
  const { editState, setEdit } = useEditState()
  const router = useRouter()
  useEffect(() => {
    // Go back to the page you were on previously
  }, [])
  // Display a brief message to the user
  return <div>Going into edit mode...</div>

export default GoToEditPage

Note that the tinacms/dist/edit-state (>2kb) code will be in your production bundle with this pattern.


How do I customize the CMS instance?

TinaCMS is highly customizable, use the cmsCallback property to access the TinaCMS instance and customize to your heart's desire.