Sanity integration for Vue
Composition API methods to incorporate Sanity into a Vue project.
- 🗄 Caching: Query results are cached.
- 💪 TypeScript: Written in TypeScript.
- 📡 Real-time: Supports previews using Sanity listening mode.
- 🖇 Composition API: Vue3/Vue2 support using
vue-demi
. - 📝 SSR support: Compatible with server-side rendering with Nuxt and vanilla Vue.
First install vue-sanity
:
yarn add vue-sanity
# or npm
npm install vue-sanity --save
Now configure Sanity in your root component:
import { useSanityClient } from 'vue-sanity'
export default {
name: 'App',
setup() {
useSanityClient({
projectId: 'myprojectid',
dataset: 'production',
useCdn: process.env.NODE_ENV === 'production',
})
},
}
Then you can use useSanityFetcher
in any child component:
<script>
import { useSanityFetcher } from 'vue-sanity'
export default {
setup() {
const { data: title } = useSanityFetcher('*[_type == "article"][0].title')
// OR use a factory function
const { data: title } = useSanityFetcher(
() => `*[slug.current == ${slug.value}][0].title`
)
return { title }
},
}
</script>
<template>
<div>
<h1>
{{ title }}
</h1>
</div>
</template>
-
config
These are the options required by
@sanity/client
. For more details, see the Sanity docs. -
supportPreview
In addition to the config you would normally pass to
@sanity/client
, you can pass a boolean as a second parameter for whether to create a preview client. (Used currently only when listening to real-time data updating.) -
defaultOptions
You may also pass an object of options that will be passed to any queries you make using
useSanityFetcher
, although of course they will be overridden by any specific options you pass touseSanityFetcher
.
import { useSanityClient } from 'vue-sanity'
export default {
setup() {
useSanityClient(
{
projectId: 'myprojectid',
dataset: 'production',
useCdn: process.env.NODE_ENV === 'production',
},
true // will now create a preview client for use elsewhere
)
},
}
-
query
A function that retuns a query string. If the return value changes, a new Sanity query will be run and the return value automatically updated.
-
initialValue
You can provide an initial value for the query result (which will be returned before query completes). -
mapper
You can provide a function to transform the query result.
-
options
You can also provide an object of additional options.
- listen: true, false or an object of options to pass to
client.listen
(defaults tofalse
) - strategy: strategy for fetching. Defaults to
both
.:server
: will not refetch if the cache has been populated on SSR:client
: will disable SSR fetching entirely:both
: will fetch on server and refetch when page is loaded
- deduplicate: Whether to de-duplicate identical fetches. If set to
true
, additional fetches will not run unless made after the previous request errors or succeeds. If set to a number, additional fetches will run, but only after this many milliseconds after the previous fetch began.
- listen: true, false or an object of options to pass to
If you are using sanity-typed-queries
to define your schema, this is a helper function to reduce boilerplate and explicit typing.
import { useSanityQuery } from 'vue-sanity'
import { builder } from './cms/schemas/author.js'
export default {
setup() {
// title will be typed as Ref<string | null>, with null as a default value
const { data: title } = useSanityQuery(builder.pick('name').first())
// authors will be typed as Ref<string[]>, with an empty array as a default value
const { data: authors } = useSanityQuery(builder.pick('name'))
return { title, authors }
},
}
import { useSanityClient } from 'vue-sanity'
export default {
setup() {
const { data: title } = useSanityFetcher(
// query
() => `*[_type == "article"][0].title`,
// initial value
'Title - Default',
// mapper
result => `Title - ${result}`,
// options
{
listen: true,
clientOnly: true,
}
)
return { title }
},
}
You can type the return value of useSanityFetcher
in several ways.
// data will be typed as Ref<string | null>
const { data } = useSanityFetcher<string>(
() => `*[_type == "article"][0].title`
)
// data will be typed as Ref<string | number> as a number has been provided as a default value
const { data } = useSanityFetcher<string, number>(
() => `*[_type == "article"][0].title`,
3
)
// data will be typed as Ref<boolean | { value: string }> as it can infer the type
const { data } = useSanityFetcher(
() => `*[_type == "article"][0].title`,
true,
(result: string) => ({ value: result })
)
Projects I've found helpful are:
This has been developed to suit my needs but additional use cases and contributions are very welcome.
MIT License - Copyright © Daniel Roe