Tags
The written version and video cover the same example, you can follow any format you like.
NOTE: for this example we will be using caisy’s nextjs starter template with the next pages router, feel free to clone this repository and follow the instructions to be at the same starting point. You can also use your own project, you might need to adapt some steps accordingly. While this setup focuses on the pages router, you can translate the usage to the app router, by wrapping all the live preview part in "use client".
Starting with the template "Next.js - Simple Blog" we first create a .env.local
file with the following properties:
CAISY_PROJECT_ID
CAISY_API_KEY
NEXT_PUBLIC_USE_DRAFT_MODE=true
We use NEXT_PUBLIC_USE_DRAFT_MODE
as a way to enable the draft and live preview mode, but you can change this and use a more dynamic and maybe authorised approach if you want to restrict you preview mode to just authorised users later.
skip this next two steps if you already have your project running and you get updates form the graphql api in draft mode
Next, let’s start with what need to do on caisy in our project:
Get the CAISY_PROJECT_ID
If we go to the General Settings of our project, we can copy the projectId, and paste it under .env.local
/ CAISY_PROJECT_ID
Then we need to create an API key to be able to communicate with caisy
from an external source, we can create one by navigating to settings/development/api keys
and clicking on the CREATE API KEY
button:
Then copy the created key and paste it on the .env.local
/ CAISY_API_KEY
file
First go to your project settings in caisy and navigate to development -> previews and click on the "create preview" button
Secondly give your Preview any name and add a blueprint to it (we will use Page
in this example, please use the same blueprint to follow along)
After that add the Preview URL: here we need to link to the an API page we’ll be creating later, we also need to include the slug
parameter, this is the slug
field we have on the Page
blueprint, we use it to identify the part of the URL that will take us to the details of each blog article, for example /about
Further we add the project_id as a token, so we do not have to expose the the project_id as a public variable.
So the final input url for you Page preview should look like this: http://localhost:3000/{document_field.slug}?project_id={project_id}
if your app is running on port 3000.
Caisy will automatically replace the params in this url and attach another param: caisy_preview_access_token
to your preview url with your current token, when you open this preview in the ui.
Lastly you need to also turn on the Enable Live Preview
toggle
The changes for you previews save automatically
First of all, we need to install @caisy/live-preview-react
and @caisy/live-preview-javascript
libraries:
yarn add @caisy/live-preview-react @caisy/live-preview-javascript
or
npm install @caisy/live-preview-react @caisy/live-preview-javascript
The live preview logic for caisy consists of four main parts:
Setup event connection to caisy by calling using caisyLivePreview
Wrap you graphql response with useCaisyUpdates
Highlight editable components: Adding the global css for component edit editing styles and add "data-caisy-field-name" and "data-caisy-document-id" attributes to your html elements with a helper
Connection indicator: Showcase the current connection to the live preview data stream.
Here is an example that uses the nextjs router (pages) to pull the relevant params form the current page url and initates the caisyLivePreview
const router = useRouter();
const livePreviewEnabled =
`${process.env.NEXT_PUBLIC_USE_DRAFT_MODE}` === "true";
useEffect(() => {
if (typeof window === "undefined") return;
const token = router.query.caisy_preview_access_token as string;
const projectId = router.query.project_id as string;
if (!token || !projectId) {
return;
}
const close = caisyLivePreview({
projectId,
token,
locale: router.locale,
enabled: livePreviewEnabled,
});
return () => {
close && close();
};
}, [router.locale, router.query, livePreviewEnabled]);
This function initiates the live preview, and it takes 4 properties:
projectId: this is the ID of the project we fetch the content from
token: the preview access token coming from your account in caisy, to get this token read it form the current url.
locale(optional, default: en): since we have the functionality to add different locales to caisy, we can sync them here to fetch the correct data from the Document
enabled(optional, default: true): a boolean value to dynamically enable/disable the live-preview, in the example we use a primitive NEXT_PUBLIC_USE_DRAFT_MODE env variable, but this can be more dynamic
This useEffect can run in the _app.tsx or any other location of you app. But if this has not been started, everything else will not work.
This is how we connect caisy with our application, it takes all the documents/components we fetch from caisy as props, it then takes care of listening to the caisy documents, and reflects the changes on the value, as a result, it returns all the same fields it takes.
In order for this to work the results need to be fetched trough graphql and every document besides it fields also needs to have the id and __typename fetched from the external api. Like you see here:
{
allPage{
edges{
node{
id
__typename
components{
... on NewsletterSignup{
id
__typename
headline
subheadline
}
... on Headline{
id
__typename
headline
subheadline
}
... on Fulltext{
id
__typename
text{
json
}
}
}
}
}
}
}
This returned value is what we need to display on the UI, on our example we do it like this:
import { useCaisyUpdates } from "@caisy/live-preview-react";
export default function App({ Component, pageProps }: AppProps) {
...
const liveProps = useCaisyUpdates(pageProps);
return (
<>
<Navigation {...liveProps.Navigation} />
<Component {...liveProps} />
<Footer {...liveProps.Footer} />
</>
);
}
In order to make your fields being clickable with this edit button - we need to provide the library in the html the id of the document and the field name. Therefore we use the helper function getCaisyInspectProps
form "@caisy/live-preview-react"
This function is very simple:
function getCaisyInspectProps({ id, fieldName }: { id: string; fieldName: string }) {
return {
"data-caisy-document-id": id,
"data-caisy-field-name": fieldName,
};
}
and adds the necessary data attributes that the library needs to display this interface
but you need to add this everywhere, where you want the editor to be able to click the edit button.
For our example, we implement it like this in the Headline
component:
import { getCaisyInspectProps } from "@caisy/live-preview-react";
...
<div className="mb-8 flex flex-col justify-start items-center gap-2.5">
{headline && (
<h1
{...getCaisyInspectProps({ id: id, fieldName: "headline" })}
className="text-4xl font-bold text-left text-slate-900"
>
{headline}
</h1>
)}
{subheadline && (
<h4
{...getCaisyInspectProps({ id: id, fieldName: "subheadline" })}
className="mt-2 text-xl text-center text-gray-400"
>
{subheadline}
</h4>
)}
</div>
In order to get the result as in seen in the screenshot we need the above and some global css to be loaded to display the blue frames.
import "@caisy/live-preview-react/index.css";
The CaisyConnectionIndicator
component can be added in order to show the connection state.
import { CaisyConnectionIndicator } from "@caisy/live-preview-react";
...
return (
<>
{livePreviewEnabled && <CaisyConnectionIndicator />}
</>
)
If we put all of the above together (expect the the component getCaisyInspectProps
part) your _app.tsx might look like this. However you can split this up too and inject it on several levels of your app.
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import Head from "next/head";
import { Footer } from "../layouts/Footer";
import { Navigation } from "../layouts/Navigation";
import { useRouter } from "next/router";
import { useEffect } from "react";
import "@caisy/live-preview-react/index.css";
import {
CaisyConnectionIndicator,
caisyLivePreview,
useCaisyUpdates,
} from "@caisy/live-preview-react";
export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const livePreviewEnabled =
`${process.env.NEXT_PUBLIC_USE_DRAFT_MODE}` === "true";
useEffect(() => {
if (typeof window === "undefined") return;
const token = router.query.caisy_preview_access_token as string;
const projectId = router.query.project_id as string;
if (!token || !projectId) {
return;
}
const close = caisyLivePreview({
projectId,
token,
locale: router.locale,
enabled: livePreviewEnabled,
});
return () => {
close && close();
};
}, [router.locale, router.query, livePreviewEnabled]);
const livePageProps = useCaisyUpdates(pageProps);
return (
<>
<Head>
<meta name="viewport" content="width=device-width" />
</Head>
{livePreviewEnabled && <CaisyConnectionIndicator />}
{livePageProps.Navigation && <Navigation {...livePageProps.Navigation} />}
<Component {...livePageProps} />
{livePageProps.Footer && <Footer {...livePageProps.Footer} />}
</>
);
}
By clicking on the Eye Icon on the top right on any Page
document will open a window with the Preview URL
we set up before
If everything went well, we should see all the UI elements we mentioned, and any change made on the caisy document will be reflected on your application!
Subscribe to our newsletters
and stay updated
While you subscribe you agree to our Privacy Policy and Terms of Service apply.
Tags