Skip to content

Instantly share code, notes, and snippets.

@beamercola
Last active January 10, 2022 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beamercola/d2c55f50450e1930fd4616674f1d8cb4 to your computer and use it in GitHub Desktop.
Save beamercola/d2c55f50450e1930fd4616674f1d8cb4 to your computer and use it in GitHub Desktop.
// pages/[slug.tsx]
import { GetStaticPropsContext } from "next"
import Head from "next/head"
import { useRouter } from "next/router"
import useUpdatePreviewRef from "../utils/useUpdatePreviewRef"
import { Client } from "~/../prismic.client"
import SliceZone from "~/Slices/Zone"
import Loader from "~/Loader"
const Page = ({ page, previewRef }) => {
const router = useRouter()
if (router.isFallback || !page) return <Loader />
console.log("Page", page)
useUpdatePreviewRef(previewRef, page.id)
return (
<>
<Head>
<title>Wonder Valley</title>
</Head>
<SliceZone slices={page.body} />
</>
)
}
export default Page
export async function getStaticPaths() {
return {
paths: [],
fallback: true,
}
}
export async function getStaticProps(context: GetStaticPropsContext) {
const previewRef = context.previewData ? context.previewData["ref"] : null
const refOption = previewRef ? { ref: previewRef } : null
console.log("context.previewData", context.previewData)
const page = await Client().getByUID(
"page",
context.params.slug as string,
refOption
)
console.log(page)
return {
props: { page: { ...page.data, id: page.id }, previewRef },
}
}
import Document, { Html, Head, Main, NextScript } from "next/document"
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head>
<script
async
defer
src={`//static.cdn.prismic.io/prismic.js?repo=${process.env.PRISMIC_NAME}&new=true`}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
{
"name": "wondervalley",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"chromatic": "npx chromatic --project-token=d5bb55a38b2d",
"slicemachine": "start-slicemachine",
"sm": "start-slicemachine"
},
"dependencies": {
"@prismicio/client": "^6.0.0",
"@prismicio/helpers": "^2.0.0",
"@prismicio/react": "^2.0.2",
"@shopify/hydrogen": "^0.8.0",
"@takeshape/routing": "^8.15.0",
"autoprefixer": "^10.4.0",
"dotenv": "^10.0.0",
"graphql-tag": "^2.12.6",
"js-cookie": "^3.0.1",
"next": "^12.0.7",
"next-slicezone": "^0.1.3",
"next-transpile-modules": "^9.0.0",
"phosphor-react": "^1.2.1",
"prismic-reactjs": "^1.3.4",
"react": "^18.0.0-beta-24dd07bd2-20211208",
"react-dom": "^18.0.0-beta-24dd07bd2-20211208",
"react-inner-image-zoom": "^2.1.0",
"react-router-dom": "^6.0.2",
"react-sticky-box": "^0.9.3",
"swiper": "^6.7.1"
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@storybook/addon-actions": "^6.3.13",
"@storybook/addon-essentials": "^6.3.13",
"@storybook/addon-links": "^6.3.13",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.3.13",
"@storybook/manager-webpack5": "^6.3.13",
"@storybook/preset-scss": "^1.0.3",
"@storybook/preset-typescript": "^3.0.0",
"@storybook/react": "^6.3.13",
"@tailwindcss/aspect-ratio": "^0.4.0",
"@tailwindcss/typography": "^0.5.0",
"@types/node": "^17.0.8",
"@types/react": "^17.0.38",
"babel-loader": "^8.2.2",
"chromatic": "^5.9.2",
"postcss": "^8.4.5",
"postcss-loader": "^6.2.1",
"sass": "^1.43.4",
"sass-loader": "^12.3.0",
"slice-machine-ui": "^0.1.2",
"storybook-dark-mode": "^1.0.8",
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.12",
"typescript": "^4.4.4",
"webpack": "5"
}
}
// pages/api/preview.ts
import { NextApiRequest, NextApiResponse } from "next"
import { Client, linkResolver } from "../../prismic.client"
export default async (req: NextApiRequest, res: NextApiResponse) => {
const { token: ref } = req.query
const redirectUrl = await Client(req).resolvePreviewURL({
linkResolver,
defaultURL: "/home",
})
if (!redirectUrl) {
return res.status(401).json({ message: "Invalid token" })
}
res.setPreviewData({ ref })
res.write(
`<!DOCTYPE html><html><head><meta http-equiv="Refresh" content="0; url=${redirectUrl}" />
<script>window.location.href = '${redirectUrl}'</script>
</head>`
)
res.end()
}
// ~/utils/prismicHelpers.js
import { Client as PrismicClient, createClient } from "@prismicio/client"
// Helper function to convert Prismic Rich Text links to Next/Link components
// export const customLink = (type, element, content, children, index) => (
// <Link key={index} href={linkResolver(element.data)}>
// <a>{content}</a>
// </Link>
// )
// -- Route Resolver rules
// Manages the url links to internal Prismic documents two levels deep (optionals)
export const Router = {
routes: [
{
type: "page",
path: "/:uid",
},
],
}
// -- Link resolution rules
// Manages the url links to internal Prismic documents
export const linkResolver = doc => {
console.log("doc", doc)
if (doc.type === "page") {
return `/${doc.uid}`
}
return "/"
}
// -- @prismicio/client initialisation
// Initialises the Prismic Client that's used for querying the API and passes it any query options.
export const Client = (req = null): PrismicClient =>
createClient(
`https://${process.env.PRISMIC_NAME}.cdn.prismic.io/api/v2`,
createClientOptions(req, process.env.PRISMIC_TOKEN, Router)
)
// Options to be passed to the Client
const createClientOptions = (
req = null,
prismicAccessToken: string | undefined,
routes: any = null
) => {
const reqOption = req ? { req } : {}
const accessTokenOption = prismicAccessToken
? { accessToken: prismicAccessToken }
: {}
const routesOption = routes ? { routes: Router.routes } : {}
return {
...reqOption,
...accessTokenOption,
...routesOption,
}
}
export default Client
// utils/useUpdatePreviewRef.js
import { useEffect } from "react"
import { useRouter } from "next/router"
import Cookies from "js-cookie"
function getExitPreviewRoute(router) {
const defaultPreviewExitUrl = "/api/exit-preview"
const linkUrl = router.asPath
? `${defaultPreviewExitUrl}?currentUrl=${router.asPath}`
: defaultPreviewExitUrl
return linkUrl
}
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
export default function useUpdatePreviewRef(previewRef, documentId) {
const router = useRouter()
const previewExitRoute = getExitPreviewRoute(router)
useEffect(() => {
const updatePreview = async () => {
await timeout(1000)
const rawPreviewCookie = Cookies.get("io.prismic.preview")
const previewCookie = rawPreviewCookie
? JSON.parse(rawPreviewCookie)
: null
const previewCookieObject = previewCookie
? previewCookie[`${process.env.PRISMIC_NAME}.prismic.io`]
: null
const previewCookieRef =
previewCookieObject && previewCookieObject.preview
? previewCookieObject.preview
: null
if (router.isPreview) {
if (rawPreviewCookie && previewCookieRef) {
if (previewRef !== previewCookieRef) {
return router.push(
`/api/preview?token=${previewCookieRef}&documentId=${documentId}`
)
}
} else {
return router.push(previewExitRoute)
}
} else if (rawPreviewCookie && previewCookieRef) {
return router.push(
`/api/preview?token=${previewCookieRef}&documentId=${documentId}`
)
}
return undefined
}
updatePreview()
}, [])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment