♻️ Use sanity

This commit is contained in:
2024-02-24 21:56:35 +08:00
parent 4b05046a17
commit 1a9ada9e0e
32 changed files with 8441 additions and 194 deletions

21
sanity/env.ts Normal file
View 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
View 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
View 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
View 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],
};

View 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",
},
},
});

View 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",
},
],
}),
],
});

View 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",
}),
],
});

View 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}` };
},
},
});