NextJS: Short URL for Viewing Layout Service Response

The age of JSS + Headless + NextJS is all about quality of life improvements for developers. Here's a good one for you.
Often, it's helpful to be able to ping the layout service to see what data you're working with. The problem is that the URL is tricky to remember. You could bookmark it, but what about other devs who don't have the bookmark? Let's make it easier for everyone.
// This code makes it easier to ping your layout service without having to remember the long URL that is accessible by default.// Add this file to /pages/api/viewpage or wherever you want.// From there, all you need to do is visit /api/viewpage to view the layout service response for your home page// Subpage would be /api/viewpage/someSubPageimport type { NextApiRequest, NextApiResponse } from 'next';
const handler = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => { const apiHost = process.env.SITECORE_API_HOST ? process.env.SITECORE_API_HOST : `https://mysite.sc`;
const siteName = process.env.NEXT_PUBLIC_JSS_SITE_NAME ? process.env.NEXT_PUBLIC_JSS_SITE_NAME : `main`;
const apiKey = process.env.SITECORE_API_KEY ? process.env.SITECORE_API_KEY : `{CHANGEME}`;
const { path } = req.query; const itemPath = path ? path : '/';
if (typeof itemPath === 'string') { queryStringPath = itemPath; } else { queryStringPath = itemPath.join('/'); }
const layoutServiceResponse = await fetch( `${apiHost}/sitecore/api/layout/render/jss/?sc_lang=en&sc_site=${siteName}&sc_apikey=${apiKey}&item=${queryStringPath}` );
res.status(200).json(await layoutServiceResponse.json());};
export default handler;The above solution may not work in all cases. The solution above is for a solution that's configured with REST, however content can also be fetched with GraphQL, and that's where everything is headed (Experience Edge / XM Cloud). I haven't looked yet, but the layout service may not be present, or the method by which one could fetch that data may be different.
Another possible (and potentially more future proof) solution is:
// [[...path]].tsimport type { NextApiRequest, NextApiResponse } from 'next';import { GetServerSidePropsContext, GetStaticPropsContext } from 'next';import { sitecorePagePropsFactory } from 'lib/page-props-factory';
const handler = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => { const { path } = req.query;
const context: GetServerSidePropsContext | GetStaticPropsContext = { params: { path: path, }, };
const props = await sitecorePagePropsFactory.create(context);
res.status(200).json(props.layoutData);};
export default handler;// layout-service-factory.tsimport { LayoutService, RestLayoutService, GraphQLLayoutService,} from '@sitecore-jss/sitecore-jss-nextjs';import config from 'temp/config';
export class LayoutServiceFactory { create(): LayoutService { return process.env.FETCH_WITH === 'GraphQL' ? new GraphQLLayoutService({ endpoint: config.graphQLEndpoint, apiKey: config.sitecoreApiKey, siteName: config.jssAppName, }) : new RestLayoutService({ apiHost: config.sitecoreApiHost, apiKey: config.sitecoreApiKey, siteName: config.jssAppName,
// CHANGE THIS FROM 'default' TO 'jss' configurationName: 'jss', }); }}
export const layoutServiceFactory = new LayoutServiceFactory();Note that this endpoint will be PUBLICLY VIEWABLE, so make sure to lock it down somehow, possibly with this or WAF rules.
Pair this solution with a browser extension that formats JSON, and you're off to the races.
-MG





