♻️ Use sanity
This commit is contained in:
21
sanity/env.ts
Normal file
21
sanity/env.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export const apiVersion = process.env.NEXT_PUBLIC_SANITY_API_VERSION || "2024-02-24";
|
||||
|
||||
export const dataset = assertValue(
|
||||
process.env.NEXT_PUBLIC_SANITY_DATASET,
|
||||
"Missing environment variable: NEXT_PUBLIC_SANITY_DATASET",
|
||||
);
|
||||
|
||||
export const projectId = assertValue(
|
||||
process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
|
||||
"Missing environment variable: NEXT_PUBLIC_SANITY_PROJECT_ID",
|
||||
);
|
||||
|
||||
export const useCdn = false;
|
||||
|
||||
function assertValue<T>(v: T | undefined, errorMessage: string): T {
|
||||
if (v === undefined) {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
10
sanity/lib/client.ts
Normal file
10
sanity/lib/client.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createClient } from "next-sanity";
|
||||
|
||||
import { apiVersion, dataset, projectId, useCdn } from "../env";
|
||||
|
||||
export const client = createClient({
|
||||
apiVersion,
|
||||
dataset,
|
||||
projectId,
|
||||
useCdn,
|
||||
});
|
13
sanity/lib/image.ts
Normal file
13
sanity/lib/image.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import createImageUrlBuilder from "@sanity/image-url";
|
||||
import type { Image } from "sanity";
|
||||
|
||||
import { dataset, projectId } from "../env";
|
||||
|
||||
const imageBuilder = createImageUrlBuilder({
|
||||
projectId: projectId || "",
|
||||
dataset: dataset || "",
|
||||
});
|
||||
|
||||
export const urlForImage = (source: Image) => {
|
||||
return imageBuilder?.image(source).auto("format").fit("max").url();
|
||||
};
|
10
sanity/schema.ts
Normal file
10
sanity/schema.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { type SchemaTypeDefinition } from "sanity";
|
||||
|
||||
import blockContent from "./schemaTypes/blockContent";
|
||||
import category from "./schemaTypes/category";
|
||||
import post from "./schemaTypes/post";
|
||||
import author from "./schemaTypes/author";
|
||||
|
||||
export const schema: { types: SchemaTypeDefinition[] } = {
|
||||
types: [post, author, category, blockContent],
|
||||
};
|
57
sanity/schemaTypes/author.ts
Normal file
57
sanity/schemaTypes/author.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { defineField, defineType } from "sanity";
|
||||
|
||||
export default defineType({
|
||||
name: "author",
|
||||
title: "Author",
|
||||
type: "document",
|
||||
fields: [
|
||||
defineField({
|
||||
name: "name",
|
||||
title: "Name",
|
||||
type: "string",
|
||||
}),
|
||||
defineField({
|
||||
name: "slug",
|
||||
title: "Slug",
|
||||
type: "slug",
|
||||
options: {
|
||||
source: "name",
|
||||
maxLength: 96,
|
||||
},
|
||||
}),
|
||||
defineField({
|
||||
name: "image",
|
||||
title: "Image",
|
||||
type: "image",
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
type: "string",
|
||||
title: "Alternative Text",
|
||||
},
|
||||
],
|
||||
}),
|
||||
defineField({
|
||||
name: "bio",
|
||||
title: "Bio",
|
||||
type: "array",
|
||||
of: [
|
||||
{
|
||||
title: "Block",
|
||||
type: "block",
|
||||
styles: [{ title: "Normal", value: "normal" }],
|
||||
lists: [],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "name",
|
||||
media: "image",
|
||||
},
|
||||
},
|
||||
});
|
75
sanity/schemaTypes/blockContent.ts
Normal file
75
sanity/schemaTypes/blockContent.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { defineType, defineArrayMember } from "sanity";
|
||||
|
||||
/**
|
||||
* This is the schema type for block content used in the post document type
|
||||
* Importing this type into the studio configuration's `schema` property
|
||||
* lets you reuse it in other document types with:
|
||||
* {
|
||||
* name: 'someName',
|
||||
* title: 'Some title',
|
||||
* type: 'blockContent'
|
||||
* }
|
||||
*/
|
||||
|
||||
export default defineType({
|
||||
title: "Block Content",
|
||||
name: "blockContent",
|
||||
type: "array",
|
||||
of: [
|
||||
defineArrayMember({
|
||||
title: "Block",
|
||||
type: "block",
|
||||
// Styles let you define what blocks can be marked up as. The default
|
||||
// set corresponds with HTML tags, but you can set any title or value
|
||||
// you want, and decide how you want to deal with it where you want to
|
||||
// use your content.
|
||||
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" }],
|
||||
// Marks let you mark up inline text in the Portable Text Editor
|
||||
marks: {
|
||||
// Decorators usually describe a single property – e.g. a typographic
|
||||
// preference or highlighting
|
||||
decorators: [
|
||||
{ title: "Strong", value: "strong" },
|
||||
{ title: "Emphasis", value: "em" },
|
||||
],
|
||||
// Annotations can be any object structure – e.g. a link or a footnote.
|
||||
annotations: [
|
||||
{
|
||||
title: "URL",
|
||||
name: "link",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "URL",
|
||||
name: "href",
|
||||
type: "url",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
// You can add additional types here. Note that you can't use
|
||||
// primitive types such as 'string' and 'number' in the same array
|
||||
// as a block type.
|
||||
defineArrayMember({
|
||||
type: "image",
|
||||
options: { hotspot: true },
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
type: "string",
|
||||
title: "Alternative Text",
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
19
sanity/schemaTypes/category.ts
Normal file
19
sanity/schemaTypes/category.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { defineField, defineType } from "sanity";
|
||||
|
||||
export default defineType({
|
||||
name: "category",
|
||||
title: "Category",
|
||||
type: "document",
|
||||
fields: [
|
||||
defineField({
|
||||
name: "title",
|
||||
title: "Title",
|
||||
type: "string",
|
||||
}),
|
||||
defineField({
|
||||
name: "description",
|
||||
title: "Description",
|
||||
type: "text",
|
||||
}),
|
||||
],
|
||||
});
|
77
sanity/schemaTypes/post.ts
Normal file
77
sanity/schemaTypes/post.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { defineField, defineType } from "sanity";
|
||||
|
||||
export default defineType({
|
||||
name: "post",
|
||||
title: "Post",
|
||||
type: "document",
|
||||
fields: [
|
||||
defineField({
|
||||
name: "title",
|
||||
title: "Title",
|
||||
type: "string",
|
||||
}),
|
||||
defineField({
|
||||
name: "description",
|
||||
title: "Description",
|
||||
type: "string",
|
||||
}),
|
||||
defineField({
|
||||
name: "slug",
|
||||
title: "Slug",
|
||||
type: "slug",
|
||||
options: {
|
||||
source: "title",
|
||||
maxLength: 96,
|
||||
},
|
||||
}),
|
||||
defineField({
|
||||
name: "author",
|
||||
title: "Author",
|
||||
type: "reference",
|
||||
to: { type: "author" },
|
||||
}),
|
||||
defineField({
|
||||
name: "mainImage",
|
||||
title: "Main image",
|
||||
type: "image",
|
||||
options: {
|
||||
hotspot: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "alt",
|
||||
type: "string",
|
||||
title: "Alternative Text",
|
||||
},
|
||||
],
|
||||
}),
|
||||
defineField({
|
||||
name: "categories",
|
||||
title: "Categories",
|
||||
type: "array",
|
||||
of: [{ type: "reference", to: { type: "category" } }],
|
||||
}),
|
||||
defineField({
|
||||
name: "publishedAt",
|
||||
title: "Published at",
|
||||
type: "datetime",
|
||||
}),
|
||||
defineField({
|
||||
name: "body",
|
||||
title: "Body",
|
||||
type: "blockContent",
|
||||
}),
|
||||
],
|
||||
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
author: "author.name",
|
||||
media: "mainImage",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { author } = selection;
|
||||
return { ...selection, subtitle: author && `by ${author}` };
|
||||
},
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user