Skip to content

Commit

Permalink
feat: support SSR-only mode
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Nov 8, 2023
1 parent 2c4fc5b commit 96d82f2
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 284 deletions.
5 changes: 3 additions & 2 deletions apps/remix/app/VisualEditing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { useLocation, useNavigate } from '@remix-run/react'
import { enableOverlays, type HistoryUpdate } from '@sanity/overlays'
import { studioUrl } from 'apps-common/env'
import { useEffect, useRef } from 'react'
import { useLiveMode } from './useQuery'
import { useLiveMode } from '~/sanity.loader'
import { client } from '~/sanity'

export default function VisualEditing() {
const navigateRemix = useNavigate()
Expand Down Expand Up @@ -41,7 +42,7 @@ export default function VisualEditing() {
}
}, [location.hash, location.pathname, location.search])

useLiveMode({ allowStudioOrigin: studioUrl })
useLiveMode({ allowStudioOrigin: studioUrl, client })

return null
}
76 changes: 0 additions & 76 deletions apps/remix/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,8 @@
import { studioUrl, workspaces } from 'apps-common/env'
import { vercelStegaCombine } from '@vercel/stega'
import { Link } from '@remix-run/react'
import { encodeSanityNodeData } from '~/sanity'

export default function Index() {
return (
<div className="flex flex-col items-center justify-center px-2 py-10">
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
type: 'shoe',
path: 'title',
})}
>
encodeSanityNodeData
</h1>
<h1>
{vercelStegaCombine('vercelStegaCombine', {
origin: 'sanity.io',
href: `${studioUrl}/intent/edit/id=0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2;path=title`,
})}
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
// type: 'shoe',
path: 'title',
})}
>
encodeSanityNodeData but minimal
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
type: 'shoe',
path: 'slug',
})}
>
encodeSanityNodeData but slug
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
type: 'shoe',
path: 'slug.current',
})}
>
encodeSanityNodeData but slug.current
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
type: 'shoe',
path: '',
})}
>
encodeSanityNodeData without a path
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '0e6fa235-3bd5-41cc-9f25-53dc0a5ff7d2',
type: 'shoe',
path: 'details.ledLifespan',
})}
>
encodeSanityNodeData but details.lifespan
</h1>
<h1
data-sanity={encodeSanityNodeData({
id: '1ca3ce94-688f-4f77-ac76-085b269735d6',
type: 'brand',
path: 'name',
projectId: workspaces['cross-dataset-references'].projectId,
dataset: workspaces['cross-dataset-references'].dataset,
workspace: workspaces['cross-dataset-references'].workspace,
tool: workspaces['cross-dataset-references'].tool,
})}
>
Cross Dataset Reference
</h1>
<hr className="max-w-32 my-8 h-px w-full border-0 bg-slate-200 dark:bg-slate-700" />
<Link to="/shoes">Shoes</Link>
</div>
Expand Down
55 changes: 21 additions & 34 deletions apps/remix/app/routes/shoes.$slug.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { PortableText } from '@portabletext/react'
import { Link, useLoaderData, useParams } from '@remix-run/react'
import { unwrapData, wrapData, sanity } from '@sanity/react-loader/jsx'
import { studioUrl, workspaces } from 'apps-common/env'
import { type ShoeParams, type ShoeResult, shoe } from 'apps-common/queries'
import { formatCurrency } from 'apps-common/utils'
import { urlFor, urlForCrossDatasetReference } from '~/utils'
import { useMemo } from 'react'
import { query, useQuery } from '~/useQuery'
import { urlFor, urlForCrossDatasetReference } from '~/sanity'
import { json, type LoaderFunction } from '@remix-run/node'
import { query } from '~/sanity.loader.server'
import { useQuery } from '~/sanity.loader'

export const loader: LoaderFunction = async ({ params }) => {
return json({
initialData: await query<ShoeResult>(shoe, params),
})
return json(await query<ShoeResult>(shoe, params))
}

export default function ShoePage() {
Expand All @@ -23,26 +19,19 @@ export default function ShoePage() {
throw new Error('No slug, 404?')
}

const { initialData } = useLoaderData<typeof loader>()
const { data: initialData } = useLoaderData<typeof loader>()
const {
data,
data: product,
error,
loading: _loading,
sourceMap,
} = useQuery<ShoeResult>(
shoe,
{
slug,
} satisfies ShoeParams,
{ initialData },
)
const loading = !data && _loading

const product = useMemo(
() =>
wrapData({ ...workspaces['remix'], baseUrl: studioUrl }, data, sourceMap),
[data, sourceMap],
)
const loading = !product && _loading

if (error) {
throw error
Expand Down Expand Up @@ -82,7 +71,7 @@ export default function ShoePage() {
>
{loading
? 'Loading'
: <sanity.span>{product?.title}</sanity.span> || 'Untitled'}
: <span>{product?.title}</span> || 'Untitled'}
</Link>
</li>
</ol>
Expand All @@ -94,13 +83,13 @@ export default function ShoePage() {
<div className="mx-auto max-w-2xl px-4 pt-16 sm:px-6 lg:max-w-7xl lg:px-8 lg:pt-24">
<img
className="aspect-video w-full rounded-md object-cover object-center group-hover:opacity-75 lg:rounded-lg"
src={urlFor(unwrapData(coverImage))
src={urlFor(coverImage)
.width(1280 * 2)
.height(720 * 2)
.url()}
width={1280}
height={720}
alt={coverImage.alt?.value || ''}
alt={coverImage.alt || ''}
/>
</div>
)}
Expand All @@ -119,13 +108,13 @@ export default function ShoePage() {
>
<img
className="h-32 w-40 shrink-0 rounded bg-white shadow-xl lg:rounded-lg"
src={urlFor(unwrapData(image))
src={urlFor(image)
.width(1280 / 2)
.height(720 / 2)
.url()}
width={1280 / 2}
height={720 / 2}
alt={image.alt?.value || ''}
alt={image.alt || ''}
/>
</div>
)
Expand All @@ -137,19 +126,19 @@ export default function ShoePage() {
{/* Product info */}
<div className="mx-auto max-w-2xl px-4 pb-16 pt-10 sm:px-6 lg:grid lg:max-w-7xl lg:grid-cols-3 lg:grid-rows-[auto,auto,1fr] lg:gap-x-8 lg:px-8 lg:pb-24 lg:pt-16">
<div className="lg:col-span-2 lg:border-r lg:border-gray-200 lg:pr-8">
<sanity.h1
<h1
className="text-2xl font-bold tracking-tight text-gray-900 sm:text-3xl"
style={{ ['textWrap' as any]: 'balance' }}
>
{product.title}
</sanity.h1>
</h1>
</div>

{/* Options */}
<div className="mt-4 flex flex-col gap-y-6 lg:row-span-3 lg:mt-0">
<h2 className="sr-only">Product information</h2>
<p className="text-3xl tracking-tight text-gray-900">
{product.price ? formatCurrency(product.price.value) : 'FREE'}
{product.price ? formatCurrency(product.price) : 'FREE'}
</p>

{product.brand?.name && (
Expand All @@ -160,23 +149,21 @@ export default function ShoePage() {
className="h-10 w-10 rounded-full bg-gray-50"
src={
product.brand?.logo?.asset
? urlForCrossDatasetReference(
unwrapData(product.brand.logo),
)
? urlForCrossDatasetReference(product.brand.logo)
.width(48)
.height(48)
.url()
: `https://source.unsplash.com/featured/48x48?${encodeURIComponent(
product.brand.name.value,
product.brand.name,
)}`
}
width={24}
height={24}
alt={product.brand?.logo?.alt?.value || ''}
alt={product.brand?.logo?.alt || ''}
/>
<sanity.span className="text-lg font-bold">
<span className="text-lg font-bold">
{product.brand.name}
</sanity.span>
</span>
</div>
</div>
)}
Expand All @@ -198,7 +185,7 @@ export default function ShoePage() {

<div className="space-y-6 text-base text-gray-900">
{product.description ? (
<PortableText value={unwrapData(product.description)} />
<PortableText value={product.description} />
) : (
'No description'
)}
Expand Down
57 changes: 23 additions & 34 deletions apps/remix/app/routes/shoes._index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import { Link, useLoaderData } from '@remix-run/react'
import { unwrapData, wrapData, sanity } from '@sanity/react-loader/jsx'
import { studioUrl, workspaces } from 'apps-common/env'
import { formatCurrency } from 'apps-common/utils'
import { shoesList, type ShoesListResult } from 'apps-common/queries'
import { urlFor, urlForCrossDatasetReference } from '~/utils'
import { useMemo } from 'react'
import { useQuery, query } from '~/useQuery'
import { json } from '@remix-run/node'
import { useQuery } from '~/sanity.loader'
import { query } from '~/sanity.loader.server'
import { urlFor, urlForCrossDatasetReference } from '~/sanity'

export const loader = async () => {
return json(await query<ShoesListResult>(shoesList))
}

export default function ShoesPage() {
const { data: initialData } = useLoaderData<typeof loader>()
const { data: initialData, sourceMap: initialSourceMap } =
useLoaderData<typeof loader>()
const {
data,
data: products,
error,
loading: _loading,
sourceMap,
} = useQuery<ShoesListResult>(shoesList, {}, { initialData })
const loading = !data?.length && _loading

const products = useMemo(
() =>
wrapData({ ...workspaces['remix'], baseUrl: studioUrl }, data, sourceMap),
[data, sourceMap],
} = useQuery<ShoesListResult>(
shoesList,
{},
{ initialData, initialSourceMap },
)
const loading = !products?.length && _loading

if (error) {
throw error
Expand Down Expand Up @@ -59,62 +55,55 @@ export default function ShoesPage() {
<div className="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8">
{products?.map?.((product, i) => (
<Link
key={product.slug.current.value}
to={`/shoes/${product.slug.current.value}`}
key={product.slug.current}
to={`/shoes/${product.slug.current}`}
className="group relative"
>
<div className="aspect-h-1 aspect-w-1 xl:aspect-h-8 xl:aspect-w-7 w-full overflow-hidden rounded-lg bg-gray-200">
<img
className="h-full w-full object-cover object-center group-hover:opacity-75"
src={
product.media?.asset
? urlFor(unwrapData(product.media))
.width(1440)
.height(1440)
.url()
? urlFor(product.media).width(1440).height(1440).url()
: `https://source.unsplash.com/featured/720x720?shoes&r=${i}`
}
width={720}
height={720}
alt={product.media?.alt?.value || ''}
alt={product.media?.alt || ''}
/>
</div>
<sanity.h2
<h2
className="mb-8 mt-4 text-sm text-gray-700"
style={{ ['textWrap' as any]: 'balance' }}
>
{product.title}
</sanity.h2>
</h2>
<p className="absolute bottom-0 left-0 mt-1 text-lg font-medium text-gray-900">
{product.price?.value
? formatCurrency(product.price.value)
: 'FREE'}
{product.price ? formatCurrency(product.price) : 'FREE'}
</p>
{product.brand && (
<div className="absolute bottom-0.5 right-0 flex items-center gap-x-2">
<img
className="h-6 w-6 rounded-full bg-gray-50"
src={
product.brand?.logo?.asset
? urlForCrossDatasetReference(
unwrapData(product.brand.logo),
)
? urlForCrossDatasetReference(product.brand.logo)
.width(48)
.height(48)
.url()
: `https://source.unsplash.com/featured/48x48?${
product.brand.name
? encodeURIComponent(product.brand.name.value)
? encodeURIComponent(product.brand.name)
: `brand&r=${i}`
}`
}
width={24}
height={24}
alt={product.brand?.logo?.alt?.value || ''}
alt={product.brand?.logo?.alt || ''}
/>
<sanity.span className="font-bold text-gray-600">
<span className="font-bold text-gray-600">
{product.brand.name}
</sanity.span>
</span>
</div>
)}
</Link>
Expand Down
6 changes: 6 additions & 0 deletions apps/remix/app/sanity.loader.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { client } from './sanity'
import { server__query, setServerClient } from './sanity.loader'

setServerClient(client)

export { server__query as query }
8 changes: 8 additions & 0 deletions apps/remix/app/sanity.loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createQueryStore } from '@sanity/react-loader'

export const {
query: server__query,
useQuery,
setServerClient,
useLiveMode,
} = createQueryStore({ client: false, ssr: true })
Loading

5 comments on commit 96d82f2

@vercel
Copy link

@vercel vercel bot commented on 96d82f2 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visual-editing-remix – ./apps/remix

visual-editing-remix-git-main.sanity.build
visual-editing-remix.sanity.build

@vercel
Copy link

@vercel vercel bot commented on 96d82f2 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visual-editing-page-builder-demo – ./apps/page-builder-demo

visual-editing-page-builder-demo-git-main.sanity.build
visual-editing-page-builder-demo.sanity.build

@vercel
Copy link

@vercel vercel bot commented on 96d82f2 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visual-editing-svelte – ./apps/svelte

visual-editing-svelte.sanity.build
visual-editing-svelte-git-main.sanity.build

@vercel
Copy link

@vercel vercel bot commented on 96d82f2 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visual-editing-studio – ./apps/studio

visual-editing-studio.sanity.build
visual-editing-studio-git-main.sanity.build

@vercel
Copy link

@vercel vercel bot commented on 96d82f2 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visual-editing-nuxt – ./apps/nuxt

visual-editing-nuxt.sanity.build
visual-editing-nuxt-git-main.sanity.build

Please sign in to comment.