Skip to content

Commit

Permalink
get live preview working
Browse files Browse the repository at this point in the history
  • Loading branch information
SimeonGriggs committed Nov 16, 2022
1 parent 5bc369c commit 75b3ce9
Show file tree
Hide file tree
Showing 18 changed files with 271 additions and 205 deletions.
13 changes: 10 additions & 3 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
SANITY_PROJECT_ID=6h1mv88x
SANITY_DATASET=production
SANITY_API_VERSION=2022-09-23
# These will be added to the window so the Studio can read them
SANITY_PUBLIC_PROJECT_ID="6h1mv88x"
SANITY_PUBLIC_DATASET="production"
SANITY_PUBLIC_API_VERSION="2022-09-23"

# A random string checked server-side to enable preview mode
SANITY_PREVIEW_SECRET=

# Generated in sanity.io/manage
SANITY_READ_TOKEN=
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@

## Includes:

Useful Sanity examples with a light sprinkling of opinionated patterns

- Sanity Studio v3 embedded in the `/studio` route
- Styled Components SSR support for the `/studio` route
- Live Preview powered by [@sanity/plugin-kit](https://github.com/sanity-io/preview-kit)
- Example Sanity Studio config and schema
- Example Portable Text Component
- Example Image Builder Component
- Example Portable Text Component using [@portabletext/react](https://github.com/portabletext/react-portabletext)
- Example Image Builder Component using [@sanity/image-url](https://github.com/sanity-io/image-url)
- Validated and Typed GROQ query results using [Zod](https://zod.dev/)
- eslint and Prettier
- Tailwind CSS for the front-end
- Tailwind CSS with presets by [@sanity/demo](https://github.com/sanity-io/demo)
- Tailwind Prose and Prettier plugins

## Development
Expand Down
13 changes: 5 additions & 8 deletions app/components/Product.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import {definePreview} from '@sanity/preview-kit'

import Layout from '~/components/Layout'
import SanityContent from '~/components/SanityContent'
import type {ProductDocument} from '~/sanity/types/Product'
import {projectDetails} from '~/sanity/projectDetails'
import type {Product as ProductDocument} from '~/types/product'

export default function Product(props: ProductDocument) {
const {title, content, token} = props
const data = usePreview(token, `*[]`)
const {title, content} = props

return (
<Layout>
Expand All @@ -21,21 +20,19 @@ export default function Product(props: ProductDocument) {
}

type PreviewProductProps = {
product: ProductDocument
query: string
params: {[key: string]: string}
token: string
}

const {projectId, dataset} = projectDetails()

const usePreview = definePreview({projectId, dataset})

export function PreviewProduct(props: PreviewProductProps) {
const {product, query, params, token} = props
console.log(`initial data`, product)
const {query, params, token} = props
console.log(props)

const data = usePreview(token, query, params)
const data = usePreview(token ? token : null, query, params)

return <Product {...data} />
}
10 changes: 10 additions & 0 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export default function App() {
<Meta />
<Links />
{isStudioRoute && typeof document === 'undefined' ? '__STYLES__' : null}
{isStudioRoute ? null : (
<>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@500;700&family=Inter:wght@500;700;800&family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
/>
</>
)}
</head>
<body className="min-h-screen bg-white">
<Outlet />
Expand Down
47 changes: 30 additions & 17 deletions app/routes/$slug.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
import type {LinksFunction, LoaderArgs} from '@remix-run/node'
import type {LinksFunction, LoaderArgs, ResponseInit} from '@remix-run/node'
import {json} from '@remix-run/node'
import {useLoaderData} from '@remix-run/react'
import groq from 'groq'
import {PreviewSuspense} from '@sanity/preview-kit'

import styles from '~/styles/app.css'
import Product, {PreviewProduct} from '~/components/Product'
import {client} from '~/sanity/client'
import type {ProductDocument} from '~/sanity/types/Product'

import styles from '~/styles/app.css'
import {productZ} from '~/types/product'

export const links: LinksFunction = () => {
return [{rel: 'stylesheet', href: styles}]
}

export const loader = async ({params}: LoaderArgs) => {
const preview = true
const query = groq`*[_type == "product" && slug.current == $slug][0]`
const product: ProductDocument | null = await client.fetch(query, params)
export const loader = async ({params, request}: LoaderArgs) => {
// If the URL contained a 'secret' query param and it matches the one on the server
const requestUrl = new URL(request.url)
const preview = requestUrl.searchParams.get('secret') === process.env.SANITY_PREVIEW_SECRET
const token = preview ? process.env.SANITY_READ_TOKEN : null

// TODO: Create a 'session' to store preview authentication
// TODO: Exit-preview route

const query = groq`*[_type == "product" && slug.current == $slug][0]{
title,
"slug": slug.current,
images,
content
}`

const product = await client
// Params from the loader uses the filename
// $slug.tsx has the params { slug: 'hello-world' }
.fetch(query, params)
// Parsed with Zod to validate data at runtime
// and generate a Typescript type
.then((res) => productZ.parse(res))

if (!product) {
return new Response('Not found', {status: 404})
Expand All @@ -28,22 +46,17 @@ export const loader = async ({params}: LoaderArgs) => {
preview,
query: preview ? query : null,
params: preview ? params : null,
token: preview ? token : null,
})
}

export default function ProductPage() {
const {product, preview, query, params} = useLoaderData<typeof loader>()
const {product, preview, query, params, token} = useLoaderData<typeof loader>()

if (preview) {
return (
<PreviewSuspense fallback="Loading...">
<PreviewProduct
product={product}
query={query}
params={params}
// TODO: REMOVE THIS BEFORE DEPLOYING
token="asdf"
/>
<PreviewSuspense fallback={<Product {...product} />}>
<PreviewProduct query={query} params={params} token={token} />
</PreviewSuspense>
)
}
Expand Down
16 changes: 2 additions & 14 deletions app/routes/studio/*.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import type {LinksFunction, MetaFunction} from '@remix-run/node'
import {ClientOnly} from 'remix-utils'
import {Studio, defineConfig} from 'sanity'
import {deskTool} from 'sanity/desk'

import {projectDetails} from '~/sanity/projectDetails'
import schema from '~/sanity/schema'
import {Studio} from 'sanity'
import {config} from '~/sanity/sanity.config'

import styles from '~/styles/studio.css'

Expand All @@ -13,15 +10,6 @@ export const meta: MetaFunction = () => ({
robots: 'noindex',
})

const config = defineConfig({
...projectDetails(),
plugins: [deskTool()],
basePath: `/studio`,
schema: {
types: schema,
},
})

export const links: LinksFunction = () => {
return [{rel: 'stylesheet', href: styles}]
}
Expand Down
27 changes: 20 additions & 7 deletions app/sanity/projectDetails.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
export const projectDetails = () => ({
projectId:
typeof document === 'undefined' ? process.env.SANITY_PROJECT_ID : window?.ENV?.projectId,
dataset: typeof document === 'undefined' ? process.env.SANITY_DATASET : window?.ENV?.dataset,
apiVersion:
typeof document === 'undefined' ? process.env.SANITY_API_VERSION : window?.ENV?.apiVersion,
})
declare global {
interface Window {
ENV: {
SANITY_PUBLIC_PROJECT_ID: string
SANITY_PUBLIC_DATASET: string
SANITY_PUBLIC_API_VERSION: string
}
}
}

export const projectDetails = () => {
const {SANITY_PUBLIC_PROJECT_ID, SANITY_PUBLIC_DATASET, SANITY_PUBLIC_API_VERSION} =
typeof document === 'undefined' ? process.env : window.ENV

return {
projectId: SANITY_PUBLIC_PROJECT_ID ?? `pnkijp0b`,
dataset: SANITY_PUBLIC_DATASET ?? `remix`,
apiVersion: SANITY_PUBLIC_API_VERSION ?? `2022-09-23`,
}
}
16 changes: 16 additions & 0 deletions app/sanity/sanity.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {defineConfig} from 'sanity'
import {deskTool} from 'sanity/desk'

import {projectDetails} from '~/sanity/projectDetails'
import schema from '~/sanity/schema'

export const config = defineConfig({
...projectDetails(),
name: 'sanity-remix',
title: 'Sanity Remix',
plugins: [deskTool()],
basePath: `/studio`,
schema: {
types: schema,
},
})
20 changes: 20 additions & 0 deletions app/sanity/schema/category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {defineType, defineField} from 'sanity'

export default defineType({
name: 'category',
title: 'Category',
type: 'document',
fields: [
defineField({
name: 'title',
type: 'string',
}),
defineField({
name: 'slug',
type: 'slug',
options: {
source: 'title',
},
}),
],
})
3 changes: 2 additions & 1 deletion app/sanity/schema/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import category from './category'
import product from './product'

export default [product]
export default [product, category]
16 changes: 16 additions & 0 deletions app/sanity/schema/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,21 @@ export default defineType({
type: 'array' as const,
of: [{type: 'block'}, {type: 'image'}],
}),
defineField({
name: 'images',
type: 'array',
of: [
defineField({
name: 'image',
type: 'image',
options: {hotspot: true},
}),
],
}),
defineField({
name: 'category',
type: 'reference',
to: [{type: 'category'}],
}),
],
})
9 changes: 0 additions & 9 deletions app/sanity/types/Product.ts

This file was deleted.

Loading

0 comments on commit 75b3ce9

Please sign in to comment.