Open danielroe opened 2 years ago
I followed this tutorial by Sanity, and added some extra code/steps to make it work in Nuxt.
This should be a pretty complete tutorial on how to embed Sanity Studio v3 in Nuxt 3:
Add Sanity to your project
npm install sanity@latest
Create a new plugin in your plugins
-folder called sanity-studio.client.ts
with the following content:
import { defineConfig } from 'sanity';
import { deskTool } from 'sanity/desk';
import { schemaTypes } from '../schemas';
export default defineNuxtPlugin((nuxtApp) => {
const config = defineConfig({
plugins: [deskTool()],
name: '<PROJECT-NAME>',
projectId: '<PROJECT-ID>',
basePath: '/admin', // Same as our page
schema: {
types: schemaTypes, // Your Sanity-schemas
},
});
return {
provide: {
sanityConfig: config,
},
};
});
I assume you I don't have to explain in detail how to define Sanity-schemas, but in my example I created a folder in the root of my project called schemas
, and inside I have two files:
animal.ts
export default {
name: 'animal',
type: 'document',
title: 'Animal',
fields: [
{
name: 'name',
type: 'string',
title: 'Name',
},
],
}
index.ts
import animal from './animal'
export const schemaTypes = [animal]
In your pages
-folder, create a new folder called admin
. Under that folder, create a file called [...slug].vue
. You will now have:
pages
- admin
-- [...slug.vue]
Add the following content to the page
<template>
<div id="studio" ref="studio"></div>
</template>
<script setup>
import { renderStudio } from 'sanity';
const { $sanityConfig } = useNuxtApp();
const studio = ref();
onMounted(() => {
renderStudio(studio.value, $sanityConfig);
});
</script>
<style>
/* This assumes no margin or padding on #app's parent(s) */
#studio {
height: 100vh;
max-height: 100dvh;
overscroll-behavior: none;
-webkit-font-smoothing: antialiased;
overflow: auto;
}
/* Fix if you're using Tailwind.css */
*:not([data-ui='Popover__arrow']):not([data-ui='Tooltip__arrow']) > svg {
display: inline;
}
</style>
We also need to add some config to our nuxt.config.ts
:
nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/admin/**': {
ssr: false,
},
},
vite: {
define: {
// Fix broken process.env for styled-components in Sanity Studio
'process.env': {
REACT_APP_SC_ATTR: 'data-styled',
},
},
},
});
Some explanation
routeRules
- Sanity Studio does not support SSR, so we disable it for the admin-page we created.
vite
- Sanity Studio is built on React and uses the styled-components
package. It tries to access a propert in process.env
, which does not exist, and therefore result in an exception. But with this config, we are able to work around the issue. Got the solution from https://github.com/nuxt/nuxt.js/issues/13264.
Sanity Studio should now be running on /admin
. Remember to add localhost to Sanity's CORS settings.
I have not tested this implementation fully as I just got it working myself, but it seems to be working fine.
@danielroe Would it be interesting to add this as a built-in option in the @nuxtjs/sanity
module? Or at least add this tutorial to the documentation? Let me know what you think, and I will happily submit a PR 😄
It seems like you will run in to some issues if you try to customize Sanity Studio with React-components. For instance, if you want to change the logo, you have to create a React-component with JSX. But with my solution it will give the following error:
Error: Objects are not valid as a React child (found: object with keys {__v_isVNode, __v_skip, type, props, key, ref, scopeId, slotScopeIds, children, component, suspense, ssContent, ssFallback, dirs, transition, el, anchor, target, targetAnchor, staticCount, shapeFlag, patchFlag, dynamicProps, dynamicChildren, appContext, ctx}). If you meant to render a collection of children, use an array instead.
Error: Objects are not valid as a React child (found: object with keys {__v_isVNode, __v_skip, type, props, key, ref, scopeId, slotScopeIds, children, component, suspense, ssContent, ssFallback, dirs, transition, el, anchor, target, targetAnchor, staticCount, shapeFlag, patchFlag, dynamicProps, dynamicChildren, appContext, ctx}). If you meant to render a collection of children, use an array instead.
at throwOnInvalidObjectType (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:20784:17)
at reconcileChildFibers2 (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:21403:15)
at reconcileChildren (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:23815:37)
at mountIndeterminateComponent (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:24490:13)
at beginWork (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:25389:22)
at beginWork$1 (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:29190:22)
at performUnitOfWork (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:28635:20)
at workLoopSync (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:28574:13)
at renderRootSync (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:28553:15)
at recoverFromConcurrentError (http://localhost:3000/_nuxt/node_modules/.vite/deps/chunk-XHZEAB7L.js?v=23f3e8d7:28175:28)
So maybe the best solution is to keep the Sanity Studio completely outside of the Nuxt rendering. I guess one solution could be to just have an API-route in the server
-folder that would return a plain static .html
file that could render the studio.
Another solution would be to use Sanity CLI and build the studio project to static files, and put them in the static
-folder or something, but I don't think that sounds like a smooth option.
Any thoughts on this, @danielroe ? 😇
Thank you so much Ola! Great work!
This is great work! 🙌
I think the objectives are:
I'm up for some different approaches to achieving these objectives, or even exposing multiple options for the end user.
@OlaAlsaker Do you know how to exclude types coming from the sanity studio? I am getting all these annoying react ts errors. I tried everything i found on google, and one solution working on fullcalendar but not for sanity,
Not yet, unfortunately! If you need to do custom things with React in Sanity, the best current solution is to have Sanity Studio as it's own project in a custom folder.
@OlaAlsaker I am thinking in combination with Nuxt. Sanity is enabled with ts and nuxt also. They are in the same repo (seperate folders).
Hello:) Any updates on this? I am heavily using sanity with Nuxt 3, and to be frank I think this would be such a good feature to implement for various reasons. I would love to help on this, but i dont know where to start. Maybe someone could point me in the right direction?
So the main stopper for me is the ability to create custom components in the studio, maybe this could even be done as a Vue component? And that react types flows into Nuxt types to make it useless.
Any ideas about a possible approach to this? Thanks:D
Any updates on this? Currently working on this using renderStudio function but getting:
Cannot read properties of undefined (reading 'REACT_APP_SC_ATTR')
I believe it is because vite using a different way to get env vars.