Skip to content

Instantly share code, notes, and snippets.

@yhunko
Created December 26, 2023 09:17
Show Gist options
  • Save yhunko/fa713bcf7169f6bdf365184084ab6ccf to your computer and use it in GitHub Desktop.
Save yhunko/fa713bcf7169f6bdf365184084ab6ccf to your computer and use it in GitHub Desktop.
Sanity CMS setup steps

Create a Sanity Studio project

  • pnpm create sanity@latest
  • cd project-name
  • nr dev
  • Studio should be running

Configure Sanity Studio project

  • add env variables (local / dev example)
    • SANITY_STUDIO_DATASET=development
    • SANITY_STUDIO_TITLE="Blog (DEV)"
    • SANITY_STUDIO_PROD_URL=http://localhost:3882
    • SANITY_STUDIO_PREVIEW_SECRET=randomly-generated-string
      • !!! should be equal to env variable in FE project SANITY_PREVIEW_SECRET
  • configure studio - use code snippets from files below

Configure Next FE project

  • install next-sanity
    • ni next-sanity
  • add env variables (local / dev example)
    • NEXT_PUBLIC_SANITY_DATASET=development
    • NEXT_PUBLIC_SANITY_PROJECT_ID=studio_project_id
    • SANITY_PREVIEW_SECRET=same_as_in_studio_env
    • SANITY_API_READ_TOKEN=
      • See "Add / obtain Sanity configs" section below

Add / obtain Sanity configs

  • Manage project > API > Tokens > Add Token
  • Generate a READ_ONLY preview token
import { BlogPostPage } from 'pages/blog-post/BlogPost.page';
const PreviewBlogPostPage = dynamic(() => import('pages/blog-post/PreviewBlogPost.page'), {
ssr: false,
});
export const getStaticPaths: GetStaticPaths = async () => {
const paths = await sanityClient.fetch(
groq`*[_type == "post" && defined(slug.current)][]{
"params": { "slug": slug.current }
}`,
);
// Use `fallback: false`, to return 404 page
// if slug is not in the list of available ones
return { paths, fallback: true };
};
type BlogPostPreviewDataType = {
token: string | null;
};
export const getStaticProps: GetStaticProps<
{ [key: string]: any },
any,
BlogPostPreviewDataType
> = async ({ params, preview = false, previewData = {} }) => {
const queryParams: GetPostBySlugParams = { slug: `${params?.slug}`};
try {
let post;
if (preview) {
post = await getSanityClient(previewData?.token).fetch(getPostQuery.query, queryParams);
return { props: { preview, token: previewData.token ?? null, initialData: post } };
}
post = await SanityApi.getPost(queryParams);
// Can be used to be 100% sure if the post exist
// should be used with `fallback: true` in getStaticPaths
if (!post) {
return {
notFound: true,
};
}
const queryClient = new QueryClient();
queryClient.setQueryData([QueryKeys.POST, queryParams], post);
return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
} catch (e) {
return {
notFound: true,
};
}
};
const Page: FC<{ preview?: boolean; token: string | null; initialData: PostSelection }> = ({
preview,
token,
initialData,
}) => {
return preview && token ? (
<SanityPreviewProvider token={token}>
<MainLayout>
<PreviewBlogPostPage initialData={initialData} />
</MainLayout>
</SanityPreviewProvider>
) : (
<MainLayout>
<BlogPostPage />
</MainLayout>
);
};
export default Page;
import { q } from 'groqd';
import { useLiveQuery } from 'next-sanity/preview';
import { BlogPostPage } from './BlogPost.page';
type PreviewBlogPostPageProps = {
initialData: PostSelection;
};
const PreviewBlogPostPage: FC<PreviewBlogPostPageProps> = ({ initialData }) => {
const router = useRouter();
const [previewData, loading] = useLiveQuery<PostSelection>(
initialData,
q('*').filterByType('post').filter('slug.current == $slug').grab(postSelection).slice(0).query,
{
slug: `${router?.query?.slug}` ?? '',
},
);
if (loading) return 'Loading...';
return <BlogPostPage previewData={previewData} />;
};
export default PreviewBlogPostPage;
import { createClient } from 'next-sanity';
export const dataset = env.SANITY_DATASET;
export const projectId = env.SANITY_PROJECT_ID;
export const getSanityClient = (token?: string | null) => {
const client = createClient({
projectId,
dataset,
useCdn: process.env.NODE_ENV === 'production' && env.ENV_NAME === 'production',
apiVersion: '2021-10-21',
});
return token
? client.withConfig({
token,
useCdn: false,
ignoreBrowserTokenWarning: true,
perspective: 'previewDrafts',
})
: client;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment