Dla stron usługowych w Next.js Sanity rozwiązuje konkretny problem, który początkowo może nie być taki oczywisty. Nietechniczny klient może samodzielnie edytować treści - teksty, zdjęcia, meta tagi, FAQ to sekcja najczęściej zadawanych pytań i odpowiedzi, często używana też do danych strukturalnych. - i to bez angażowania dewelopera przy każdej zmianie.
Setup
Code
# Inicjalizacja Sanity w projekcie Next.jsnpm create sanity@latest -- --project-id xxx --dataset production --template cleannpm install next-sanity @sanity/image-url @portabletext/react
Oczywiście możesz też użyć yarn zamiast npm.
Sanity Studio - czyli panel admina - działa jako route w Twojej aplikacji Next.js, czyli wchodzisz na /studio.
SANITY_API_READ_TOKEN generujesz w manage.sanity.io → API, czyli Application Programming Interface, definiuje sposób komunikacji między aplikacjami lub modułami. Tu chodzi o konwencje plików Next.js, które zamieniają eksportowaną funkcję w gotowy plik sitemap.xml lub robots.txt. → Tokens → dodaj token z uprawnieniami Viewer.
Przy Draft Mode w Next.js pozwala tymczasowo ominąć cache i renderować nieopublikowane lub robocze treści., preview i Visual Editing używaj previewClient — widzi najnowsze drafty zamiast danych z CDN, czyli Content Delivery Network, to rozproszona sieć serwerów dostarczająca zasoby z węzła najbliższego użytkownikowi; CDN do obrazów dodatkowo transformuje je w locie..
Pomocnik urlFor
Code
// lib/sanity/image.tsimport imageUrlBuilder from '@sanity/image-url'import { client } from './client'const builder = imageUrlBuilder(client)export function urlFor(source: Parameters<typeof builder.image>[0]) { return builder.image(source)}
Schema — definicja typów treści
Najpierw blockContent — typ wielokrotnego użytku dla pól Portable Text:
Wygeneruj typy TypeScript ze schemy, żeby uniknąć any w komponentach:
Code
npx sanity typegen generate
Tworzy sanity.types.ts — importuj stamtąd typy zamiast pisać je ręcznie.
Zapytania GROQ
GROQ to język zapytań Sanity służący do pobierania i filtrowania treści z datasetu. to język zapytań Sanity — podobny do GraphQL, ale
prostszy. Każde zapytanie powinno deklarować cache tagi, żeby on-demand
revalidation działała poprawnie:
Zamiast czekać na rewalidację czasową — odśwież stronę natychmiast po edycji w Sanity:
Code
// app/api/revalidate/route.tsimport { revalidateTag } from 'next/cache'import { NextRequest, NextResponse } from 'next/server'import { parseBody } from 'next-sanity/webhook'export async function POST(req: NextRequest) { try { const { isValidSignature, body } = await parseBody( req, process.env.SANITY_WEBHOOK_SECRET, ) if (!isValidSignature) { return NextResponse.json({ error: 'Invalid signature' }, { status: 401 }) } const { _type, slug } = body if (_type === 'post') { revalidateTag('posts') if (slug?.current) revalidateTag(`post-${slug.current}`) } return NextResponse.json({ revalidated: true }) } catch (error) { return NextResponse.json({ error: 'Bad Request' }, { status: 400 }) }}
W panelu Sanity: Manage → API → Webhooks → dodaj URL (https://twoja-domena.pl/api/revalidate) i secret.
Draft Mode — włączanie podglądu
Draft Mode to mechanizm Next.js przełączający rendering z cache'owanych danych na dane na żywo — czyli drafty z Sanity. Potrzebujesz dwóch route'ów: jeden włącza podgląd, drugi go wyłącza:
Code
// app/api/draft/enable/route.tsimport { draftMode } from 'next/headers'import { redirect } from 'next/navigation'import { NextRequest } from 'next/server'export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) if (searchParams.get('secret') !== process.env.SANITY_PREVIEW_SECRET) { return new Response('Invalid token', { status: 401 }) } const draft = await draftMode() draft.enable() redirect(searchParams.get('redirect') || '/')}
Code
// app/api/draft/disable/route.tsimport { draftMode } from 'next/headers'import { redirect } from 'next/navigation'export async function GET() { const draft = await draftMode() draft.disable() redirect('/')}
W Sanity Studio skonfiguruj Presentation Tool z URL podglądu:
previewClient ma perspective: 'previewDrafts' — zwraca nieopublikowane zmiany. Dla pełnego preview na żywo z aktualizacjami w czasie rzeczywistym (bez przeładowania strony) użyj VisualEditing razem z @sanity/preview-kit — dane są wtedy synchronizowane przez WebSocket w momencie każdej zmiany w edytorze.
Visual Editing — edycja treści na żywej stronie
Visual Editing pozwala klientowi kliknąć dowolny element na żywej stronie i edytować go bez otwierania panelu Studio:
Klient widzi stronę jak użytkownik, ale edytowalne elementy dostają overlay prowadzący do Sanity Studio lub Presentation Tool. Jeśli Studio jest osadzone w tej samej aplikacji, trzymaj jego route w osobnej grupie layoutów i nie renderuj VisualEditing nad panelem Studio.
Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.
Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty side-projecty.