@manifolio/sdk citește conținutul din Next.js, Astro, Cloudflare Workers sau orice server cu Node 18+. Nu are dependențe, dă tip fiecărei intrări și verifică webhook-urile.
npm i @manifolio/sdkcreateClient
import { createClient } from "@manifolio/sdk";
export const cms = createClient({
project: process.env.MANIFOLIO_PROJECT!, // id-ul proiectului
key: process.env.MANIFOLIO_KEY!, // mf_live_ sau mf_test_
locale: "ro", // limba implicită a cererilor
});| Opțiune | Ce face |
|---|---|
project | id-ul proiectului, din Developers → API keys → Connection |
key | o cheie secretă; cheile publicabile mf_pk_ sunt refuzate |
locale | limba implicită; altfel, limba principală a proiectului |
environment | production sau development; dacă e dat, trebuie să se potrivească cu cheia |
preview | citește ciornele prin Preview API (cheia are nevoie de content:preview) |
baseUrl | implicit https://api.manifolio.com |
fetch | propriul fetch, de exemplu un service binding din Cloudflare |
fetchOptions | se adaugă la fiecare cerere, de exemplu { next: { revalidate: 60 } } în Next.js |
SDK-ul refuză să ruleze cu o cheie secretă în browser.
Citirea
await cms.entries("article", {
locale: "ro", // cade pe limba principală, câmp cu câmp
fields: ["title", "slug", "date"],
sort: "-date", // published, updated sau un câmp; cu - descrescător
filter: { series: "toamna", date: { gte: "2026-01-01" }, tags: ["cafea", "evenimente"] },
populate: 2, // referințele devin intrări, pe două niveluri
});
await cms.page("article", { limit: 20, cursor }); // { entries, nextCursor }
await cms.entry("article", "primul-articol"); // după slug sau id, null dacă lipsește
await cms.singleton("site_settings"); // intrarea unui tip singleton
await cms.types(); // limbile și schema publicăentries urmează nextCursor pagină cu pagină până le are pe toate, sau până la max intrări. Un array în filter înseamnă in.
Fiecare intrare are _id, _type, _locale, _publishedAt și _updatedAt lângă câmpurile ei.
Erori
Cererile eșuate aruncă ManifolioError, cu status și code:
import { ManifolioError } from "@manifolio/sdk";
try {
await cms.entries("article");
} catch (e) {
if (e instanceof ManifolioError && e.code === "type_not_found") {
// tipul a fost redenumit sau șters
}
}entry și singleton întorc null pentru o intrare care lipsește, în loc să arunce o eroare.
Conținut tipizat
npx manifolio types --out src/manifolio.d.tsComanda citește MANIFOLIO_PROJECT și MANIFOLIO_KEY (și din .env și .env.local) sau --project, --key și --base-url. Fișierul generat îți înregistrează tipurile în SDK: cms.entries("article") întoarce intrări Article, numele câmpurilor se completează singure în fields, filter și sort, iar o cheie de tip necunoscută e eroare de tip. O rulezi din nou după ce schimbi structura.
Previzualizare
export const preview = createClient({
project: process.env.MANIFOLIO_PROJECT!,
key: process.env.MANIFOLIO_PREVIEW_KEY!, // o cheie cu content:preview
preview: true,
});
const ciorna = await preview.entry("article", "primul-articol");
ciorna?._status; // "draft", "published" sau "changed"O pui în spatele modului de ciornă al framework-ului, ca doar editorii să vadă conținutul nepublicat.
Framework-uri
Next.js (App Router), cu o fereastră de reîmprospătare:
export const cms = createClient({
project: process.env.MANIFOLIO_PROJECT!,
key: process.env.MANIFOLIO_KEY!,
fetchOptions: { next: { revalidate: 60 } },
});Astro, citit în frontmatter-ul paginii (la build pentru paginile statice, la fiecare cerere cu un adaptor):
import { createClient } from "@manifolio/sdk";
const cms = createClient({ project: import.meta.env.MANIFOLIO_PROJECT, key: import.meta.env.MANIFOLIO_KEY });
const articole = await cms.entries("article", { sort: "-published" });Cloudflare Workers, printr-un service binding:
const cms = createClient({ project: env.MANIFOLIO_PROJECT, key: env.MANIFOLIO_KEY, fetch: (req, init) => env.API.fetch(req, init) });Verificarea webhook-urilor
import { parseWebhook, verifyWebhook } from "@manifolio/sdk";
const body = await req.text(); // corpul brut, exact cum a sosit
const event = await parseWebhook(process.env.MANIFOLIO_WEBHOOK_SECRET!, body, req.headers.get("manifolio-signature"));parseWebhook aruncă ManifolioError(401, "invalid_signature") când semnătura nu se potrivește sau e mai veche de cinci minute. verifyWebhook întoarce în schimb true sau false. Detalii la Webhook-uri.