61
loading...
This website collects cookies to deliver better user experience
node <=14.0.0
npm >=6.0.0
yarn
Strapi (v3.6.5)
Next.js (v.11.0.1)
git clone https://github.com/amirtds/strapi-sqlite
strapi-sqlite
yarn install && yarn develop
find
and count
permission to public.next-blog
using our example in the GitHub repo and run the development environment. Make sure you created some records in Strapi for Authors and Blogs before running this command.npx create-next-app next-blog --example "https://github.com/amirtds/blog/tree/develop"
cd next-blog
npm run dev
Image
Componentimport Image from 'next/image'
Image
. In our app, We also set the src as src={urlBuilder(post.image[0].url)}
{siteBlogs.map((post) => (
<Link key={post.id} href={`/blogs/${post.slug}`}>
<a>
<motion.div variants={fadeIn} key={post.id} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}className="flex flex-col rounded-lg shadow-lg overflow-hidden">
<div className="flex-shrink-0">
<Image width={600} height={350} className="h-48 w-full object-cover" src={urlBuilder(post.image[0].url)} alt={post.title} />
</div>
<div className="flex-1 bg-white p-6 flex flex-col justify-between">
<div className="flex-1">
<a href={post.href} className="block mt-2">
<p className="text-xl font-semibold text-gray-900">{post.title}</p>
<p className="mt-3 text-base text-gray-500">{post.description}</p>
</a>
</div>
<div className="mt-6 flex items-center">
<div className="flex-shrink-0">
<span className="sr-only">{post.author.name}</span>
<Image width={50} height={50} className="h-10 w-10 rounded-full" src={urlBuilder(post.author.photo[0].url)} alt={post.title} />
</div>
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">
{post.author.name}
</p>
<div className="flex space-x-1 text-sm text-gray-500">
<time dateTime={post.published}>{post.published}</time>
</div>
</div>
</div>
</div>
</motion.div>
</a>
</Link>
))}
*siteBlogs*
is an array that has a list of all of our blogs. We are looping over it and creating a blog card based on each blog item in this list. In the Image
src={urlBuilder(post.image[0].url)}
result will be STRAPI_URL/IMAGE_URL
for example http://localhost:1337/uploads/strapi_cover_1fabc982ce_1c5a5b390a.png
.domain
in next.config.js
. In this file, you should have something likemodule.exports = {
images: {
domains: ["localhost"],
},
}
module.exports = {
images: {
domains: [configs.STRAPI_DOMAIN],
},
}
configs.STRAPI_DOMAIN
is what we have in the configs.json
file for the Strapi domain./api/preview
, which adds preview mode cookies to your site. After successfully implementing this API, calls to it will add __prerender_bypass
and __next_preview_data
cookies.preview.js
file and add the following codes:// src/pages/api/preview.js
import { getPost } from 'lib/api'
export default async function handler(req, res) {
# Check if the user is requesting with valid token
if (req.query.secret !== (process.env.STRAPI_PREVIEW_SECRET)) {
return res.status(401).json({ message: "Invalid token" });
}
# Make sure the blog post actiually exits
const slug = req.query.slug
const blogData = await getPost(slug)
if (!blogData) {
return res.status(401).json({ message: "Invalid slug" });
}
# If all good we set preview cookies
# And we redirect the user to the preview version of the blog post
res.setPreviewData({});
res.writeHead(307, { Location: `/blogs/${slug}` });
res.end();
};
/api/exit-preview
. To return to SSG mode, we need to remove those cookies from our browser. This API will take care of that.// src/pages/api/exit-preview.js
export default async function exit(_, res) {
// Exit the current user from "Preview Mode". This function accepts no args.
res.clearPreviewData()
// Redirect the user back to the index page.
res.writeHead(307, { Location: "/" })
res.end()
}
context
object has a preview
attribute that returns true
or false
getStaticProps
function of your page, you can use context
as an argument, and based on the status of Preview, we fetch live or preview content from Strapi.// src/pages/blogs/[slug].js
export const getStaticProps = async (context) => {
const previewMode = context.preview == false || context.preview == null ? "live" : "preview"
const slug = context.params.slug
const BLOG_QUERY = gql`
query($slug: String, $previewMode: String){
blogs(where: {slug: $slug, _publicationState: $previewMode}){
id
title
subtitle
description
published
slug
image{
url
}
author {
name
photo {
url
}
}
content
}
}
`
const { data:blogData } = await apolloClient.query({
query: BLOG_QUERY,
variables: {
slug,
previewMode
},
preview: context.preview,
})
_publicationState
condition in our call that can be live
or Preview
.