Shared Schemas
If you're not using our latest Next.js Sanity Starter
Skip this section if you're using our latest Next.js Sanity Starter. The shared schemas are already included in the starter template.
- Portable Text
sanity/schemas/blocks/shared/block-content.ts
:
import { defineType, defineArrayMember } from "sanity";
import { SquarePlay } from "lucide-react";
import { YouTubePreview } from "@/sanity/schemas/previews/youtube-preview";
export default defineType({
title: "Block Content",
name: "block-content",
type: "array",
of: [
defineArrayMember({
title: "Block",
type: "block",
styles: [
{ title: "Normal", value: "normal" },
{ title: "H1", value: "h1" },
{ title: "H2", value: "h2" },
{ title: "H3", value: "h3" },
{ title: "H4", value: "h4" },
{ title: "Quote", value: "blockquote" },
],
lists: [
{ title: "Bullet", value: "bullet" },
{ title: "Number", value: "number" },
],
marks: {
decorators: [
{ title: "Strong", value: "strong" },
{ title: "Emphasis", value: "em" },
],
annotations: [
{
title: "URL",
name: "link",
type: "object",
fields: [
{
title: "URL",
name: "href",
type: "url",
validation: (Rule) =>
Rule.uri({
allowRelative: true,
scheme: ["http", "https", "mailto", "tel"],
}),
},
],
},
],
},
}),
defineArrayMember({
type: "image",
options: { hotspot: true },
fields: [
{
name: "alt",
type: "string",
title: "Alternative Text",
},
],
}),
defineArrayMember({
name: "youtube",
type: "object",
title: "YouTube",
icon: SquarePlay,
fields: [
{
name: "videoId",
title: "Video ID",
type: "string",
description: "YouTube Video ID",
},
],
preview: {
select: {
title: "videoId",
},
},
components: {
preview: YouTubePreview,
},
}),
defineArrayMember({
name: "code",
type: "code",
options: {
withFilename: true,
language: "typescript",
languageAlternatives: [
{ title: "TypeScript", value: "typescript" },
{ title: "JavaScript", value: "javascript" },
{ title: "JSX", value: "jsx" },
{ title: "TSX", value: "tsx" },
{ title: "HTML", value: "html" },
{ title: "CSS", value: "css" },
{ title: "SCSS", value: "scss" },
{ title: "JSON", value: "json" },
{ title: "Python", value: "python" },
{ title: "PHP", value: "php" },
{ title: "Ruby", value: "ruby" },
{ title: "Shell", value: "shell" },
{ title: "Markdown", value: "markdown" },
{ title: "YAML", value: "yaml" },
{ title: "GraphQL", value: "graphql" },
{ title: "SQL", value: "sql" },
],
},
}),
],
});
- Youtube Preview
sanity/schemas/previews/youtube-preview.tsx
:
import type { PreviewProps } from "sanity";
import { Flex, Text } from "@sanity/ui";
import YouTubePlayer from "react-player/youtube";
import { SquarePlay } from "lucide-react";
export function YouTubePreview(props: PreviewProps) {
const { title: videoId } = props;
return (
<Flex padding={3} align="center" justify="center">
{typeof videoId === "string" ? (
<YouTubePlayer url={`https://www.youtube.com/watch?v=${videoId}`} />
) : (
<Flex align="center" justify="center">
<SquarePlay />
<Text>Add a YouTube Video ID</Text>
</Flex>
)}
</Flex>
);
}
- Link with
shadcn/ui
button variant
sanity/schemas/blocks/shared/link.ts
:
import { defineField, defineType } from "sanity";
export default defineType({
name: "link",
type: "object",
title: "Link",
fields: [
defineField({
name: "title",
type: "string",
}),
defineField({
name: "href",
title: "href",
type: "string",
}),
defineField({
name: "target",
type: "boolean",
title: "Open in new tab",
}),
defineField({
name: "buttonVariant",
type: "button-variant",
title: "Button Variant",
}),
],
});
- Layout Variants
sanity/schemas/blocks/shared/layout-variant.ts
:
import { defineType } from "sanity";
export const STACK_ALIGN = [
{ title: "Left", value: "left" },
{ title: "Center", value: "center" },
];
export const SECTION_WIDTH = [
{ title: "Default", value: "default" },
{ title: "Narrow", value: "narrow" },
];
export const COLS_VARIANTS = [
{ title: "2 Columns", value: "grid-cols-2" },
{ title: "3 Columns", value: "grid-cols-3" },
{ title: "4 Columns", value: "grid-cols-4" },
];
- Color Variants from
shadcn/ui
sanity/schemas/blocks/shared/color-variant.ts
:
import { defineType } from "sanity";
export const COLOR_VARIANTS = [
{ title: "Background", value: "background" },
{ title: "Primary", value: "primary" },
{ title: "Secondary", value: "secondary" },
{ title: "Card", value: "card" },
{ title: "Accent", value: "accent" },
{ title: "Destructive", value: "destructive" },
{ title: "Muted", value: "muted" },
];
export const colorVariant = defineType({
name: "color-variant",
title: "Color Variant",
type: "string",
options: {
list: COLOR_VARIANTS.map(({ title, value }) => ({ title, value })),
layout: "radio",
},
initialValue: "background",
});
- Button Variants from
shadcn/ui
sanity/schemas/blocks/shared/button-variant.ts
:
import { defineType } from "sanity";
export const BUTTON_VARIANTS = [
{ title: "Default", value: "default" },
{ title: "Destructive", value: "destructive" },
{ title: "Outline", value: "outline" },
{ title: "Secondary", value: "secondary" },
{ title: "Ghost", value: "ghost" },
{ title: "Link", value: "link" },
];
export const buttonVariant = defineType({
name: "button-variant",
title: "Button Variant",
type: "string",
options: {
list: BUTTON_VARIANTS.map(({ title, value }) => ({ title, value })),
layout: "radio",
},
initialValue: "default",
});
- Section Padding
sanity/schemas/blocks/shared/section-padding.ts
:
import { defineField, defineType } from "sanity";
export default defineType({
name: "section-padding",
type: "object",
title: "Padding",
description: "Add padding to the section. Based on design system spacing",
fields: [
defineField({
name: "top",
type: "boolean",
title: "Top Padding",
}),
defineField({
name: "bottom",
type: "boolean",
title: "Bottom Padding",
}),
],
});