Kas tas Keystone.js ir kodėl jis įdomus
Jei esi dirbęs su headless CMS sistemomis, tikriausiai žinai, kad rinkoje jų – kaip šiukšlių po lietaus. Bet Keystone.js išsiskiria vienu labai svarbiu dalyku – jis nuo pat pradžių buvo kuriamas su GraphQL galvoje. Ne kaip priedas, ne kaip „o, dar galima ir per GraphQL”, bet kaip pagrindinis duomenų sąveikos būdas.
Keystone.js yra open-source headless CMS, pastatytas ant Node.js ir React. Versija 6, kuri šiuo metu yra aktuali, buvo visiškai perrašyta nuo nulio ir tapo dar galingesnė. Sistema leidžia greitai sukurti administravimo sąsają, API ir valdyti duomenis be didelių galvos skausmų. O geriausias dalykas – viskas automatiškai generuojama iš tavo duomenų schemos.
GraphQL integracija – ne priedas, o pagrindas
Štai kur prasideda tikrasis malonumas. Kai apibrėžiate savo duomenų modelius Keystone.js, sistema automatiškai sugeneruoja visą GraphQL schemą. Ir ne kokią nors bazinę – pilnavertę, su visais CRUD operacijomis, filtravimo galimybėmis, ryšiais tarp modelių ir net autentifikacija.
Pavyzdžiui, jei sukuriate paprastą blog’o sistemą:
import { list } from '@keystone-6/core';
import { text, relationship, timestamp } from '@keystone-6/core/fields';
export const Post = list({
fields: {
title: text({ validation: { isRequired: true } }),
content: text({ ui: { displayMode: ‘textarea’ } }),
author: relationship({ ref: ‘User.posts’, many: false }),
publishedAt: timestamp(),
},
});
Iš tokio paprasčiausio kodo Keystone automatiškai sukuria GraphQL queries kaip posts, post, mutations kaip createPost, updatePost, deletePost, ir net sudėtingesnius dalykus kaip postsCount. Viskas veikia out of the box.
Filtravimas ir paginacija – jau įdiegta
Vienas iš dalykų, kuris mane tikrai nustebino pirmą kartą dirbant su Keystone – tai kaip gerai išspręstas filtravimas. GraphQL API automatiškai palaiko sudėtingus filtrus visiem tavo laukams.
Gali rašyti queries tokius kaip:
query {
posts(
where: {
AND: [
{ title: { contains: "GraphQL" } }
{ publishedAt: { lte: "2024-01-01" } }
{ author: { name: { equals: "Jonas" } } }
]
}
take: 10
skip: 0
orderBy: { publishedAt: DESC }
) {
id
title
author {
name
}
}
}
Viskas veikia be jokio papildomo kodo. Sistema supranta tavo duomenų tipus ir automatiškai sukuria atitinkamus filtrus – contains, startsWith, equals, gt, lt ir panašiai. Paginacija su take ir skip taip pat veikia iš karto.
Admin UI, kuris nesukelia pyktį
Dažnas headless CMS minusas – arba negauni admin sąsajos visai, arba gauni tokią, kurią norisi išmesti pro langą. Keystone čia tikrai pasistengė. Admin UI yra React aplikacija, kuri automatiškai generuojama iš tavo schemos, bet ji nėra kažkoks generinis šlamštas.
Sąsaja yra intuitivi, greita ir tikrai naudojama. Gali ją customizuoti, pridėti savo komponentus, pakeisti išvaizdą. Bet net ir default versija atrodo profesionaliai ir veikia sklandžiai. Klientams galima drąsiai rodyti – nesigėdijant.
Dar vienas pliusas – visi ryšiai tarp modelių (relationships) veikia labai gerai. Gali sukurti many-to-many, one-to-many ryšius, ir admin sąsajoje viskas bus gražiai atvaizduota su paieškos galimybėmis ir dropdown’ais.
Hooks ir custom logika
Realybėje niekada neužtenka tik CRUD operacijų. Reikia validacijos, reikia papildomos logikos prieš išsaugant, reikia siųsti email’us, reikia… na, supratote. Keystone turi puikią hooks sistemą, kuri leidžia įsikišti į bet kurį proceso etapą.
Pavyzdžiui, jei norite automatiškai nustatyti slug’ą iš pavadinimo:
export const Post = list({
fields: {
title: text({ validation: { isRequired: true } }),
slug: text({
isIndexed: 'unique',
ui: { createView: { fieldMode: 'hidden' } }
}),
},
hooks: {
resolveInput: async ({ resolvedData, operation }) => {
if (operation === 'create' && resolvedData.title) {
resolvedData.slug = resolvedData.title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-');
}
return resolvedData;
},
},
});
Yra hooks’ų prieš ir po kiekvienos operacijos: resolveInput, validateInput, beforeOperation, afterOperation. Galite valdyti logiką labai detaliai.
Autentifikacija ir prieigos kontrolė
Čia Keystone tikrai šviečia. Sistema turi įmontuotą autentifikacijos sistemą, kuri veikia su session’ais arba JWT. Bet dar įdomiau – labai galingą prieigos kontrolės (access control) sistemą.
Galite apibrėžti prieigą kiekvienam modeliui, kiekvienam laukui, net kiekvienai operacijai atskirai. Ir tai nėra kažkoks paprastas „logged in arba ne” – galite rašyti sudėtingas funkcijas, kurios tikrina bet kokias sąlygas:
export const Post = list({
access: {
operation: {
query: () => true,
create: ({ session }) => !!session,
update: ({ session, item }) => {
if (!session) return false;
if (session.data.isAdmin) return true;
return item.authorId === session.itemId;
},
delete: ({ session }) => session?.data.isAdmin === true,
},
},
fields: {
// ...
},
});
Tokiu būdu galite leisti visiems skaityti, bet redaguoti tik autoriui arba adminui. Ir visa ši logika automatiškai veikia tiek GraphQL API, tiek Admin UI.
Darbas su failais ir vaizdais
Kiekviena CMS sistema turi gerai dirbti su failais. Keystone turi file ir image field tipus, kurie palaiko įvairius storage backend’us – lokalų file system, S3, Cloudinary ir kitus.
Vaizdams yra automatinis resize’inimas ir optimizavimas. Galite apibrėžti, kokių dydžių versijos jums reikia, ir Keystone pasirūpins viskuo:
import { image } from '@keystone-6/core/fields';
export const Post = list({
fields: {
title: text(),
coverImage: image({ storage: ‘my_local_images’ }),
},
});
GraphQL API automatiškai grąžina URL’us į originalius ir resize’intus vaizdus. Admin sąsajoje galite drag-and-drop’inti failus. Viskas veikia taip, kaip tikėtumėtės.
Ką reikia žinoti prieš pradedant projektą
Gerai, dabar apie realybę. Keystone.js nėra tobulas, ir yra dalykų, kuriuos reikia žinoti prieš įsipareigojant.
Pirma, dokumentacija yra gera, bet ne ideali. Kartais randi save besikasantį po GitHub issues, ieškodamas atsakymų į specifines problemas. Community nėra tokia didelė kaip Strapi ar Contentful, bet žmonės aktyvūs ir padeda.
Antra, jei tau reikia labai specifinių dalykų, kartais teks rašyti custom sprendimus. Keystone yra labai extensible, bet tai reiškia, kad kartais reikės pasikasti į kodą. Tai nėra WordPress, kur visam yra plugin’as.
Trečia, performance. Jei planuoji labai didelį projektą su milijonais įrašų, reikės pagalvoti apie optimizavimą. Default setup’as yra geras, bet ne optimizuotas ekstremaliam scale’ui. Nors, tiesą sakant, tai galioja daugumai CMS sistemų.
Dar vienas dalykas – deployment. Keystone yra Node.js aplikacija, tai reiškia, kad negali tiesiog upload’inti į shared hosting’ą. Reikia serverio, kur gali paleisti Node.js. Vercel, Railway, Heroku, Digital Ocean – visi šie veikia puikiai, bet tai papildomas kompleksiškumas, palyginus su tradicinėmis CMS.
Duomenų bazės palaikymas yra geras – PostgreSQL, MySQL, SQLite. MongoDB nepalaikomas, nes Keystone naudoja Prisma kaip ORM, o Prisma su MongoDB dar turi savo keblumų.
Kada Keystone.js yra geriausias pasirinkimas
Jei kuri projektą, kur frontend ir backend yra atskirti, ir nori turėti stiprų GraphQL API – Keystone yra puikus pasirinkimas. Ypač jei komandoje yra žmonių, kurie moka React ir Node.js.
Jis puikiai tinka:
– Marketing svetainėms su headless architektūra
– Blog’ams ir content platformoms
– E-commerce backend’ams (su papildomomis integracijomis)
– Internal tools ir admin dashboards
– API-first projektams
Netinka, jei:
– Reikia tradicinės monolithic CMS su theming sistema (geriau WordPress)
– Projektas labai paprastas ir nereikia GraphQL galimybių
– Komanda neturi patirties su JavaScript ekosistema
– Reikia milžiniškos plugin’ų ekosistemos
Aš asmeniškai naudoju Keystone jau keliuose projektuose ir esu patenkintas. Pradinis setup’as užtrunka gal valandą, po to vystymas eina labai sklandžiai. GraphQL API veikia puikiai su Next.js, Gatsby, arba bet kokiu kitu frontend framework’u.
Vienas projektas buvo marketing svetainė su Next.js frontend’u. Keystone leido klientui lengvai valdyti turinį, o mums – turėti visišką kontrolę kaip tas turinys atvaizduojamas. Kitas projektas – internal tool su sudėtingais duomenų ryšiais ir specifine logika. Keystone hooks sistema leido viską implementuoti be didelių skausmų.
Jei galvoji apie Keystone savo projektui – rekomenduoju tiesiog išbandyti. Oficialus starter projektas paleidžiamas per kelias minutes, ir gali greitai pamatyti ar tai tinka tavo poreikiams. Sistema yra pakankamai lanksti, kad galėtum pritaikyti ją beveik bet kokiam use case’ui, bet pakankamai opinionated, kad nebūtų per daug sprendimų, kuriuos reikia priimti.
GraphQL integracija tikrai yra killer feature. Jei dirbi su modern JavaScript stack’u ir nori CMS, kuri natūraliai integruojasi su tavo workflow – Keystone.js tikrai verta dėmesio.
