├── .eslintrc.json
├── app
├── globals.css
├── favicon.ico
├── api
│ └── hello
│ │ └── route.ts
├── (studio)
│ ├── admin
│ │ └── [[...index]]
│ │ │ └── page.tsx
│ └── layout.tsx
└── (site)
│ ├── [slug]
│ └── page.tsx
│ ├── layout.tsx
│ ├── projects
│ └── [project]
│ │ └── page.tsx
│ └── page.tsx
├── postcss.config.js
├── .vscode
└── settings.json
├── sanity
├── schemas
│ ├── index.ts
│ ├── page-schema.ts
│ └── project-schema.ts
├── config
│ └── client-config.ts
└── sanity-utils.ts
├── types
├── Page.ts
└── Project.ts
├── next.config.js
├── tailwind.config.js
├── sanity.config.ts
├── .gitignore
├── public
├── vercel.svg
├── thirteen.svg
└── next.svg
├── tsconfig.json
├── package.json
└── README.md
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kapehe-ok/next-sanity-test/HEAD/app/favicon.ico
--------------------------------------------------------------------------------
/app/api/hello/route.ts:
--------------------------------------------------------------------------------
1 | export async function GET(request: Request) {
2 | return new Response('Hello, Next.js!')
3 | }
4 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "typescript.enablePromptUseWorkspaceTsdk": true
4 | }
--------------------------------------------------------------------------------
/sanity/schemas/index.ts:
--------------------------------------------------------------------------------
1 | import project from './project-schema'
2 | import page from "./page-schema"
3 |
4 | const schemas = [project, page];
5 |
6 | export default schemas;
--------------------------------------------------------------------------------
/sanity/config/client-config.ts:
--------------------------------------------------------------------------------
1 | const config = {
2 | projectId: "txd29ab2",
3 | dataset: "production",
4 | apiVersion: "2023-03-09",
5 | }
6 |
7 | export default config;
--------------------------------------------------------------------------------
/types/Page.ts:
--------------------------------------------------------------------------------
1 | import { PortableTextBlock } from "sanity"
2 |
3 | export type Page = {
4 | _id: string,
5 | _createdAt: Date,
6 | title: string,
7 | slug: string,
8 | content: PortableTextBlock[]
9 | };
--------------------------------------------------------------------------------
/app/(studio)/admin/[[...index]]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { NextStudio } from 'next-sanity/studio';
4 | import config from "@/sanity.config";
5 |
6 | export default function AdminPage() {
7 | return
8 | }
--------------------------------------------------------------------------------
/types/Project.ts:
--------------------------------------------------------------------------------
1 | import { PortableTextBlock } from "sanity";
2 |
3 | export type Project = {
4 | _id: string;
5 | createdAt: Date;
6 | name: string;
7 | slug: string;
8 | image: string;
9 | url: string;
10 | content: PortableTextBlock[];
11 | }
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | experimental: {
4 | appDir: true,
5 | },
6 | images: {
7 | remotePatterns: [
8 | {
9 | protocol: 'https',
10 | hostname: 'cdn.sanity.io',
11 | port: '',
12 | },
13 | ],
14 | },
15 | }
16 |
17 | module.exports = nextConfig
18 |
--------------------------------------------------------------------------------
/app/(studio)/layout.tsx:
--------------------------------------------------------------------------------
1 | import '../globals.css'
2 |
3 | export const metadata = {
4 | title: 'My Awesome Site',
5 | description: 'Generated by Next + Sanity',
6 | }
7 |
8 | export default function RootLayout({
9 | children,
10 | }: {
11 | children: React.ReactNode
12 | }) {
13 | return (
14 |
15 |
{children}
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./app/**/*.{js,ts,jsx,tsx}",
5 | "./pages/**/*.{js,ts,jsx,tsx}",
6 | "./components/**/*.{js,ts,jsx,tsx}",
7 |
8 | // Or if using `src` directory:
9 | "./src/**/*.{js,ts,jsx,tsx}",
10 | ],
11 | theme: {
12 | extend: {},
13 | },
14 | plugins: [],
15 | }
16 |
--------------------------------------------------------------------------------
/sanity.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'sanity';
2 | import { deskTool } from 'sanity/desk';
3 | import schemas from "./sanity/schemas"
4 |
5 | const config = defineConfig({
6 | projectId: "txd29ab2",
7 | dataset: "production",
8 | title: "My Personal Website",
9 | apiVersion: "2023-03-09",
10 | basePath: "/admin",
11 | plugins: [deskTool()],
12 | schema: { types: schemas }
13 | })
14 |
15 | export default config
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/sanity/schemas/page-schema.ts:
--------------------------------------------------------------------------------
1 | const page = {
2 | name: "page",
3 | title: "Pages",
4 | type: "document",
5 | fields: [
6 | {
7 | name: "title",
8 | title: "Title",
9 | type: "string"
10 | },
11 | {
12 | name: "slug",
13 | title: "Slug",
14 | type: "slug",
15 | options: { source: "title", maxLength: 96 }
16 | },
17 | {
18 | name: "content",
19 | title: "Content",
20 | type: "array",
21 | of: [
22 | { type: "block" }
23 | ]
24 | }
25 | ]
26 | }
27 |
28 | export default page;
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/(site)/[slug]/page.tsx:
--------------------------------------------------------------------------------
1 | import { getPage } from "@/sanity/sanity-utils";
2 | import { PortableText } from "@portabletext/react";
3 |
4 | type Props = {
5 | params: { slug: string }
6 | }
7 |
8 | export default async function Page({ params }: Props) {
9 | const page = await getPage(params.slug);
10 |
11 | return (
12 |
15 | )
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "paths": {
23 | "@/*": ["./*"]
24 | }
25 | },
26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27 | "exclude": ["node_modules"]
28 | }
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "next-sanity-test",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@portabletext/react": "^2.0.2",
13 | "@types/node": "18.15.0",
14 | "@types/react": "18.0.28",
15 | "@types/react-dom": "18.0.11",
16 | "eslint": "8.35.0",
17 | "eslint-config-next": "13.2.3",
18 | "next": "13.2.3",
19 | "next-sanity": "^4.1.5",
20 | "react": "18.2.0",
21 | "react-dom": "18.2.0",
22 | "sanity": "^3.6.0",
23 | "typescript": "4.9.5"
24 | },
25 | "devDependencies": {
26 | "autoprefixer": "^10.4.14",
27 | "postcss": "^8.4.21",
28 | "tailwindcss": "^3.2.7"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/sanity/schemas/project-schema.ts:
--------------------------------------------------------------------------------
1 | const project = {
2 | name: "project",
3 | title: "Projects",
4 | type: "document",
5 | fields: [
6 | {
7 | name: "name",
8 | title: "Name",
9 | type: "string",
10 | },
11 | {
12 | name: "slug",
13 | title: "Slug",
14 | type: "slug",
15 | options: { source: "name" }
16 | },
17 | {
18 | name: "image",
19 | title: "Image",
20 | type: "image",
21 | options: { hotspot: true },
22 | fields: [
23 | {
24 | name: "alt",
25 | title: "Alt",
26 | type: "string"
27 | }
28 | ]
29 | },
30 | {
31 | name: "url",
32 | title: "URL",
33 | type: "url"
34 | },
35 | {
36 | name: "content",
37 | title: "Content",
38 | type: "array",
39 | of: [{ type: "block" }]
40 | }
41 | ]
42 | }
43 |
44 | export default project;
--------------------------------------------------------------------------------
/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/(site)/layout.tsx:
--------------------------------------------------------------------------------
1 | import '../globals.css'
2 | import Link from "next/link"
3 | import { getPages } from '@/sanity/sanity-utils';
4 |
5 | export const metadata = {
6 | title: 'My Awesome Site',
7 | description: 'Generated by Next + Sanity',
8 | }
9 |
10 | export default async function RootLayout({
11 | children,
12 | }: {
13 | children: React.ReactNode
14 | }) {
15 | const pages = await getPages();
16 |
17 | return (
18 |
19 |
20 |
30 | {children}
31 |
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/app/(site)/projects/[project]/page.tsx:
--------------------------------------------------------------------------------
1 | import { getProject } from "@/sanity/sanity-utils";
2 | import { PortableText } from '@portabletext/react';
3 | import Image from "next/image"
4 |
5 | type Props = {
6 | params: { project: string }
7 | }
8 |
9 | export default async function Project({ params }: Props) {
10 | const slug = params.project;
11 | const project = await getProject(slug);
12 |
13 | return
14 |
20 |
21 |
24 |
25 |
26 |
27 | }
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/(site)/page.tsx:
--------------------------------------------------------------------------------
1 | import { getProjects } from "@/sanity/sanity-utils"
2 | import Image from 'next/image'
3 | import Link from 'next/link'
4 |
5 | export default async function Home() {
6 | const projects = await getProjects();
7 |
8 | return (
9 |
10 |
Hello I'm
11 | Kapehe!
12 |
13 |
Aloha everyone! Check out my projects!
14 |
My Projects
15 |
16 |
{projects.map((project) => (
17 |
18 | {project.image && (
19 |
26 | )}
27 |
28 | {project.name}
29 |
30 |
31 | ))}
32 |
33 |
34 | )
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/sanity/sanity-utils.ts:
--------------------------------------------------------------------------------
1 | import { createClient, groq } from "next-sanity";
2 | import { Project } from "@/types/Project";
3 | import clientConfig from './config/client-config'
4 | import { Page } from "@/types/Page";
5 |
6 | export async function getProjects(): Promise {
7 | return createClient(clientConfig).fetch(
8 | groq`*[_type == "project"]{
9 | _id,
10 | _createdAt,
11 | name,
12 | "slug": slug.current,
13 | "image": image.asset->url,
14 | url,
15 | content
16 | }`
17 | )
18 | }
19 |
20 | export async function getProject(slug: string): Promise {
21 | return createClient(clientConfig).fetch(
22 | groq`*[_type == "project" && slug.current == $slug][0]{
23 | _id,
24 | _createdAt,
25 | name,
26 | "slug": slug.current,
27 | "image": image.asset->url,
28 | url,
29 | content
30 | }`,
31 | { slug }
32 | )
33 | }
34 |
35 | export async function getPages(): Promise {
36 | return createClient(clientConfig).fetch(
37 | groq`*[_type == "page"]{
38 | _id,
39 | _createdAt,
40 | title,
41 | "slug": slug.current
42 | }`
43 | )
44 | }
45 |
46 | export async function getPage(slug: string): Promise {
47 | return createClient(clientConfig).fetch(
48 | groq`*[_type == "page" && slug.current == $slug][0]{
49 | _id,
50 | _createdAt,
51 | title,
52 | "slug": slug.current,
53 | content
54 | }`,
55 | { slug }
56 | )
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | ```
14 |
15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16 |
17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
18 |
19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
20 |
21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
22 |
23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
24 |
25 | ## Learn More
26 |
27 | To learn more about Next.js, take a look at the following resources:
28 |
29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
31 |
32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
33 |
34 | ## Deploy on Vercel
35 |
36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
37 |
38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
39 |
--------------------------------------------------------------------------------