Using Kontent Web Spotlight when developing locally with ngrok & Nextjs Preview Mode without deploying any code.

Using Kontent Web Spotlight when developing locally with ngrok & Nextjs Preview Mode without deploying any code.

I really like the way Kontent provides a way of editing your website instantly, without any code changes whilst completely separating the concept of content & application.

Kontent’s Web Spotlight feature is also a must have when creating a website with a headless CMS like Kontent. This feature really opens up the doors when editing websites, because it means a website can be viewed in real time giving website editors the ability to preview & directly edit website content changes in the context of how the website will finally look when these changes are promoted to a live environment. This allows for cross team collaboration when creating or updating content as well as a structured sign-off process with a strong separation of concern. Editors only need to know about the content itself, not how it is structured in Kontent or the various page blocks a page is built from.

I have recently been working on a project that required Web Spotlight functionality in a preview environment. After doing some research I found that Nextjs has some nice preview functionality in version 9.3+ which allows a website to be in a ‘Preview Mode’ context, after some testing & teething issues, it worked great with Kontent’s Web Spotlight feature.

Kontent has Preview URL functionality which means that you can configure this URL to point to a preview environment, I followed this approach and implemented a secret query string meaning we can restrict incoming requests for this preview route, so only incoming requests with the correct secret can pass through. This secures Kontent from being exposed accidently in a preview route context, or being indexed etc.

I created a [[…slug]].ts file in the pages/api/preview folder and the finished code looks like below.

import {NextApiRequest, NextApiResponse} from 'next'

export default async (request: NextApiRequest, response: NextApiResponse) => {
  if (request.query.secret !== process.env.KONTENT_PREVIEW_SECRET) {
    return response.status(401).json({message: 'request secret query parameter does not match application secret.'});

  if (!request.query.slug) {
    return response.status(400).json({message: 'missing required slug query parameter.'});

  response = setResponseCookieHeaderSameSitePolicy(response);
  response.writeHead(307, {Location: request.query.slug});

function setResponseCookieHeaderSameSitePolicy(response: NextApiResponse): NextApiResponse {
  const setCookieHeaders = response.getHeader('Set-Cookie') as string[];
  setCookieHeaders.forEach((cookie: string, index: number) => {
    setCookieHeaders[index] = cookie.replace('SameSite=Lax', 'SameSite=None;Secure');

  response.setHeader('Set-Cookie', setCookieHeaders);
  return response;

I needed to update the Same Site policy for the Set-Cookie headers to allow Kontent to correctly render this in an Iframe (This is what Spotlight does) whilst also maintaining the preview mode cookies after redirecting that Nextjs applies when you apply preview mode by calling response.setPreviewData({});

I reported this same site policy change that is required, back to Kontent once I got the fix working & they were super helpful & are updating the documentation to reflect this.

This means so far, we have Nextjs preview mode configured with an API route, that can enable Nextjs preview mode for an incoming request in this route that the request matches.

This is where it get’s interesting, after activating & configuring spotlight based on the Kontent documentation here: Kontent Configure Web Spotlight we can actually test our spotlight setup, and our Nextjs preview mode configuration, before actually doing a pull request, committing and deploying this integration code that we cannot test untill it’s been deployed. As Developers we do not want to close off any issues or commit any code into the main branch until we know it works locally right? Especially if we block and other development because these changes are across multiple pages. But without actually deploying this code to an environment how can we test the code we have added to integrate Web Spotlight? This is where ngrok comes into play. ngrok allows us to expose a local web server behind NATs and firewalls to the public internet over secure tunnels meaning we can share direct access to a local machine, whilst also managing TLS and providing a HTTPS URL for us to use.

Note – You can setup ngrok by following the docs here:

So let’s run ngrok after we have our website running so we can tunnel traffic to our web server using the following code, but substitute 3000 for the correct port you run the application on locally.

ngrok http 3000

This will provide us with a http & https forwarding url like this.

This means we can then route Kontents Web Spotlight Preview Traffic to the URL above by changing the preview URL for the content type in question like below, notice the secret query & value (This should be changed to a secure secret value)

Now let’s give it a test, we are expecting Kontent to render the Web Spotlight IFrame, using the Preview URL we entered above, allowing the request to match our preview route, also matching the file [[…slug]].ts then the secret query value will be validated against the configuration value. If successful & the slug has been entered too preview mode will be activated in Nextjs, the cookies will be added to the request the redirect to the non-preview page will occur. The preview mode cookies allow this non-preview page to have access to the props of the request, and use the preview property to pass down to the Kontent Delivery Client like below.

	const deliveryClient = new DeliveryClient({
			projectId: projectId || '',
			globalQueryConfig: {preview},

The final result is below, we have Web Spotlight loading the website in preview mode, correctly showing Kontent that is not fully published yet with the ability to edit this Kontent directly from the Spotlight screen and see all content together in a live preview. This means we can prove this code & integration works locally before we commit it into the development environment without causing any knock on effects or blocking changes required, this is also great if you need to show or continue website development whilst waiting for a separate team to create infrastructure for the website.

The preview mode banner is bonus functionality I have implemented that I will blog about in a future post. It allows you to see you the request is currently in preview mode, with the ability to exit preview mode by clicking the cross in the top right hand corner, removing the cookies, showing only published Kontent again inspired by the Kontent Starter Nextjs Template