Dette er workshoppen for deg som er helt ny med Sanity. Her vil du lære å bygge skjemaer og litt om de forskjellige innholdstypene, og hvordan man kan bruke de for å bygge opp forskjellige dokumenter.
På slutten av workshoppen sitter du igjen med din helt egne portfolio-side med innebygget CMS, som er klar til å prodsettes! 🚀
For å komme i gang med utvikling i Sanity, er det greit å ha litt kjennskap til JavaScript eller TypeScript. Det er likevel helt mulig å få til workshoppen uten å være særlig godt kjent i språkene. ✨
Selve redaktørverktøyet er Sanity, som er tilgjengelig som et bibliotek vi bruker inne i frontend-appen.
Frontenden til portfolioen-appen er skrevet i React ⚛️ og NextJs 🔼 med app
-folder.
Der brukes NextUI 🧱 til noen av komponentene, og tailwindcss 🎨 til stilsetting.
For enkel kobling mellom Sanity og Next brukes Sanity.io toolkit for Next.js 🔧
Før du kan begynne med selve workshoppen må vi laste ned prosjektet og installere litt avhengigheter.
- Du må å ha
node
installert. git clone
prosjektet ned til din maskin- Gå inn i prosjekt-mappen og innstallerer avhengighetene med
npm install
- Først av alt må du gå på https://www.sanity.io/login/sign-up og lage deg en bruker. Det enkleste er kanskje å bruke
github
-brukeren din - Her blir det litt hårete for å få satt opp prosjektet til rett bruker. Så her er det greit å ha tunga rett i munnen 👅.
- Kjør
npm -y create sanity@latest
i prosjekt-mappa - Velg påloggingstypen du bruke for å registrere deg i steg 1, vent til den hopper inn i nettleseren og logger deg inn.
- Gi prosjektet ditt et navn
- Svar på følgende spørsmål:
Use the default dataset configuration?
Yes
Would you like to add configuration files for a Sanity project in this Next.js folder?
Yes
Do you want to use TypeScript?
Yes
Would you like an embedded Sanity Studio?
Yes
Would you like to use the Next.js app directory for routes?
Yes
What route do you want to use for the Studio?
/studio
File /app/studio/[[...index]]/page.tsx already exists. Do you want to overwrite it?
No
File /sanity.config.ts already exists. Do you want to overwrite it?
No
File /sanity.cli.ts already exists. Do you want to overwrite it?
No
Select project template to use
Clean project with no predefined schemas
File /sanity/schema.ts already exists. Do you want to overwrite it?
No
File /sanity/env.ts already exists. Do you want to overwrite it?
No
File /sanity/lib/client.ts already exists. Do you want to overwrite it?
No
File /sanity/lib/image.ts already exists. Do you want to overwrite it?
No
Would you like to add the project ID and dataset to your .env file?
Yes
- Og da skal du være klar til å starte appen med kommandoen
npm run dev
.
- Appen starter opp på http://localhost:3000
- Naviger deg fra forsiden inn til studioet.
- Der vil du få forespørsel om å legge til CORS origin i Sanity prosjektet. Velg Continue
- Du vil bli flyttet til Sanity sine sider. Velg Add CORS origin
- Da, er du ferdig og klar! 👏✨
Du kommer til å se noen emojis i oppgavene. De betyr ca det her:
- 🏆 Oppgave: Her er hva du skal gjøre
- 💡 Tips: Litt ekstra info som kan være greit å være for å løse en oppgave
- ✅ Testing av løsningen: Hvordan du kan sjekke at det du har gjør blir riktig
- 🚨 Løsningsforslag: Her finner du en komplett gjennomgang av hvordan du kan løse oppgaven
Vi starter litt enkelt. Vi trenger å lage et dokument for en forfatter, for å så legge til litt data om oss selv.
For å lage dokumenter, må vi definere en schema for hvordan dataen ser ut. I Sanity har alle schemas noen spesifikke felter:
name
som gir navn til et felt.type
som spesifiserer hvilke type skjema det skal være.fields
som er hvilke felter skjemaet skal inneholde.
For å registrere skjemaer må du importere det og legge det til i lista over forskjellige skjema-typer i /sanity/schema.ts
🏆 I filen /sanity/schemas/author.ts
, kan du lage et dokument-type schema
for author
, som inneholder et felt name
av typen string
.
✅ For å se om det har blitt riktig kan du åpne Sanity studioet på http://localhost:3000/studio/. Det skal automatisk ha blitt lagt til en "mappe" for forfattere, hvor man kan trykke på 📝-ikonet for å lage et nytt dokument. Dette bør inneholde et enkelt input felt for å fylle inn navn på forfatteren.
💡 Vi får mye hjelp av TypeScript til å definere skjemaer.
Skjema-definisjoner kan types medSchemaTypeDefinition
så får man feilmelding hvis man prøver å legge til noen attributter som ikke er gyldige!
💡 Du kan endre tittel og legge til en beskrivelse på felter med å legge til
title
ogdescription
på felter.
💡 NB: Selv om du kan lage flere forfatter-dokumenter, er frontenden konfigurert til å kun bruke det som var laget først hvis det er flere 🤠
🚨 Løsningforslag
I filen sanity/schemas/author.ts
må vi fylle inn de grunnleggende feltene for dokument-skjemaet vårt i author
-objektet. Fordi dette skal være et enkeltstående dokument vi kan hente data fra, så må det ha typen document
.
Hvis man ønsker kan man gi det en tittel.
Alle dokumenter har en liste fields
med hvilke felter dokumentet skal inneholde. Her må vi legge til en liste som inneholder et objekt som definerer name
-feltet.
export const author: SchemaTypeDefinition = {
name: "author",
type: "document",
title: "Forfatter",
fields: [{ name: "name", title: "Navn", type: "string" }],
};
Alle skjema-typer må registreres slik at Sanity-studio vet at de eksisterer. Dette kan gjøres enkelt i sanity/schema.ts
, ved å importere author
fra underliggende mappen, og legge det til i arrayet med skjemaer.
export const schema: { types: SchemaTypeDefinition[] } = {
types: [author],
};
Det finnes flere måter å vise felter på. string
gir et helt standard lite input
-felt å skrive i. Et alternativ for litt lengre tekster vil være å bruke typen text
som gir et textarea
-felt med muligheten til å justere størrelsen på input-feltet.
🏆 Legg til et felt bio
av typen text
på forfatter-objektet.
🏆 Juster samtidig bio
feltet slik at det bare er 3 rader stort.
✅ Hvis alt blir riktig kan du se at det dukker opp et nytt felt på forfatter-dokumentet i studioet.
🚨 Løsningforslag
Her kan vi enkelt og greit legge til et nytt felt, men denne gangen med typen text
. Man kan også legge på attributtet rows
for å styre hvor mange rader feltet har når man åpner dokumentet.
i sanity/schemas/author.ts
export const author: SchemaTypeDefinition = {
name: "author",
type: "document",
title: "Forfatter",
fields: [
{ name: "name", title: "Navn", type: "string" },
{ name: "bio", title: "Biografi", type: "text", rows: 3 },
],
};
Det er fort gjort å gjøre feil! Derfor er det greit å legge på litt enkle valideringer som forhindrer oss å publisere feilaktig data.
En av de enkleste valideringene er å sette felt som påkrevd, men det finnes mange andre typer valideringsregler man også kan bruke rett ut av boksen. Det er også mulig å lage egne regler.
🏆 Lag en regel som gjør feltet name
påkrevd
🏆 Lag en regel som gjør at feltet bio
er både påkrevet og skal være mellom 30 og 160 tegn.
✅ Gi studioet en liten refresh ♻️. Hvis alt går som det skal vil du få en feilmelding i det du tømmer en av feltene. Feilmeldingene vil forhindre at dokumentet publiseres. Hvis det fungerer som det skal, er det bare å fylle ut feltene og publisere dokumentet. 🚀
Nå skal det begynne å dukke opp noe på forsiden av appen vår.
💡 Det er også nyttig å legge til description på felter og av og til hjelpetekst i valideringer.
🚨 Løsningforslag
Her må vi legge på validation
på hvert av feltene våre. Denne tar inn en funksjon som tar i mot et rule
-objekt man kan legge til valideringer på.
Her skal vi legge til henholdsvis (rule) => rule.required()
for påkrevd og min(30)
og max(160)
for å styre antall tegn.
I sanity/schemas/author.ts
export const author: SchemaTypeDefinition = {
name: "author",
type: "document",
title: "Forfatter",
fields: [
{
name: "name",
title: "Navn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "bio",
title: "Biografi",
type: "text",
rows: 3,
validation: (rule) => rule.required().min(30).max(160),
},
],
};
Det er også mulig å nøste felter sammen i objekter. Det er fint å benytte seg av når man begynner å få mange felter og det gir mening med en dypere struktur.
Vi skal nå utvide forsiden vår med litt lenker til forskjellige sosiale medier.
🏆 Lag et felt socials
av typen object
med underfelter github
, twitter
og linkedin
som er lenker til forskjellige profiler.
💡 Hvis man skal bruke URL'er finnes det en egen felt-type url
som automatisk validerer at det er i riktig format.
💡 Felter av typen object
kan ta et felt options
med collapsible
og collapsed
for å enkelt "lukke" objektet.
✅ Fyll ut feltene og publiser dokumentet på nytt. Forsiden skal nå ha lenker til de forskjellige feltene. Du trenger ikke fylle ut alle hvis du ikke bruker alle tjenestene. Feltene er tross alt ikke påkrevd.
🚨 Løsningforslag
Her må vi først legge til et felt av typen object
. Deretter kan man legge på ytteligere fields
inne i objektet.
Ved å bruke typen url
på disse nøsta feltene, vil vi få validering ut av boksen.
Som en bonus kan man legge på optionene collapsible
og collapsed
for å gjøre feltet ekspanderbart, og lukket når man åpner dokumentet.
Det er kanskje ikke nødvendig her, men på store dokumenter, er det ganske greit å holde det litt ryddig.
I sanity/schemas/author.ts
export const author: SchemaTypeDefinition = {
name: "author",
type: "document",
title: "Forfatter",
fields: [
{
name: "name",
title: "Navn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "bio",
title: "Biografi",
type: "text",
rows: 3,
validation: (rule) => rule.required().min(30).max(160),
},
{
name: "socials",
title: "Sosiale medier",
type: "object",
options: {
collapsible: true,
collapsed: true,
},
fields: [
{
name: "github",
type: "url",
},
{
name: "linkedin",
type: "url",
},
{
name: "twitter",
type: "url",
},
],
},
],
};
En av de aller beste måtene å presentere innhold på med er med bilder, og nå er det på tide å lage muligheten for å legge til et bilde av forfatteren.
Sanity har en egen type for bilder, og har et kraftig bildeverktøy for å generere lenker til forskjellige størrelser og varianter av et bilde som er lastet opp.
🏆 Legg inn et felt image
for av bilde på forfatteren.
🏆 Lag støtte for å kunne sette en hotspot
på bildet
✅ Legg inn et fint bilde. Gå over til forsiden igjen og se at det dukker opp istedenfor placeholder-bildet. Hvis bildet er litt rart croppa, kan du justere det med croppe-verktøyet oppe i høyre hjørnet av bilde-feltet. ✂️
🚨 Løsningforslag
Her legger vi til et felt av typen image
. På det kan man legge til en option
for hotspot
for å gjøre det mulig å legge til croppe-muligheter.
I sanity/schemas/author.ts
export const author: SchemaTypeDefinition = {
name: "author",
type: "document",
title: "Forfatter",
fields: [
{
name: "name",
title: "Navn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "bio",
title: "Biografi",
type: "text",
rows: 3,
validation: (rule) => rule.required().min(30).max(160),
},
{
name: "image",
title: "Bilde",
type: "image",
options: {
hotspot: true,
},
},
{
name: "socials",
title: "Sosiale medier",
type: "object",
options: {
collapsible: true,
collapsed: true,
},
fields: [
{
name: "github",
type: "url",
},
{
name: "linkedin",
type: "url",
},
{
name: "twitter",
type: "url",
},
],
},
],
};
Nok om oss selv 💅. Hele poenget med en portfolio er jo å vise frem litt prosjekter man har gjort! Nå er det på tide at vi går i gang med å lage dokument-skjemaet for prosjekter.
🏆 Lag dokumenttypen for prosjekter i /sanity/schemas/project.ts.
- Et prosjektnavn som heter
projectName
- En
slug
🐌 som heterslug
- En slug er den siste delen av en
URL
. Her kunne vi ha brukt den innebygde skjulte feltet_id
som ligger på dokumentet. Men det er mye mer SEO-vennlig med en lesbar og relevantURL
.
- En slug er den siste delen av en
- En kort beskrivelse som heter
shortDescription
- En
dato
som heterdate
- Et bilde som heter
image
🏆 Gjør alle feltene påkrevd
🏆 Legg til en knapp for automatisk slug-generering som bruker projectName
feltet
🏆 Gi feltene noen bedre visningsnavn i studioet 🏷️
💡 Dokumentasjonen til skjema-typene forteller mye spennende om hvilke options
man kan legge på de forskjellige type feltene.
💡 Unsplash har mange gode placeholder-bilder hvis man ikke har bilder til prosjektene sine.
✅ Fyll inn feltene og se om det dukker opp et prosjekt på forsiden. Se at det går an å trykke seg inn der!
🚨 Løsningforslag
Her går vi rett å slett i gang med å legge til feltene som trengs.
slug
typen har en option
som heter source
som vil legge til muligheten for å generere en slug basert på sourcen
Feltene må inneholde en title
for å få bedre visningsnavn.
Her må man også huske på å legge til den nye skjema-typen vår i sanity/schema.ts
I sanity/schemas/project.ts
export const project: SchemaTypeDefinition = {
name: "project",
title: "Prosjekter",
type: "document",
fields: [
{
name: "projectName",
title: "Prosjektnavn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "shortDescription",
title: "En kort beskrivelse av prosjektet",
type: "text",
validation: (rule) => rule.required(),
},
{
name: "slug",
type: "slug",
options: { source: "projectName" },
validation: (rule) => rule.required(),
},
{
name: "date",
title: "Dato",
type: "date",
},
{
name: "image",
title: "Prosjektbilde",
type: "image",
validation: (rule) => rule.required(),
},
],
};
I sanity/schema.ts
export const schema: { types: SchemaTypeDefinition[] } = {
types: [author, project],
};
Vi ønsker å kunne tagge prosjektene våre med relevant nøkkelord. Siden vi har flere av disse, så passer det seg å ta i bruk array
-typen. Man kan putte hva som helst i et array
, men vi skal gå for noen enkle nøkkelord.
🏆 Legg til et felt keywords
som er en liste av string
🏆 Endre layout til tags
sånn at det blir enkelt å legge til tags.
🚨 Løsningforslag
I sanity/schemas/project.ts
export const project: SchemaTypeDefinition = {
name: "project",
title: "Prosjekter",
type: "document",
fields: [
{
name: "projectName",
title: "Prosjektnavn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "shortDescription",
title: "En kort beskrivelse av prosjektet",
type: "text",
validation: (rule) => rule.required(),
},
{
name: "slug",
type: "slug",
options: { source: "projectName" },
validation: (rule) => rule.required(),
},
{
name: "date",
title: "Dato",
type: "date",
},
{
name: "keywords",
title: "Nøkkelord",
type: "array",
of: [{ type: "string" }],
options: {
layout: "tags",
},
},
{
name: "image",
title: "Prosjektbilde",
type: "image",
validation: (rule) => rule.required(),
},
],
};
Vanlige string
-baserte felter kan være litt begrensende hvis man skal produsere mye innhold til en side. En av superkreftene til Sanity er block content som gir en kraftig og tilpassningsvennlig WYSIWYG-editor.
Dette gjør det mulig å berike tekst med en eller annen form for markup. Som for eksempel å gjøre en tekst bold eller italic. Det gjør det også mulig å markere tekst som for eksempel headere (<h1>
).
🏆 Legg til et felt content
som er en riktekst editor.
✅ Prøv å fylle ut litt innhold om et prosjekt og publiser det. Innholdet vil dukke opp når du trykker inn på prosjektet.
🚨 Løsningforslag
I sanity har rik-tekst innhold typen block
. Hvis man lager et array
av typen block
vil Sanity automatisk vise dette som et felt med riktekst.
I sanity/schemas/project.ts
export const project: SchemaTypeDefinition = {
name: "project",
title: "Prosjekter",
type: "document",
fields: [
{
name: "projectName",
title: "Prosjektnavn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "shortDescription",
title: "En kort beskrivelse av prosjektet",
type: "text",
validation: (rule) => rule.required(),
},
{
name: "slug",
type: "slug",
options: { source: "projectName" },
validation: (rule) => rule.required(),
},
{
name: "date",
title: "Dato",
type: "date",
},
{
name: "keywords",
title: "Nøkkelord",
type: "array",
of: [{ type: "string" }],
options: {
layout: "tags",
},
},
{
name: "image",
title: "Prosjektbilde",
type: "image",
validation: (rule) => rule.required(),
},
{
name: "content",
title: "Content",
type: "array",
of: [
{
type: "block",
},
],
},
],
};
Sanity er veldig konfigurerbart. Man kan både avgrense og utvide støtte for forskjellig markup i riktekst-editoren. Men i vår editor kan ikke bare være tekst i tekst-editoren 🤡. Vi ønsker nemlig å kunne bryte opp wall-of-text beskrivelsen av prosjektene med litt fine bilder.
🏆 Utvid rik-tekst editoren vår med støtte for en type image
💡 Riktekst er et array
av block
. Hva skjer om vi legger til andre ting også her?
✅ I riktekst-editoren vil det nå dukke opp en liten knapp i høyre hjørne for å legge til et bilde. Legg til et bilde, publiser, og sjekk at det dukker opp rett på prosjekt-siden.
🚨 Løsningforslag
Vi utvider hvilke typer som skal være tilgjengelige i array
et og legger på et image
I sanity/schemas/project.ts
export const project: SchemaTypeDefinition = {
name: "project",
title: "Prosjekter",
type: "document",
fields: [
{
name: "projectName",
title: "Prosjektnavn",
type: "string",
validation: (rule) => rule.required(),
},
{
name: "shortDescription",
title: "En kort beskrivelse av prosjektet",
type: "text",
validation: (rule) => rule.required(),
},
{
name: "slug",
type: "slug",
options: { source: "projectName" },
validation: (rule) => rule.required(),
},
{
name: "date",
title: "Dato",
type: "date",
},
{
name: "keywords",
title: "Nøkkelord",
type: "array",
of: [{ type: "string" }],
options: {
layout: "tags",
},
},
{
name: "image",
title: "Prosjektbilde",
type: "image",
validation: (rule) => rule.required(),
},
{
name: "content",
title: "Content",
type: "array",
of: [
{
type: "block",
},
{
type: "image",
},
],
},
],
};
Gratulerer! Da er du ferdig med portfolio-nettsiden 🤩.
Hvis du vil så kan du prøve å bryne deg på noen av ekstraoppgavene ⭐️
Du kan rimelig enkelt putte appen din i produksjon! Vercel er en rask og enkel måte å deploye NextJs-apper på! Det du trenger å gjøre er å dytte koden til prosjektet ditt opp i et eget Github-repository og så koble Vercel på det.
Du må huske å konfigurere env
-variablene for Sanity-tilgang på Vercel, samt å åpne opp for en ny CORS-policy hos Sanity
Det kan også være nyttig å justere på revalidate
-intervallet som er satt i funksjonene for å hente data i /utils/author.ts
og /utils/projects.ts
. Sånn som det er satt opp nå vil den hente dataen for hver eneste besøkende på siden, men hvis det ikke endrer seg så ofte kan man godt skru denne opp. Du kan lese mer om data-henting, caching og revalidering på NextJs-dokumentasjonen
Det nytter ikke å ha en flunkende ny portfolio-app uten innhold! Bruk litt tid på å fylle ut noen av prosjektene du har gjort tidligere.
Det er helt supert om du gjør frontenden din egen! Frontenden bruker NextUI og tailwindcss som gir både komponenter og en hel haug av stiler ut av boksen. Det er også veldig enkelt å justere ting hvis det er noe du ikke er fornøyd med.
Det går fint an å utvide med noen ekstra felter hvis man ønsker det. Spørringene for å hente ut data ligger i
/utils/
-mappa. De henter nå ut alle feltene som legges inn på dokumenter.
Hvis man vil se litt på mer avanserte måter å hente ut data, kan man sjekke ut query-språket til Sanity, som er groq
.