Skip to content

Commit

Permalink
feat: add Studio v3 embed support
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Aug 12, 2022
1 parent 918743d commit 4edd5d0
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 2 deletions.
171 changes: 170 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# next-sanity
# next-sanity<!-- omit in toc -->

[Sanity.io](https://www.sanity.io/?utm_source=github&utm_medium=readme&utm_campaign=next-sanity) toolkit for Next.js.

**Features:**

- Client-side live real-time preview for authenticated users
- GROQ syntax highlighting
- [Embed](#next-sanitystudio-dev-preview) [Studio v3](https://www.sanity.io/studio-v3) in [Next.js](https://nextjs.org/) apps

## Table of contents

Expand All @@ -16,7 +17,15 @@
- [Optimizing bundle size](#optimizing-bundle-size)
- [Usage](#usage)
- [Example: Minimal blog post template](#example-minimal-blog-post-template)
- [`next-sanity/studio` (dev-preview)](#next-sanitystudio-dev-preview)
- [Usage](#usage-1)
- [Opt-in to using `StudioProvider` and `StudioLayout`](#opt-in-to-using-studioprovider-and-studiolayout)
- [Customize `<ServerStyleSheetDocument />`](#customize-serverstylesheetdocument-)
- [Full-control mode](#full-control-mode)
- [Migrate](#migrate)
- [From `v0.4`](#from-v04)
- [`createPortableTextComponent` is removed](#createportabletextcomponent-is-removed)
- [`createImageUrlBuilder` is removed](#createimageurlbuilder-is-removed)
- [License](#license)

## Installation
Expand Down Expand Up @@ -203,6 +212,166 @@ export async function getStaticPaths() {
}
```
## `next-sanity/studio` (dev-preview)
> [See it live](https://next.sanity.build/)
The latest version of Sanity Studio allows you to embed a near-infinitely configurable content editing interface into any React application. This opens up many possibilities:
- Any service that hosts Next.js apps can now host your Studio.
- Building previews for your content is easier as your Studio lives in the same environment.
- Use [Data Fetching](https://nextjs.org/docs/basic-features/data-fetching/overview) to configure your Studio.
- Easy setup of [Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode).
### Usage
The basic setup is two files:
1. `pages/[[...index]].tsx`
```tsx
// Import your sanity.config.ts file
import config from '../sanity.config'
import {NextStudio} from 'next-sanity/studio'

export default function StudioPage() {
// Loads the Studio, with all the needed neta tags and global CSS reqiired for it to render correctly
return <NextStudio config={config} />
}
```
The `<NextStudio />` wraps `<Studio />` component and supports forwarding all its props:
```tsx
import {Studio} from 'sanity'
```
2. `pages/_document.tsx`
```tsx
import {ServerStyleSheetDocument} from 'next-sanity/studio'

// Set up SSR for styled-components, ensuring there's no missing CSS when deploying a Studio in Next.js into production
export default class Document extends ServerStyleSheetDocument {}
```
### Opt-in to using `StudioProvider` and `StudioLayout`
If you want to go lower level and have more control over the studio you can pass `StudioProvider` and `StudioLayout` from `sanity` as `children`:
```tsx
import {NextStudio} from 'next-sanity/studio'
import {StudioProvider, StudioLayout} from 'sanity'

import config from '../sanity.config'

function StudioPage() {
return (
<NextStudio config={config}>
<StudioProvider config={config}>
{/* Put components here and you'll have access to the same React hooks as Studio gives you when writing plugins */}
<StudioLayout />
</StudioProvider>
</NextStudio>
)
}
```
### Customize `<ServerStyleSheetDocument />`
You can still customize `_document.tsx`, the same way you would the default `<Document />` component from `next/document`:
```tsx
import {ServerStyleSheetDocument} from 'next-sanity/studio'

export default class Document extends ServerStyleSheetDocument {
static async getInitialProps(ctx: DocumentContext) {
// You can still override renderPage:
const originalRenderPage = ctx.renderPage
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => <App {...props} />,
})

const initialProps = await ServerStyleSheetDocument.getInitialProps(ctx)

const extraStyles = await getStyles()
return {
...initialProps,
// Add to the default styles if you want
styles: [initialProps.styles, extraStyles],
}
}
render() {
// do the same stuff as in `next/document`
}
}
```
### Full-control mode
If you only need parts of what `<NextStudio />` does for you, but not all of it.
No problem. You can import any which one of the components that `<NextStudio />` is importing and assemble them in any way you want.
```tsx
import {Studio, type Config} from 'sanity'
import {NextStudioGlobalStyle, NextStudioHead} from 'next-sanity/studio'
// This implementation will only load the bare minimum of what's required for the Studio to render correctly. No favicons, fancy <meta name="theme-color"> tags or the like
export default function CustomNextStudio({config}: {config: Config}) {
return (
<>
<Studio config={config} />
<NextStudioHead>{/* Custom extra stuff in <head> */}</NextStudioHead>
<NextStudioGlobalStyle />
</>
)
}
```
And while `<NextStudio />` have all features enabled by default allowing you to opt-out by giving it props, the inner components `<NextStudioHead />` and `<NextStudioGlobalStyle />` are opt-in.
This means that these two `StudioPage` components are functionally identical:
```tsx
import {
NextStudio,
NextStudioGlobalStyle,
NextStudioHead,
useThem,
useBackgroundColorsFromTheme,
} from 'next-sanity/studio'
import {Studio} from 'sanity'
import config from '../sanity.config'

// Turning all the features off, leaving only bare minimum required meta tags and styling
function StudioPage() {
return (
<NextStudio
config={config}
// an empty string turns off the CSS that sets a background on <html>
unstable__bg=""
unstable__noTailwindSvgFix
unstable__noFavicons
// an empty string turns off the <title> tag
unstable__document_title=""
/>
)
}

// Since no features are enabled it works the same way
function Studiopage() {
const theme = useTheme(config)
const {themeColorLight, themeColorDark} = useBackgroundColorsFromTheme(theme)

return (
<>
<Studio config={config} />
<NextStudioHead themeColorLight={themeColorLight} themeColorDark={themeColorDark} />
<NextStudioGlobalStyle />
</>
)
}
```
## Migrate
### From `v0.4`
Expand Down
2 changes: 1 addition & 1 deletion src/studio/NextStudioHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const NextStudioHeadComponent = ({
/>
<meta name="robots" content="noindex" />
<meta name="referrer" content="same-origin" />
<title>{title}</title>
{title && <title>{title}</title>}
{favicons && <link rel="icon" href={interop(iconIco)} sizes="any" />}
{favicons && <link rel="icon" href={interop(iconSvg)} type="image/svg+xml" />}
{favicons && <link rel="apple-touch-icon" href={interop(iconApple)} />}
Expand Down

1 comment on commit 4edd5d0

@vercel
Copy link

@vercel vercel bot commented on 4edd5d0 Aug 12, 2022

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:

next-sanity – ./

next-sanity.sanity.build
next-sanity-git-main.sanity.build
next.sanity.build

Please sign in to comment.