Solid with Sanity CMS

Hi everyone Anyone using Solid with Sanity CMS?
26 Replies
benten
benten•6mo ago
I'm not but I've used Solid with react extensivly and the principles are mostly the same. Use the sanity client to query your cms, you can do it inside of server actions like any other query. do you have any specific questions or concerns with it?
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Is more the PortableText, the package is for React I'm new in Solid, try to learning Already do a query (not sure if I do it the correct way) and it's working
const [movies] = createResource(getMovie)

// ...

<Suspense fallback={<div>Loading....</div>}>
<Show when={movies()}>
<ul class={'grid grid-cols-4 gap-6'}>
<For each={movies()}>
{(movie) => {
const imageUrl = urlFor(movie.poster)

return (
<li
class={
'shadow-md font-sans flex flex-col gap-1 items-start p-4 rounded-sm'
}
>
<Image
loading="lazy"
class="w-full rounded aspect-square object-cover"
src={imageUrl
.width(1000)
.dpr(2)
.fit('max')
.url()}
alt={movie.title}
loadingImage={imageUrl.size(120, 120).quality(70).blur(50).format('webp').url()}
srcset={`
${imageUrl.width(78).url()} 78w,
${imageUrl.width(120).url()} 120w,
${imageUrl.width(1000).fit('max').url()} 1000w,
`}
/>
<h2 class={'font-sans text-xl'}>{movie.title}</h2>
<p class={'font-sans text-sm'}>{movie.slug}</p>
</li>
)
}}
</For>
</ul>
</Show>
</Suspense>
const [movies] = createResource(getMovie)

// ...

<Suspense fallback={<div>Loading....</div>}>
<Show when={movies()}>
<ul class={'grid grid-cols-4 gap-6'}>
<For each={movies()}>
{(movie) => {
const imageUrl = urlFor(movie.poster)

return (
<li
class={
'shadow-md font-sans flex flex-col gap-1 items-start p-4 rounded-sm'
}
>
<Image
loading="lazy"
class="w-full rounded aspect-square object-cover"
src={imageUrl
.width(1000)
.dpr(2)
.fit('max')
.url()}
alt={movie.title}
loadingImage={imageUrl.size(120, 120).quality(70).blur(50).format('webp').url()}
srcset={`
${imageUrl.width(78).url()} 78w,
${imageUrl.width(120).url()} 120w,
${imageUrl.width(1000).fit('max').url()} 1000w,
`}
/>
<h2 class={'font-sans text-xl'}>{movie.title}</h2>
<p class={'font-sans text-sm'}>{movie.slug}</p>
</li>
)
}}
</For>
</ul>
</Show>
</Suspense>
benten
benten•6mo ago
oh yeah
benten
benten•6mo ago
GitHub
GitHub - portabletext/solid-portabletext: Render Portable Text with...
Render Portable Text with Solid. Contribute to portabletext/solid-portabletext development by creating an account on GitHub.
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Oh thanks
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
One question that maybe is something that I'm doing wrong When I navigate between pages the request to Sanity fails, but if I refresh the page everything works fine
No description
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
I'm doing the fetching wrong? And sorry for the questions :/
benten
benten•6mo ago
why be sorry? this is the place to ask 🙂 can i see the code you use to fetch? not the actual fetcher but the solid code and maybe the fetching code as well
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
get-movies.ts
import {client} from '~/cms'
import {getMoviesQuery} from '~/cms/queries/movie'
import {cache} from '@solidjs/router'

const getMovies = cache(async () => {
try {
const movies = await client.fetch(getMoviesQuery)

return movies
} catch (error) {
console.error(error)
return []
}
}, 'movies')

export {getMovies}
import {client} from '~/cms'
import {getMoviesQuery} from '~/cms/queries/movie'
import {cache} from '@solidjs/router'

const getMovies = cache(async () => {
try {
const movies = await client.fetch(getMoviesQuery)

return movies
} catch (error) {
console.error(error)
return []
}
}, 'movies')

export {getMovies}
get-movies.query.ts
const getMoviesQuery = `
*[_type == "movie"] {
title,
'slug': slug.current,
overview,
releaseDate,
'poster': {
...poster,
'asset': poster.asset->
}
}
`;
const getMoviesQuery = `
*[_type == "movie"] {
title,
'slug': slug.current,
overview,
releaseDate,
'poster': {
...poster,
'asset': poster.asset->
}
}
`;
routes/index.tsx
export default function Home() {
const movies = createAsync(() => getMovies())

return (
<main class="text-center mx-auto text-gray-700 p-4">
<Suspense fallback={<div>Loading....</div>}>
<Show when={movies()}>
<ul class={'grid grid-cols-4 gap-6'}>
<For each={movies()}>
{(movie) => {
const imageUrl = urlFor(movie.poster)

return (
<li
class={
'shadow-md font-sans flex flex-col gap-1 p-4 rounded-sm text-left'
}
>
<Image
loading="lazy"
class="w-full rounded aspect-square object-cover"
src={imageUrl
.width(1000)
.dpr(2)
.fit('max')
.url()}
alt={movie.title}
loadingImage={imageUrl.size(120, 120).quality(70).blur(50).format('webp').url()}
srcset={`
${imageUrl.width(78).url()} 78w,
${imageUrl.width(120).url()} 120w,
${imageUrl.width(1000).fit('max').url()} 1000w,
`}
/>
<h2 class={'font-sans text-left text-xl font-semibold'}>{movie.title}</h2>
<p class={'font-sans text-sm text-left'}>{movie.slug}</p>

<div class={'line-clamp-3'}>
<PortableText value={movie.overview} components={components} />
</div>
</li>
)
}}
</For>
</ul>
</Show>
</Suspense>
</main>
)
}
export default function Home() {
const movies = createAsync(() => getMovies())

return (
<main class="text-center mx-auto text-gray-700 p-4">
<Suspense fallback={<div>Loading....</div>}>
<Show when={movies()}>
<ul class={'grid grid-cols-4 gap-6'}>
<For each={movies()}>
{(movie) => {
const imageUrl = urlFor(movie.poster)

return (
<li
class={
'shadow-md font-sans flex flex-col gap-1 p-4 rounded-sm text-left'
}
>
<Image
loading="lazy"
class="w-full rounded aspect-square object-cover"
src={imageUrl
.width(1000)
.dpr(2)
.fit('max')
.url()}
alt={movie.title}
loadingImage={imageUrl.size(120, 120).quality(70).blur(50).format('webp').url()}
srcset={`
${imageUrl.width(78).url()} 78w,
${imageUrl.width(120).url()} 120w,
${imageUrl.width(1000).fit('max').url()} 1000w,
`}
/>
<h2 class={'font-sans text-left text-xl font-semibold'}>{movie.title}</h2>
<p class={'font-sans text-sm text-left'}>{movie.slug}</p>

<div class={'line-clamp-3'}>
<PortableText value={movie.overview} components={components} />
</div>
</li>
)
}}
</For>
</ul>
</Show>
</Suspense>
</main>
)
}
https://docs.solidjs.com/solid-start/building-your-application/data-loading I see an example from this docs And on the route/page, I added:
export const route = {
load: () => getMovies()
}
export const route = {
load: () => getMovies()
}
I'm doing something wrong?
benten
benten•6mo ago
I'm assuming your fetching code is working on the server but not on the client. so when you navigate client side it the fetch fails try putting "use server" at the top of your getMovies() function inside of cache()
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Works Should I do something different? And other thing, is possible fetch the data while I hover the link? I'm probably being a very noob, but it's normal this happen:
/movies/[slug].tsx
export default function MovieDetails() {
const {slug} = useParams<{slug: string}>()

return <main>
<h1>{slug} Movie</h1>
</main>
}
export default function MovieDetails() {
const {slug} = useParams<{slug: string}>()

return <main>
<h1>{slug} Movie</h1>
</main>
}
Only have this and put <a href={/movies/${movie.slug}}>view details</a> And whe I click on the view details the URL is ok but the page appears blank, after a refresh the slug appears Is very strange
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Before refresh
No description
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
After refresh
No description
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
I did another test: - If I comment the fetch code and the for loop, and add a simpel button to /movies/abc works - If I access the route directly from the URL works Otherwise not
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Sometimes appear this error on console
No description
benten
benten•6mo ago
this feels to me like a bug within solid start / vinxi well, the sanity client not working on the server your params aren't updating because you're destructuring which loses reactivity
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Ok, so I should use const params = useParams
benten
benten•6mo ago
yeah, because it's reactive
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
Ok, thank you and sorry for the noob mistakes 🫣 For the sanity client, should I do something different?
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
https://github.com/tutods/sanity-solid this is my code if you want to check
GitHub
GitHub - tutods/sanity-solid
Contribute to tutods/sanity-solid development by creating an account on GitHub.
benten
benten•6mo ago
Looks fine to me. Anything specific you want me to look at?
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
For now seems to be working I will try to keep doing more queries with Sanity to see if works Thanks for your help @b_e_n_t_e_n
benten
benten•6mo ago
🔥
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•6mo ago
And sorry for the noob questions
benten
benten•6mo ago
no need to apologize
Daniel Sousa @TutoDS
Daniel Sousa @TutoDSOP•5mo ago
Hi again I'm facing a smiliar issue again
function CtaSection() {
const cta = createAsync(() => getCtaSettings(), {
name: 'cta-settings',
});

// Get location and pathname
const location = useLocation();
const pathname = createMemo(() => location.pathname);

if (
EXCLUDED_PATHS_TO_SHOW_CTA.some((path) => {
return path === pathname();
})
) {
return null;
}

return (
<section class="flex flex-col items-center justify-center overflow-hidden py-20">
<div class="container relative isolate text-center">
<h2 class="">{cta()?.title}</h2>
<p class="mt-2 text-lg leading-8">{cta()?.description}</p>

<ul class={'mt-6 flex flex-wrap items-center justify-center gap-8'}>
<For each={cta()?.points}>
{(point) => (
<li class={'flex items-center gap-3 font-medium'}>
<i class="ph ph-check" />
{point}
</li>
)}
</For>
</ul>

<a
class={
'mt-10 inline-flex items-center gap-2 border-b border-b-transparent font-semibold text-gray-700 transition-all duration-300 ease-in-out hover:border-b-gray-900 hover:text-gray-900'
}
href={'/contactos'}
>
{cta()?.button} <i class={'ph ph-arrow-right'} />
</a>
</div>
</section>
);
}

export { CtaSection };
function CtaSection() {
const cta = createAsync(() => getCtaSettings(), {
name: 'cta-settings',
});

// Get location and pathname
const location = useLocation();
const pathname = createMemo(() => location.pathname);

if (
EXCLUDED_PATHS_TO_SHOW_CTA.some((path) => {
return path === pathname();
})
) {
return null;
}

return (
<section class="flex flex-col items-center justify-center overflow-hidden py-20">
<div class="container relative isolate text-center">
<h2 class="">{cta()?.title}</h2>
<p class="mt-2 text-lg leading-8">{cta()?.description}</p>

<ul class={'mt-6 flex flex-wrap items-center justify-center gap-8'}>
<For each={cta()?.points}>
{(point) => (
<li class={'flex items-center gap-3 font-medium'}>
<i class="ph ph-check" />
{point}
</li>
)}
</For>
</ul>

<a
class={
'mt-10 inline-flex items-center gap-2 border-b border-b-transparent font-semibold text-gray-700 transition-all duration-300 ease-in-out hover:border-b-gray-900 hover:text-gray-900'
}
href={'/contactos'}
>
{cta()?.button} <i class={'ph ph-arrow-right'} />
</a>
</div>
</section>
);
}

export { CtaSection };
I have created this cta section, fetching the data from Sanity CMS I added it to the app.tsx:
export default function App() {
return (
<Router
root={(props) => (
<>
<Header mode={'transparent'} />
<Suspense>{props.children}</Suspense>

<Suspense fallback={'Loading...'}>
<CtaSection />
</Suspense>
</>
)}
>
<FileRoutes />
</Router>
);
}
export default function App() {
return (
<Router
root={(props) => (
<>
<Header mode={'transparent'} />
<Suspense>{props.children}</Suspense>

<Suspense fallback={'Loading...'}>
<CtaSection />
</Suspense>
</>
)}
>
<FileRoutes />
</Router>
);
}
But it's rendering without data, the cta() is undefined
const getCtaSettings = cache(async () => {
'use server';

return client.fetch<Settings['cta']>(getCtaSettingsQuery);
}, 'cta-settings');
const getCtaSettings = cache(async () => {
'use server';

return client.fetch<Settings['cta']>(getCtaSettingsQuery);
}, 'cta-settings');
This is my getCtaSettings Anyone can help me please?
Want results from more Discord servers?
Add your server