profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Hybrid

Collection of Pages with ComponentsTypes of ComponentsSetup server sent events (SSE) content refetchInstall Profound CMS as a proxySkripting i malbyggerenProject ScaffoldingMedia Library

Headless

Quick startSplit Screen JSON Component Builder with LLMComponent Zod Pull

REST API

REST API OverviewgetConnect your websitegetGET /routesgetGET /routegetGET /blocksgetGET /blocks/with-cel-cachegetGET /blocks/generatedgetGET /componentsgetGET /components/{name}getGET /dataset/{schema_name}getGET /content-changes (SSE)patchPATCH /dataset/{schema_name}postEtteroversettelsepatchPATCH /translationsgetGET /usagepostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

Skripting i malbyggeren

En praktisk veiledning i å skrive CEL-uttrykk i CMS-et.

En praktisk veiledning i å skrive CEL-uttrykk i CMS-et.


Slik fungerer CEL

CEL (Common Expression Language) er et lett skriptspråk som er innebygd i CMS-et vårt. Det lar deg skrive dynamiske uttrykk som kan hente data fra dokumenter, lese URL-parametere og beregne verdier underveis.

Dette skjer når et CEL-skript kjører:

Skriptet ditt                   Motoren                        Resultat
    |                              |                              |
    v                              v                              v
documents.get("article", "intro") --> Henter fra databasen --> { headline: "Welcome", body: "..." }
         .headline                --> Henter ut feltet      --> "Welcome"

Tenk på CEL som et skrivebeskyttet spørrespråk. Det kan ikke endre noe i databasen – det leser bare data og returnerer et beregnet resultat. Dette gjør det trygt å bruke hvor som helst i CMS-et.


Byggeklossene

Alle CEL-uttrykk har tilgang til tre ting:

ObjektHva det erEksempel
documentsHent et hvilket som helst dokument fra CMS-etdocuments.get("country", "us")
metaInformasjon om den gjeldende forespørselen (lokale, URL-parametere)meta.locale, meta.params.slug
schemaFeltdefinisjonene til det gjeldende dokumentetschema.fields

Selvreferanser med doc

Når du skriver CEL-uttrykk i en dokumentredigerer, kan du få tilgang til feltverdiene i det gjeldende dokumentet ved hjelp av doc-objektet. Dette muliggjør beregnede felt og referanser på tvers av felt.

// Få tilgang til prisfeltet i det gjeldende dokumentet
doc.price

// Beregn totalen fra felt i det gjeldende dokumentet
doc.price * doc.quantity

// Betingelse basert på statusen til det gjeldende dokumentet
doc.status == "published" ? doc.title : "Draft: " + doc.title

doc-objektet inneholder alle feltverdiene fra dokumentet som redigeres. Dette er nyttig for:

  • Beregnede felt (for eksempel doc.price * doc.quantity)
  • Betinget visningslogikk basert på dokumentets tilstand
  • Uttrykk av valideringstype

Hente dokumenter

Den kraftigste funksjonen i CEL er å hente dokumenter fra hvor som helst i CMS-et.

Hente ett enkelt dokument

Syntaks: documents.get(schemaName, identifier)

La oss si at du har et article-dokument lagret med identifikatoren "welcome-post":

// Lagret i CMS-et som: article / welcome-post
{
  "headline": "Velkommen til plattformen vår",
  "author": "Sarah Chen",
  "body": "Vi gleder oss til å kunngjøre...",
  "tags": ["kunngjøring", "nyheter"]
}

Slik henter du hele dokumentet:

documents.get("article", "welcome-post")

Returnerer:

{
  "headline": "Velkommen til plattformen vår",
  "author": "Sarah Chen",
  "body": "Vi gleder oss til å kunngjøre...",
  "tags": ["kunngjøring", "nyheter"]
}

Slik henter du bare overskriften:

documents.get("article", "welcome-post").headline

Returnerer: "Velkommen til plattformen vår"

Slik henter du forfatteren:

documents.get("article", "welcome-post").author

Returnerer: "Sarah Chen"


Bruke URL-parametere

Når siden din har dynamiske ruter (som /articles/[slug]), kan du bruke meta.params for å hente URL-parameteren og finne riktig dokument.

Hvis noen besøker /articles/welcome-post:

documents.get("article", meta.params.slug).headline

Returnerer: "Velkommen til plattformen vår"

Slik bygger du dynamiske sider – det samme CEL-skriptet fungerer for alle artikler og bruker bare slug-en som finnes i URL-en.


Hente flere dokumenter

Syntaks: documents.find(schemaName) eller documents.find(schemaName, filter)

// Hent alle land
documents.find("country")

Returnerer:

[
  { "code": "us", "name": "USA", "flag": "US" },
  { "code": "sa", "name": "Saudi-Arabia", "flag": "SA" },
  { "code": "gb", "name": "Storbritannia", "flag": "GB" }
]
// Hent land med et filter
documents.find("country", { "where": { "code": "us" } })

Returnerer:

[
  { "code": "us", "name": "USA", "flag": "US" }
]

Oversettelser

CEL støtter henting av oversatt dokumentinnhold på to måter: automatisk oversettelse basert på lokale og eksplisitt oppslag av oversettelser.

Automatisk oversettelse via meta.locale

Når meta.locale er angitt (for eksempel fra ruteparametere eller brukerpreferanser), slår documents.get() automatisk sammen oversatt innhold:

// Hvis meta.locale er "fr", returneres fransk oversettelse slått sammen med grunndokumentet
documents.get("greeting", "welcome").headline

Slik fungerer det:

  1. Henter innholdet i grunndokumentet
  2. Hvis meta.locale ikke er "en" eller "en-US", slår systemet opp oversettelsen i translations-tabellen
  3. Slår oversatte felt sammen med grunninnholdet: { ...baseContent, ...translatedContent }

Dette betyr at oversatte felt overstyrer grunnfeltene, mens felt uten oversettelse faller tilbake til grunndokumentet.

Eksplisitt oversettelse med documents.translated()

Når du må hente en bestemt oversettelse uavhengig av gjeldende lokale:

Syntaks: documents.translated(schemaName, identifier, locale)

// Hent alltid den spanske oversettelsen
documents.translated("greeting", "welcome", "es").headline

// Hent oversettelse basert på en URL-parameter
documents.translated("product", meta.params.id, meta.params.lang).description

// Sammenlign oversettelser
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Eksempel på oversettelse

Hilsendokumentene dine med oversettelser:

// Grunndokument: greeting / welcome
{ "headline": "Velkommen", "subheadline": "Velkommen til plattformen vår" }

// Oversettelse (språk: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }

// Oversettelse (språk: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }

CEL-skript:

// Med meta.locale = "fr"
documents.get("greeting", "welcome").headline
// Returnerer: "Bienvenue"

// Eksplisitt spansk oversettelse
documents.translated("greeting", "welcome", "es").headline
// Returnerer: "Bienvenido"

// Reservemønster for manglende oversettelser
documents.translated("greeting", "welcome", meta.params.lang) != null
  ? documents.translated("greeting", "welcome", meta.params.lang).headline
  : documents.get("greeting", "welcome").headline

Praktiske eksempler

Eksempel 1: Tittel i en hero-blokk fra et annet dokument

Du har en hero-block som skal vise en overskrift hentet fra et article-dokument.

Artikkeldokumentet ditt (identifikator: "homepage-hero"):

{
  "headline": "Bygg raskere, lever smartere",
  "subheadline": "Det moderne CMS-et for utviklere"
}

CEL-skript i tittelfeltet til hero-blokken:

documents.get("article", "homepage-hero").headline

Resultat: Hero-blokken viser "Bygg raskere, lever smartere"


Eksempel 2: Lande navn fra kode

Du bygger en side på /countries/[code] og vil vise hele landenavnet.

Landedokumentene dine:

// country / us
{ "code": "us", "name": "USA", "flag": "US", "languages": ["en", "es"] }

// country / sa
{ "code": "sa", "name": "Saudi-Arabia", "flag": "SA", "languages": ["ar", "en"] }

CEL-skript:

documents.get("country", meta.params.code).name

Når noen besøker /countries/us:

  • meta.params.code = "us"
  • Resultat: "USA"

Når noen besøker /countries/sa:

  • meta.params.code = "sa"
  • Resultat: "Saudi-Arabia"

Eksempel 3: Betinget innhold basert på lokale

Vis ulike overskrifter basert på brukerens lokale.

meta.locale == "ar-SA" ? "Velkommen, alle sammen" : "Velkommen"

Hvis lokale er "ar-SA": Returnerer "Velkommen, alle sammen" Hvis lokale er noe annet: Returnerer "Velkommen"


Eksempel 4: Kjedede dokumentoppslag

article har et countryCode-felt, og du vil hente hele landenavnet.

Artikkeldokument:

{ "headline": "Nyheter fra USA", "countryCode": "us" }

CEL-skript:

documents.get("country", documents.get("article", "us-news").countryCode).name

Dette skjer:

  1. documents.get("article", "us-news") returnerer { "headline": "Nyheter fra USA", "countryCode": "us" }
  2. .countryCode henter ut "us"
  3. documents.get("country", "us") returnerer { "code": "us", "name": "USA", ... }
  4. .name henter ut "USA"

Resultat: "USA"


Eksempel 5: Reserveverdier

Hvis et dokument kanskje ikke finnes, kan du angi en reserveverdi:

documents.get("article", meta.params.slug) != null
  ? documents.get("article", meta.params.slug).headline
  : "Artikkelen ble ikke funnet"

Eller kontroller om et bestemt felt finnes:

documents.get("article", "intro").author != null
  ? documents.get("article", "intro").author
  : "Ukjent forfatter"

Eksempel 6: Arbeide med lister

Artikkelen din har tagger, og du vil kontrollere om en bestemt tagg finnes:

"featured" in documents.get("article", "welcome-post").tags

Returnerer: true hvis artikkelen har taggen "featured"

Hent den første taggen:

documents.get("article", "welcome-post").tags[0]

Returnerer: "announcement" (den første taggen)

Tell taggene:

size(documents.get("article", "welcome-post").tags)

Returnerer: 2 (antall tagger)


Parametriske ruter og meta.params

Parametriske ruter er nøkkelen til å bygge dynamiske, lokaliserte sider. Når du definerer et rutemønster som /{lang}/landingPage, trekker CMS-et ut parametere fra URL-en og gjør dem tilgjengelige via meta.params.

Slik fungerer ruteparametere

Definisjon av rutemønster: Ruter bruker syntaksen :paramName eller {paramName} for å definere dynamiske segmenter:

MønsterEksempel-URLUthentede parametere
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Parameterbindinger: Hver ruteparameter kan bindes til et dokumentskjema for validering:

{
  "pattern": "/{lang}/landingPage",
  "param_bindings": {
    "lang": "language"
  }
}

Denne bindingen forteller CMS-et:

  1. Trekk ut lang-segmentet fra URL-en
  2. Valider det mot language-skjemaet (ser etter et dokument der content.code samsvarer)
  3. Hvis verdien er gyldig, gjør hele dokumentet tilgjengelig i løste parametere

Eksempel: Språkbasert landingsside

Ruterkonfigurasjon:

  • Bane: /{lang}/landingPage
  • Mønster: /{lang}/landingPage
  • Parameterbindinger: { "lang": "language" }

Hilsendokumentene dine:

// greeting / ko
{ "code": "ko", "headline": "Velkommen", "subheadline": "Velkommen til plattformen vår", "ctaText": "Kom i gang", "ctaUrl": "/ko/get-started" }

// greeting / en
{ "code": "en", "headline": "Velkommen", "subheadline": "Velkommen til plattformen vår", "ctaText": "Kom i gang", "ctaUrl": "/en/get-started" }

// greeting / ja
{ "code": "ja", "headline": "Velkommen", "subheadline": "Velkommen til plattformen vår", "ctaText": "Start", "ctaUrl": "/ja/get-started" }

CEL-skript for å hente lokalisert innhold:

documents.get("greeting", meta.params.lang).headline

Slik løses det:

URLmeta.params.langResultat
/ko/landingPage"ko""Velkommen"
/en/landingPage"en""Velkommen"
/ja/landingPage"ja""Velkommen"
```

Avansert mønster: Ruter for land + språk

For ruter som /{country}/{lang}/products:

Ruterkonfigurasjon:

{
  "pattern": "/{country}/{lang}/products",
  "param_bindings": {
    "country": "country",
    "lang": "language"
  }
}

CEL-skript:

// Hent landenavn
documents.get("country", meta.params.country).name

// Hent lokalisert produktliste basert på land
documents.find("product", { "where": { "country": meta.params.country } })

// Kombinert: Vis en landspesifikk hilsen på brukerens språk
documents.get("greeting", meta.params.lang).headline + " fra " + documents.get("country", meta.params.country).name

Valideringskjede: CMS-et validerer parametere hierarkisk. For ruter av typen /{country}/{lang}:

  1. Validerer country-parameteren mot country-skjemaet
  2. Validerer lang-parameteren mot language-skjemaet
  3. Validerer eventuelt at lang finnes i country.languages[]-matrisen (hierarkisk validering)

meta.segments – tilgang til rå URL-bane

meta.segments gir den rå URL-banen som en matrise og er nyttig når du trenger posisjonsbasert tilgang uten navngitte parametere.

Slik fungerer det:

URL-banemeta.segments
/articles/tech/ai-news["articles", "tech", "ai-news"]
/ko/landingPage["ko", "landingPage"]
/us/en/products/featured["us", "en", "products", "featured"]
/[]

Når du bør bruke meta.segments kontra meta.params

BruksområdeBeste metode
Navngitte parametere fra rutemønsteretmeta.params.lang
Posisjonsbasert tilgangmeta.segments[0]
Hente banedybdesize(meta.segments)
Kontrollere om banen inneholder et segment"admin" in meta.segments

Eksempler med meta.segments

// Hent første segment (ofte en språkkode)
meta.segments[0]

// Kontroller banedybden
size(meta.segments) > 2 ? "dyp" : "grunn"

// Kontroller om vi er i administrasjonsdelen
"admin" in meta.segments ? "administratormodus" : "offentlig modus"

// Reserve: Bruk segmentet hvis parameteren ikke er bundet
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Komplett referanse for meta-objektet

meta-objektet inneholder all kontekst om den gjeldende forespørselen:

EgenskapTypeBeskrivelse
meta.localestringGjeldende lokalkode (for eksempel "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Ruteparametere hentet ut fra URL-mønsteret
meta.segmentsstring[]URL-bane delt opp i segmenter
meta.docId`string \null`UUID-en til det gjeldende dokumentet (null for nye dokumenter)
meta.titlestringTittelen på det gjeldende dokumentet

meta.locale

Lokalkoden følger BCP 47-formatet (språk-region):

// Kontroller lokale for høyre-til-venstre-språk
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Hent bare språkdelen
meta.locale.split("-")[0]  // Ikke støttet – bruk meta.params.lang i stedet

meta.params

Ruteparametere er alltid strenger. CMS-et validerer dem mot bundne skjemaer før evaluering:

// Få tilgang til navngitt parameter
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Kontroller om parameteren finnes
has(meta.params.category)  // true/false

// Bruk i dokumenthenting
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Rå URL-segmenter som en matrise:

// Få tilgang etter indeks (starter på 0)
meta.segments[0]           // Første segment
meta.segments[1]           // Andre segment

// Kontroller lengde
size(meta.segments)        // Antall segmenter

// Kontroller medlemskap
"products" in meta.segments  // Inneholder banen "products"?

meta.docId

UUID-en til det gjeldende dokumentet, nyttig for selvrefererende skript:

// Bare tilgjengelig ved redigering av eksisterende dokumenter
meta.docId != null ? "redigerer" : "oppretter nytt"

// Bruk i betinget logikk
meta.docId != null ? documents.get("article", meta.docId).status : "utkast"

meta.title

Tittelen på det gjeldende dokumentet:

// Bruk til visning
"Redigerer: " + meta.title

// Betingelse basert på tittel
meta.title.contains("Utkast") ? "under arbeid" : "publisert"

documents.ref() – kjedede oppslag

For renere syntaks når skjemaet er kjent, men identifikatoren er dynamisk:

// Tradisjonell metode
documents.get("airports", meta.params.code).name

// Med ref() – skjemaet er adskilt fra den dynamiske identifikatoren
documents.ref("airports").get(meta.params.code).name

Begge metodene er likeverdige, men ref() gjør den dynamiske delen tydeligere.


Hurtigreferanse

Dokumenthenting

documents.get("schema", "identifier")       // Hent ett dokument
documents.get("schema", "id").fieldName     // Hent et bestemt felt
documents.find("schema")                    // Hent alle dokumenter
documents.find("schema", { "where": {...}}) // Filtrert spørring
documents.ref("schema").get(identifier)     // Kjedet oppslag
documents.translated("schema", "id", "fr")  // Hent med eksplisitt lokale

Kontekstvariabler

meta.locale          // "en-US", "ar-SA" osv.
meta.params.xyz      // URL-parameter med navnet "xyz"
meta.segments        // URL-bane som matrise: ["articles", "intro"]
meta.segments[0]     // Første banesegment
meta.docId           // Gjeldende dokument-ID (eller null)
meta.title           // Tittelen på gjeldende dokument
doc.fieldName        // Feltverdi i gjeldende dokument (i redigeringskontekst)

Operatorer

// Sammenligning
==  !=  <  <=  >  >=

// Logikk
&&  ||  !

// Ternær (hvis–ellers)
condition ? valueIfTrue : valueIfFalse

// Medlemskap
"value" in listOrMap

Vanlige funksjoner

size(list)                    // Tell elementer
size(string)                  // Strenglengde
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Kontroller om egenskapen finnes
hasProperty(obj, "key")       // Kontroller om objektet har nøkkelen (alternativ syntaks)

Feilmeldinger

Hvis noe går galt, vil du se en av disse:

FeilHva det betyr
SYNTAX_ERRORSkrivefeil i skriptet (manglende anførselstegn, ugyldig operator)
TYPE_ERRORDu blander typer som ikke kan brukes sammen
RUNTIME_ERRORSkriptet kjørte, men støtte på et problem (udefinert variabel)
FETCH_LIMIT_EXCEEDEDDu henter for mange dokumenter (maks. 50)
TIMEOUTSkriptet brukte for lang tid (maks. 5 sekunder)
AST_DEPTH_EXCEEDEDUttrykket er for dypt nøstet (maks. dybde: 50)
SCRIPT_TOO_LONGSkriptet overskrider grensen på 5000 tegn

Utvidbarhet og fremtidige funksjoner

CEL-motoren er laget for å kunne utvides. Planlagte fremtidige funksjoner omfatter:

Planlagt: MCP-serverintegrasjon

// Fremtidig: Kall eksterne tjenester via MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

Planlagt: KI-funksjoner

// Fremtidig: KI-drevet innholdsgenerering
ai.summarize(documents.get("article", meta.params.id).body, 100)
ai.translate(meta.params.text, meta.params.targetLang)
ai.classify(meta.params.input, ["positive", "negative", "neutral"])

Disse funksjonene vil bli lagt til gjennom systemet for registrerte funksjoner, samtidig som bakoverkompatibilitet med eksisterende skript opprettholdes.


Tips

  1. Bruk autofullføring – Skriv documents. eller meta., så viser redigereren tilgjengelige alternativer
  2. Begynn enkelt – Test først med documents.get("schema", "id"), og legg deretter til .fieldName
  3. Kontroller null – Hvis et dokument kanskje ikke finnes, legg til en reserveverdi med != null ? ... : ...
  4. Ikke hent for mye – Hvert kall til documents.get() eller documents.find() teller mot grensen på 50 hentinger
  5. Foretrekk meta.params fremfor meta.segments – Navngitte parametere er validerte og mer pålitelige
  6. Bruk has() for valgfrie parametere – Kontroller has(meta.params.category) før du får tilgang
  7. Bruk documents.ref() for dynamiske identifikatorer – Tydeligere syntaks når skjemaet er statisk, men identifikatoren er dynamisk
  8. Bruk doc.fieldName for selvreferanser – Få tilgang til felt i det gjeldende dokumentet i beregnede uttrykk

Referanser mellom dokumenter

Denne delen dekker avanserte mønstre for å koble dokumenter sammen og bygge relasjonelle innholdsstrukturer.

Grunnleggende referansemønster

Den enkleste formen: Ett dokument refererer til et annet ved hjelp av en identifikator.

// Artikkelen lagrer forfatter-ID-en; hent forfatterens navn
documents.get("author", documents.get("article", "intro").authorId).name

Kjedede oppslag med documents.ref()

For renere syntaks når identifikatoren er dynamisk:

// Tradisjonell metode
documents.get("country", documents.get("airport", meta.params.code).countryCode).name

// Med ref() – tydeligere når skjemaet er kjent, men identifikatoren er dynamisk
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name

Referansekjeder på flere nivåer

Bygg dype relasjoner ved å kjede flere oppslag:

// Flyplass → Land → Region → Kontinent
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Referanse med oversettelse

Kombiner dokumentreferanser med oversettelser:

// Hent lokalisert landenavn for en flyplass
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Referansemønstre etter bruksområde

Mønster 1: Oppslag av fremmednøkkel

Dokumentet lagrer en ID som refererer til et annet dokument.

// article / tech-news
{ "title": "Teknologioppdatering", "authorId": "author-123", "categoryId": "cat-tech" }
// Finn forfatternavn
documents.get("author", documents.get("article", meta.params.slug).authorId).name

// Finn kategori med reserveverdi
documents.get("article", meta.params.slug).categoryId != null
  ? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
  : "Uten kategori"

Mønster 2: Kodebaserte referanser

Dokumenter refererer til hverandre med semantiske koder i stedet for UUID-er.

// airport / JFK
{ "code": "JFK", "name": "John F. Kennedy International", "countryCode": "us" }

// country / us
{ "code": "us", "name": "USA", "currencyCode": "usd" }

// currency / usd
{ "code": "usd", "symbol": "$", "name": "Amerikansk dollar" }
// Kjeden flyplass → land → valuta
documents.get("currency",
  documents.get("country",
    documents.get("airport", meta.params.code).countryCode
  ).currencyCode
).symbol
// For JFK: Returnerer "$"

Mønster 3: Selvreferanse med doc-kontekst

Bruk doc for beregnede felt som refererer til andre dokumenter basert på verdiene i det gjeldende dokumentet.

// Hent detaljer om relatert kategori i et produktdokument
documents.get("category", doc.categoryId).description

// Beregn fraktkostnad basert på produktets opprinnelsesland
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Mønster 4: Toveisreferanser

Når dokumenter refererer til hverandre, må du være oppmerksom på hentegrensene.

// Hent artikkelens forfatter, og hent deretter forfatterens andre artikler (pass på antall hentinger!)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })

Mønster 5: Polymorfe referanser

Når et felt kan referere til ulike skjemaer:

// content-block / hero-1
{ "type": "hero", "sourceType": "article", "sourceId": "welcome-post" }

// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Dynamisk skjemautslag basert på sourceType
documents.get("content-block", "hero-1").sourceType == "article"
  ? documents.get("article", documents.get("content-block", "hero-1").sourceId).headline
  : documents.get("product", documents.get("content-block", "hero-1").sourceId).name

Avhengighetssporing

Alle kall til documents.get(), documents.find() og documents.ref().get() spores for ugyldiggjøring av hurtigbuffer. Når et referert dokument endres, vet CMS-et hvilke CEL-uttrykk som må evalueres på nytt.

Sporte avhengigheter omfatter:

  • get: schema:identifier – Avhengighet til et bestemt dokument
  • ref: schema:identifier – Samme som get, via kjedet syntaks
  • query: schema:* – Avhengighet på skjemanivå (ethvert dokument i skjemaet)

Beste praksis for referanser

  1. Minimer kjededybden – Hvert nivå øker forsinkelsen og antallet hentinger
  2. Bufre mellomresultater – Hvis du trenger den samme nøstede verdien to ganger, hent overordnet objekt én gang
  3. Bruk null-kontroller – Referanser kan slutte å fungere hvis dokumenter slettes
  4. Foretrekk koder fremfor UUID-er – Koder er lesbare i uttrykk og stabile på tvers av miljøer
  5. Følg med på hentegrensene – Komplekse referansekjeder kan raskt nå grensen på 50 hentinger

Tillegg A: Komplett eksempel på parametrisk rute

Denne gjennomgangen oppretter en flerspråklig landingsside tilgjengelig på /{lang}/landingPage.

Trinn 1: Opprett skjemaet for hilsendokumentet

Opprett et egendefinert skjema kalt greeting i CMS-administrasjonen:

{
  "name": "greeting",
  "fields": [
    { "name": "code", "type": "string", "required": true },
    { "name": "headline", "type": "string", "required": true },
    { "name": "subheadline", "type": "string" },
    { "name": "ctaText", "type": "string" },
    { "name": "ctaUrl", "type": "string" }
  ]
}

Trinn 2: Opprett hilsendokumenter

Opprett dokumenter for hvert språk:

Dokument: greeting/ko

{
  "code": "ko",
  "headline": "Velkommen",
  "subheadline": "Velkommen til plattformen vår",
  "ctaText": "Kom i gang",
  "ctaUrl": "/ko/get-started"
}

Dokument: greeting/en

{
  "code": "en",
  "headline": "Velkommen",
  "subheadline": "Velkommen til plattformen vår",
  "ctaText": "Kom i gang",
  "ctaUrl": "/en/get-started"
}

Dokument: greeting/ja

{
  "code": "ja",
  "headline": "Velkommen",
  "subheadline": "Velkommen til plattformen vår",
  "ctaText": "Start",
  "ctaUrl": "/ja/get-started"
}

Trinn 3: Opprett siden

Opprett en side med følgende konfigurasjon:

  • Bane/mønster: /{lang}/landingPage
  • Tilstand: Publisert
  • Tilordninger for dynamiske segmenter: tilordne lang → language-komponenten
  {
    "lang": "language"
  }

Trinn 4: Legg til blokker med CEL-skript

Legg til en hero-blokk i ruten med følgende CEL-skript for hvert felt:

Overskriftsfelt:

documents.get("greeting", meta.params.lang).headline

Underoverskriftsfelt:

documents.get("greeting", meta.params.lang).subheadline

CTA-tekstfelt:

documents.get("greeting", meta.params.lang).ctaText

CTA-URL-felt:

documents.get("greeting", meta.params.lang).ctaUrl

Trinn 5: Bruk i Next.js

Legg til en «catch-all»-rute. ParametricRoutePage løser siden, henter ut meta.params fra URL-en, evaluerer CEL-bindingene på serversiden og gjengir hver blokk gjennom registeret ditt – du trenger ikke å bygge meta-konteksten eller kalle klienten på lavt nivå selv.

// app/[...slug]/page.tsx
import ParametricRoutePage from 'cms-renderer/lib/renderer';
import { registry } from '@/lib/registry';
import { cmsConfig } from '@/lib/cms-config';

export const dynamic = 'force-static';

interface PageProps {
  params: Promise<{ slug: string[] }>;
}

export default async function Page({ params }: PageProps) {
  const { slug } = await params;

  return (
    <ParametricRoutePage
      registry={registry}
      apiKey={cmsConfig.apiKey}
      websiteId={cmsConfig.websiteId}
      cmsUrl={cmsConfig.cmsUrl}
      params={Promise.resolve({ slug })}
    />
  );
}

Trinn 6: Test rutene

Besøk disse URL-ene for å se lokalisert innhold:

URLForventet overskrift
/ko/landingPageVelkommen
/en/landingPageVelkommen
/ja/landingPageVelkommen

Slik fungerer oppløsningen

Når en bruker besøker /ko/landingPage:

  1. Rutesamsvar: CMS-et finner mønsteret /{lang}/landingPage
  2. Parameteruttak: meta.params.lang = "ko"
  3. Validering: CMS-et validerer at "ko" finnes i language-skjemaet
  4. CEL-evaluering: Skript som documents.get("greeting", meta.params.lang) løses til koreansk innhold
  5. Svar: Lokaliserte blokker returneres til klienten

Tillegg B: Teknisk referanse

CelMeta-grensesnitt (TypeScript)

interface CelMeta {
  /** Gjeldende lokalkode (for eksempel 'en-US') */
  locale: string;
  /** Ruteparametere hentet ut fra URL-en */
  params: Record<string, string>;
  /** URL-banens segmenter */
  segments: string[];
  /** Gjeldende dokument-ID (hvis et eksisterende dokument redigeres) */
  docId: string | null;
  /** Tittelen på det gjeldende dokumentet */
  title: string;
}

Algoritme for parameteruttak

Funksjonen extractParams behandler URL-baner:

Mønster: /{country}/{lang}/products
Bane:    /us/en/products

Algoritme:
1. Normaliser begge (fjern avsluttende skråstreker)
2. Del opp i segmenter: ["us", "en", "products"] og ["{country}", "{lang}", "products"]
3. Sammenlign antall segmenter (må være likt)
4. For hvert segmentpar:
   - Hvis mønsteret starter med : eller {}, trekk ut som parameter
   - Ellers må de samsvare nøyaktig
5. Returner: { country: "us", lang: "en" }

Støttede formater for parameterbinding

// Enkel binding (bruker "code"-feltet til oppslag)
{ "lang": "language" }

// Detaljert binding (egendefinert slug-felt)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Prioritet for dokumentoppslag

Ved henting via documents.get(schema, identifier):

  1. UUID-samsvar: Hvis identifikatoren er en gyldig UUID, hentes dokumentet etter id
  2. Code-felt: Kontroller content.code
  3. Slug-felt: Kontroller content.slug
  4. Tittelsamsvar: Kontroller title-feltet

Dette gjør det mulig å referere fleksibelt til dokumenter med en hvilken som helst unik identifikator.

Continue Reading
Previous‹Install Profound CMS as a proxyNextProject Scaffolding›