# Using Editmode with Next.js

**Introduction**

Editmode allows you to turn plain text in your Next.js app into easily inline-editable content that can be managed safely by your whole team.

[Next.js](https://nextjs.org/) is an open-source production-ready React framework used to build web applications that are either static or rendered on the server-side, with smart bundling & a config-free setup right out of the gate.&#x20;

## Adding Editmode to an existing Next.js codebase

**1. Add editmode-react to your codebase**

{% tabs %}
{% tab title="NPM" %}

```bash
npm install editmode-react
```

{% endtab %}

{% tab title="Yarn" %}

```bash
yarn add editmode-react
```

{% endtab %}
{% endtabs %}

**2. Wrap your app in the Editmode provider.**&#x20;

{% tabs %}
{% tab title="Basic Setup" %}

```jsx
import {Editmode} from "editmode-react"

// For demo purposes, we'll use a "Home" page function.
// In a real-world setting, the best set-up is to use a <Layout /> component
// which all other pages inherit from, to ensure that all pages are 
// wrapped with the <Editmode /> provider. 

export default function Home() {
  return (
    <Editmode projectId="prj_Y5HfCBS4rqZg"> {/* Replace with your own project id. */}
      <section></section>
    </Editmode>
  );
}

```

{% endtab %}

{% tab title="Specifying a branch" %}

```jsx
import { Editmode } from "editmode-react";

// Branches are used to create separate "versions" of your content, which can
// be useful for staging, running a/b tests, or developing locally on teams.
// Branches are created within the content hub at https://app.editmode.com
// Specifying a branch id when initializing Editmode will load all content
// from that specific branch.

export default function Home() {
  return (
    <Editmode projectId={project_id} branchId={branch_id}>
      <section></section>
    </Editmode>
  );
}
```

{% endtab %}

{% tab title="Specifying default content" %}

```jsx
import { Editmode } from "editmode-react";
import { defaultChunks } from "./data/defaultChunks";

// Editmode is smart about fetching and caching content to ensure that 1. Your
// app/site always remains fast, and 2. Users always see the most recent content.
// While Editmode is capable of loading content direct from our CDN, some 
// customers like to also bundle a resource file within their codebase that will 
// provide content in the event that the API fails. This can 
// be achieved by passing an object with default content to the Editmode provider
// on initialization. The creation of this file can be automated via our API.
// See https://snack.expo.io/@editmode/algolia-demo for an interactive demo
// of this setup

export default function Home() {
  return (
    <Editmode projectId={project_id} defaultChunks={defaultChunks}>
      <section></section>
    </Editmode>
  );
}
```

{% endtab %}
{% endtabs %}

For more info/best practices on how to implement the \<Layout /> pattern, consult our starter repo [here](https://github.com/editmodelabs/msiab/tree/main/themes/lagos).

**3. Use the Editmode helpers in your codebase.**

{% tabs %}
{% tab title="Render an editable chunk" %}

```jsx
import { Chunk } from "editmode-react";

function Example() {
  return (
    <section>
    
      {/* Reference a standalone chunk using the chunk identifier */}
      <Chunk identifier="cnk_7019e843b76e2d0395ab" />
      
      {/* You can also reference a chunk using its content key */}
      <Chunk identifier="company_name" />
      
      {/* Provide default content when referencing a chunk */}
      {/* Default content is a precaution that will get rendered in 
          the event that the content cannot be served from the Editmode API.
      */}
      <Chunk identifier="company_name">
        Our Company
      </Chunk> 
      
    </section>
  );
}
```

{% endtab %}

{% tab title="Render a hybrid chunk field" %}

```jsx
import { Chunk } from "editmode-react";


function Example() {
  return (
    <section>
      
      {/* Editmode has two types of chunks - "standalone" and "hybrid". 
          Standalone chunks can only store a single piece of content,
          whereas hybrid (or collection) chunks can have many fields.
          These fields are pre-specified in the Content Hub at 
          https://app.editmode.com
      */}
      
      <Chunk identifier="home_hero" field="Headline" />
      <Chunk identifier="home_hero" field="Tagline" />
      <Chunk identifier="home_hero" field="Description" />
      
    </section>
  );
}
```

{% endtab %}

{% tab title="Specify classes" %}

```jsx
import { Chunk } from "editmode-react";

// By default, an editable chunk is rendered to the client as an unstyled <em-span />
// This can cause unwanted behaviour from a styling perspective, so you can tell 
// Editmode to add a class to the wrapper.

function Example() {
  return (
    <section>
      <Chunk identifier="company_name" className="bg-white rounded shadow p-6" />
    </section>
  );
}
```

{% endtab %}

{% tab title="Mixed Examples" %}

```jsx
import Head from "next/head";
import {Editmode, Chunk, ChunkCollection, ChunkFieldValue, useGetChunk} from "editmode-react"

export default function Home() {
  return (
    <Editmode projectId="prj_Y5HfCBS4rqZg" >
      
      <div className="container mx-auto">

        {/* Render a piece of standalone content with inline editing */}
        <Chunk identifier="logo_icon" className="w-5 text-primary" />  {/* Image Chunk */}
        <Chunk identifier="company_name" /> {/* Plain Text Chunk */}
        
        {/* Render content from a collection, with inline editing */}
        <ChunkCollection identifier="testimonials" >   
          <ChunkFieldValue identifier="Name" />  
          <ChunkFieldValue identifier="Role" />   
          <ChunkFieldValue identifier="Comment" />
        </ChunkCollection>

        {/* Access the raw value of a chunk. (No inline editing)  */}
        <Head>
          <title>{useGetChunk("company_tagline")}</title>
        
        <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.8.2/dist/alpine.min.js" defer></script>
        <style>
          @font-face {
            font-family: 'Mackinac Bold';
            src: url('https://editmode.s3-eu-west-1.amazonaws.com/static/P22Mackinac-Bold_23.otf')
          } 
          div[class*="footer"] {
            display: none;
          }
          div[class*="navigationHeader"] {
              height: 60px;
          }
          div[class*="navigationHeaderLogo"] {
              display: none;
          }
          div[class*="navigationHeader"] div:last-child,
          div[class*="navigationHeader"] div:last-child button {
              width: 100%;
              justify-content: left;
          }
          div[class*="navigationHeader"] div:last-child button span:first-child::after {
              padding-left: 10px;
              content: "Search Docs..."
          }
          div[class*="pageContainer"] {
              margin: 0 40px;
          }
          h1[class*="pageTitle"] span,
          [class*="HeadingH700"],
          [class*="InfoH200"] {
              font-family: "Mackinac Bold"
          }
          [class*="wholeContentPage"] {
              border-radius: 5px;
              box-shadow: 0 3px 8px 0 rgb(116 129 141 / 10%);
          }
          [class*="pageHeaderInner"] {
            padding: 30px 0 20px 0 !important;
          }
          [class*="blockHeadingContent"] {
            display: flex;
          }
          [class*="blockHeadingAnchor"] {
            opacity: 1;
          }
          [class*="blockHeadingAnchorIcon"] {
            margin-top: 7px;
            display: block;
          }
          [class*="pageBody"] ul {
            list-style-type: disc;
          }
          @media screen and (min-width: 1023px) {
            [class*="contentNavigation"],
            [class*="sidebarMain"] {
              border-right: 0px !important;
              background: none !important;
            }
          }
        </style></Head>

      </div>
      
    </Editmode>
  )
}
```

{% endtab %}
{% endtabs %}

#### Working with collections

Chunk collections are simply a way to group chunks and can be used to render repeatable content. Each collection can contain many properties and each property can hold different types of information.

A good use case example would be creating a "Team Member" collection. It may have `Full Name`, `Title` and `Headshot` properties. Within your Next.js app, you may want to display the name, title and headshot of all your team members (i.e. all chunks within the Team Member collection). You can do this by passing the chunk collection identifier as a prop to the ChunkCollection component. For example...

{% tabs %}
{% tab title="Basic collections w/ inline editing" %}

```jsx
import { ChunkCollection, ChunkFieldValue } from "editmode-react";

function Example() {
  return (
    <section className="testimonials">
    
      {/* Render content from a collection, with inline editing */}
      <ChunkCollection identifier="col_MFxBu6fiTyRM" >   
        <ChunkFieldValue identifier="fld_LscoanYMdCOy" />  
        <ChunkFieldValue identifier="fld_Iq94B0LyQxGc" />   
        <ChunkFieldValue identifier="fld_LyRI6y3v2D8ct" />
      </ChunkCollection>
      
      {/* Use content keys for better readability */}
      <ChunkCollection identifier="testimonials" >   
        <ChunkFieldValue identifier="Name" />  
        <ChunkFieldValue identifier="Role" />   
        <ChunkFieldValue identifier="Comment" />
      </ChunkCollection>
      
      {/* Only render collection items with certain tags */}
      <ChunkCollection identifier="testimonials" tags={["home_testimonials"]}>   
        <ChunkFieldValue identifier="Name" />  
        <ChunkFieldValue identifier="Role" />   
        <ChunkFieldValue identifier="Comment" />
      </ChunkCollection>

    </section>
  );
}

```

{% endtab %}

{% tab title="Going Deeper" %}

```jsx
import { ChunkCollection, ChunkFieldValue, getChunk } from "editmode-react";

// Often, when iterating through a collection of content, your UI will need 
// to access the raw values, instead of rendering inline-editable chunks. 
// For this we use getChunk(), along with ChunkCollection.

function Example() {
  return (
    <section className="meet_the_team">
      <ChunkCollection identifier="navigation_items">
        {(getChunk, chunk) => {
          return (
            if (getChunk(chunk, "Title")) {
            
              {/* Render an editable inline field */}
              <ChunkFieldValue identifier="Title" />
              
              {/* Render a link using the chunk field values*/}
              <a href={getChunk(chunk, "Url")}>
                {getChunk(chunk, "Title")}
              </a>
            }
          )
        }}
      </ChunkCollection>
    </section>
  );
}
```

{% endtab %}
{% endtabs %}

## Full Reference

A full list of components, functions, and props can be found here 👇

{% content-ref url="/pages/-MXWcVltSl-7mtDb2sjf" %}
[Editmode for React](/editmode-docs/client-libraries/editmode-for-react.md)
{% endcontent-ref %}

* [Working with image transformations in editmode-react](/editmode-docs/client-libraries/editmode-for-react.md#image-transformations)
* [Using Variables in editmode-react](/editmode-docs/client-libraries/editmode-for-react.md#variables)

## Creating a new Editmode/Next.js project

For green-field codebases, the best way to get started is by forking our "Marketing Site in a Box" repository (specifically the "Lagos" theme). We spent a lot of time to ensure it has all the basics covered, along with examples.&#x20;

* [Read the "Marketing Site In A Box" announcement](https://twitter.com/tonyennis/status/1412819608868847616)&#x20;
* [Visit the "Marketing Site In A Box" Github repo](https://github.com/editmodelabs/msiab)

This workflow will be available as an npx command soon, but for now you can easily get started by cloning the repo, navigating to the "Lagos" theme directory, and removing the parts you don't need.&#x20;

```
git clone https://github.com/editmodelabs/msiab 
cd msiab/themes/lagos
yarn install 
yarn dev
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://editmode.gitbook.io/editmode-docs/guides/editmode-and-next.js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
