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 proxyCEL Scripting in Template BuilderProject 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}postPOST /translationpatchPATCH /translationsgetGET /usagepostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

CEL Scripting in Template Builder

En praktisk guide till att skriva CEL-uttryck i CMS:et.

En praktisk guide till att skriva CEL-uttryck i CMS:et.


SĂ„ fungerar CEL

CEL (Common Expression Language) Àr ett lÀttviktigt skriptsprÄk som Àr inbyggt i vÄrt CMS. Det lÄter dig skriva dynamiska uttryck som kan hÀmta data frÄn dokument, lÀsa URL-parametrar och berÀkna vÀrden direkt.

Det hÀr hÀnder nÀr ett CEL-skript körs:

Ditt skript                    Motorn                         Resultat
    |                              |                              |
    v                              v                              v
documents.get("article", "intro") --> HÀmtar frÄn databasen --> { headline: "Welcome", body: "..." }
         .headline                --> HÀmtar fÀltet        --> "Welcome"

TĂ€nk pĂ„ CEL som ett skrivskyddat frĂ„gesprĂ„k. Det kan inte Ă€ndra nĂ„got i databasen – det lĂ€ser bara data och returnerar ett berĂ€knat resultat. DĂ€rför Ă€r det sĂ€kert att anvĂ€nda var som helst i CMS:et.


Byggstenarna

Varje CEL-uttryck har tillgÄng till tre saker:

ObjektVad det ÀrExempel
documentsHÀmtar valfritt dokument frÄn CMS:etdocuments.get("country", "us")
metaInformation om den aktuella begÀran (lokal, URL-parametrar)meta.locale, meta.params.slug
schemaFÀltdefinitionerna för det aktuella dokumentetschema.fields

SjÀlvreferenser med doc

NÀr du skriver CEL-uttryck i en dokumentredigerare kan du komma Ät det aktuella dokumentets fÀltvÀrden med objektet doc. Detta möjliggör berÀknade fÀlt och referenser mellan fÀlt.

// Åtkomst till det aktuella dokumentets prisfĂ€lt
doc.price

// BerÀkna totalen frÄn det aktuella dokumentets fÀlt
doc.price * doc.quantity

// Villkor baserat pÄ det aktuella dokumentets status
doc.status == "published" ? doc.title : "Draft: " + doc.title

Objektet doc innehÄller alla fÀltvÀrden frÄn dokumentet som redigeras. Det Àr anvÀndbart för:

  • BerĂ€knade fĂ€lt (t.ex. doc.price * doc.quantity)
  • Villkorlig visningslogik baserad pĂ„ dokumentets tillstĂ„nd
  • Uttryck av valideringstyp

HĂ€mta dokument

CEL:s kraftfullaste funktion Àr att hÀmta dokument frÄn var som helst i CMS:et.

HĂ€mta ett enskilt dokument

Syntax: documents.get(schemaName, identifier)

Anta att du har ett article-dokument lagrat med identifieraren "welcome-post":

// Lagrad i CMS:et som: article / welcome-post
{
  "headline": "Welcome to Our Platform",
  "author": "Sarah Chen",
  "body": "We're excited to announce...",
  "tags": ["announcement", "news"]
}

SÄ hÀmtar du hela dokumentet:

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

Returnerar:

{
  "headline": "Welcome to Our Platform",
  "author": "Sarah Chen",
  "body": "We're excited to announce...",
  "tags": ["announcement", "news"]
}

SÄ hÀmtar du endast rubriken:

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

Returnerar: "Welcome to Our Platform"

SÄ hÀmtar du författaren:

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

Returnerar: "Sarah Chen"


AnvÀnda URL-parametrar

NÀr sidan har dynamiska rutter (till exempel /articles/[slug]) kan du anvÀnda meta.params för att hÀmta URL-parametern och dÀrefter rÀtt dokument.

Om nÄgon besöker /articles/welcome-post:

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

Returnerar: "Welcome to Our Platform"

SĂ„ bygger du dynamiska sidor – samma CEL-skript fungerar för alla artiklar och anvĂ€nder bara den slug som finns i URL:en.


HĂ€mta flera dokument

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

// HÀmta alla lÀnder
documents.find("country")

Returnerar:

[
  { "code": "us", "name": "United States", "flag": "US" },
  { "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
  { "code": "gb", "name": "United Kingdom", "flag": "GB" }
]
// HÀmta lÀnder med ett filter
documents.find("country", { "where": { "code": "us" } })

Returnerar:

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

ÖversĂ€ttningar

CEL stöder hÀmtning av översatt dokumentinnehÄll pÄ tvÄ sÀtt: automatisk lokalbaserad översÀttning och explicit översÀttningsuppslagning.

Automatisk översÀttning via meta.locale

NÀr meta.locale Àr instÀlld (till exempel frÄn ruttparametrar eller anvÀndarinstÀllningar) sammanfogar documents.get() automatiskt översatt innehÄll:

// Om meta.locale Àr "fr" returneras den franska översÀttningen, sammanfogad med grunddokumentet
documents.get("greeting", "welcome").headline

SĂ„ fungerar det:

  1. HÀmtar grunddokumentets innehÄll
  2. Om meta.locale inte Àr "en" eller "en-US" letar den efter en översÀttning i tabellen translations
  3. Sammanfogar översatta fÀlt ovanpÄ grundinnehÄllet: { ...baseContent, ...translatedContent }

Det innebÀr att översatta fÀlt ersÀtter grundfÀlten, medan oöversatta fÀlt hÀmtas frÄn grunddokumentet.

Explicit översÀttning med documents.translated()

NÀr du behöver hÀmta en specifik översÀttning oavsett aktuell lokal:

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

// HÀmta alltid den spanska översÀttningen
documents.translated("greeting", "welcome", "es").headline

// HÀmta översÀttning baserat pÄ en URL-parameter
documents.translated("product", meta.params.id, meta.params.lang).description

// JÀmför översÀttningar
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Exempel pÄ översÀttning

Dina greeting-dokument med översÀttningar:

// Grunddokument: greeting / welcome
{ "headline": "Welcome", "subheadline": "Welcome to our platform" }

// ÖversĂ€ttning (sprĂ„k: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }

// ÖversĂ€ttning (sprĂ„k: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }

CEL-skript:

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

// Explicit spansk översÀttning
documents.translated("greeting", "welcome", "es").headline
// Returnerar: "Bienvenido"

// Reservmönster för saknade översÀttningar
documents.translated("greeting", "welcome", meta.params.lang) != null
  ? documents.translated("greeting", "welcome", meta.params.lang).headline
  : documents.get("greeting", "welcome").headline

Exempel frÄn verkligheten

Exempel 1: Hero-blockets titel frÄn ett annat dokument

Du har ett hero-block som ska visa en rubrik hÀmtad frÄn ett article-dokument.

Ditt artikeldokument (identifierare: "homepage-hero"):

{
  "headline": "Build Faster, Ship Smarter",
  "subheadline": "The modern CMS for developers"
}

CEL-skript i hero-blockets titelfÀlt:

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

Resultat: Hero-blocket visar "Build Faster, Ship Smarter"


Exempel 2: Landets namn frÄn en kod

Du bygger en sida pÄ /countries/[code] och vill visa landets fullstÀndiga namn.

Dina landdokument:

// country / us
{ "code": "us", "name": "United States", "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 nÄgon besöker /countries/us:

  • meta.params.code = "us"
  • Resultat: "United States"

NÀr nÄgon besöker /countries/sa:

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

Exempel 3: Villkorligt innehÄll baserat pÄ lokal

Visa olika rubriker baserat pÄ anvÀndarens lokal.

meta.locale == "ar-SA" ? "Welcome, everyone" : "Welcome"

Om lokalen Àr "ar-SA": Returnerar "Welcome, everyone" Om lokalen Àr nÄgot annat: Returnerar "Welcome"


Exempel 4: Kedjade dokumentsökningar

Ditt article har ett fÀlt countryCode, och du vill hÀmta landets fullstÀndiga namn.

Artikeldokument:

{ "headline": "News from the US", "countryCode": "us" }

CEL-skript:

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

Det hÀr hÀnder:

  1. documents.get("article", "us-news") returnerar { "headline": "News from the US", "countryCode": "us" }
  2. .countryCode hÀmtar "us"
  3. documents.get("country", "us") returnerar { "code": "us", "name": "United States", ... }
  4. .name hÀmtar "United States"

Resultat: "United States"


Exempel 5: ReservvÀrden

Om ett dokument kanske inte finns kan du ange ett reservvÀrde:

documents.get("article", meta.params.slug) != null
  ? documents.get("article", meta.params.slug).headline
  : "Article Not Found"

Eller kontrollera om ett specifikt fÀlt finns:

documents.get("article", "intro").author != null
  ? documents.get("article", "intro").author
  : "Unknown Author"

Exempel 6: Arbeta med listor

Din artikel har taggar och du vill kontrollera om en specifik tagg finns:

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

Returnerar: true om artikeln har taggen "featured"

HÀmta den första taggen:

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

Returnerar: "announcement" (den första taggen)

RĂ€kna taggarna:

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

Returnerar: 2 (antalet taggar)


Parametriska rutter och meta.params

Parametriska rutter Àr nyckeln till att bygga dynamiska, lokaliserade sidor. NÀr du definierar ett ruttmönster som /{lang}/landingPage extraherar CMS:et parametrar frÄn URL:en och gör dem tillgÀngliga via meta.params.

SĂ„ fungerar ruttparametrar

Definition av ruttmönster: Rutter anvÀnder syntaxen :paramName eller {paramName} för att definiera dynamiska segment:

MönsterExempel-URLExtraherade parametrar
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Parameterbindningar: Varje ruttparameter kan bindas till ett dokumentschema för validering:

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

Den hÀr bindningen talar om för CMS:et att:

  1. Extrahera segmentet lang frÄn URL:en
  2. Validera det mot schemat language (leta efter ett dokument dÀr content.code matchar)
  3. Om det Àr giltigt göra hela dokumentet tillgÀngligt i de upplösta parametrarna

Exempel: SprÄkbaserad landningssida

Ruté…çœź:

  • SökvĂ€g: /{lang}/landingPage
  • Mönster: /{lang}/landingPage
  • Parameterbindningar: { "lang": "language" }

Dina greeting-dokument:

// greeting / ko
{ "code": "ko", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Get Started", "ctaUrl": "/ko/get-started" }

// greeting / en
{ "code": "en", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Get Started", "ctaUrl": "/en/get-started" }

// greeting / ja
{ "code": "ja", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Start", "ctaUrl": "/ja/get-started" }

CEL-skript för att hÀmta lokaliserat innehÄll:

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

SÄ löses det:

URLmeta.params.langResultat
/ko/landingPage"ko""Welcome"
/en/landingPage"en""Welcome"
/ja/landingPage"ja""Welcome"

Avancerat mönster: Rutter med land och sprÄk

För rutter som /{country}/{lang}/products:

Rutkonfiguration:

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

CEL-skript:

// HĂ€mta landets namn
documents.get("country", meta.params.country).name

// HÀmta en lokaliserad produktlista baserad pÄ land
documents.find("product", { "where": { "country": meta.params.country } })

// Kombinerat: Visa en landsspecifik hÀlsning pÄ anvÀndarens sprÄk
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name

Valideringskedja: CMS:et validerar parametrar hierarkiskt. För rutter av typen /{country}/{lang}:

  1. Validerar parametern country mot schemat country
  2. Validerar parametern lang mot schemat language
  3. Validerar eventuellt att lang finns i arrayen country.languages[] (hierarkisk validering)

meta.segments – Ă„tkomst till rĂ„ URL-sökvĂ€g

meta.segments tillhandahÄller den rÄa URL-sökvÀgen som en array och Àr anvÀndbar nÀr du behöver positionsbaserad Ätkomst utan namngivna parametrar.

SĂ„ fungerar det:

URL-sökvÀgmeta.segments
/articles/tech/ai-news["articles", "tech", "ai-news"]
/ko/landingPage["ko", "landingPage"]
/us/en/products/featured["us", "en", "products", "featured"]
/[]

NÀr ska meta.segments respektive meta.params anvÀndas?

AnvÀndningsfallBÀsta metod
Namngivna parametrar frÄn ruttmönstretmeta.params.lang
Positionsbaserad Ätkomstmeta.segments[0]
HÀmta sökvÀgens djupsize(meta.segments)
Kontrollera om sökvÀgen innehÄller ett segment"admin" in meta.segments

Exempel med meta.segments

// HÀmta första segmentet (ofta en sprÄkkod)
meta.segments[0]

// Kontrollera sökvÀgens djup
size(meta.segments) > 2 ? "deep" : "shallow"

// Kontrollera om vi befinner oss i administratörsdelen
"admin" in meta.segments ? "admin mode" : "public mode"

// Reservlösning: AnvÀnd segmentet om parametern inte Àr bunden
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

FullstÀndig referens för objektet meta

Objektet meta innehÄller all kontext för den aktuella begÀran:

EgenskapTypBeskrivning
meta.localestringAktuell lokalkod (t.ex. "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Ruttparametrar extraherade frÄn URL-mönstret
meta.segmentsstring[]URL-sökvÀgen uppdelad i segment
meta.docId`string \null`Det aktuella dokumentets UUID (null för nya dokument)
meta.titlestringDet aktuella dokumentets titel

meta.locale

Lokalkoden följer formatet BCP 47 (sprÄk-region):

// Kontrollera lokal för höger-till-vÀnster-sprÄk
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// HÀmta endast sprÄkdel
meta.locale.split("-")[0]  // Stöds inte – anvĂ€nd meta.params.lang i stĂ€llet

meta.params

Ruttparametrar Àr alltid strÀngar. CMS:et validerar dem mot bundna scheman före utvÀrderingen:

// Åtkomst till namngiven parameter
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Kontrollera om parametern finns
has(meta.params.category)  // true/false

// AnvÀnd i dokumenthÀmtning
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

RÄa URL-segment som en array:

// Åtkomst via index (börjar pĂ„ 0)
meta.segments[0]           // Första segmentet
meta.segments[1]           // Andra segmentet

// Kontrollera lÀngden
size(meta.segments)        // Antal segment

// Kontrollera medlemskap
"products" in meta.segments  // InnehÄller sökvÀgen "products"?

meta.docId

Det aktuella dokumentets UUID, anvÀndbart för sjÀlvrefererande skript:

// TillgÀngligt endast vid redigering av befintliga dokument
meta.docId != null ? "editing" : "creating new"

// AnvÀnd i villkorslogik
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Det aktuella dokumentets titel:

// AnvÀnd för visning
"Editing: " + meta.title

// Villkor baserat pÄ titel
meta.title.contains("Draft") ? "work in progress" : "published"

documents.ref() – kedjade uppslagningar

För renare syntax nÀr schemat Àr kÀnt men identifieraren Àr dynamisk:

// Traditionellt tillvÀgagÄngssÀtt
documents.get("airports", meta.params.code).name

// Med ref() – separerar schemat frĂ„n den dynamiska identifieraren
documents.ref("airports").get(meta.params.code).name

BÄda Àr likvÀrdiga, men ref() gör den dynamiska delen tydligare.


Snabbreferens

DokumenthÀmtning

documents.get("schema", "identifier")       // HĂ€mta ett dokument
documents.get("schema", "id").fieldName     // HÀmta ett specifikt fÀlt
documents.find("schema")                    // HĂ€mta alla dokument
documents.find("schema", { "where": {...}}) // Filtrerad frÄga
documents.ref("schema").get(identifier)     // Kedjad uppslagning
documents.translated("schema", "id", "fr")  // HĂ€mta med explicit lokal

Kontextvariabler

meta.locale          // "en-US", "ar-SA" osv.
meta.params.xyz      // URL-parameter med namnet "xyz"
meta.segments        // URL-sökvÀg som array: ["articles", "intro"]
meta.segments[0]     // Första sökvÀgssegmentet
meta.docId           // Aktuellt dokument-ID (eller null)
meta.title           // Aktuellt dokumentets titel
doc.fieldName        // Aktuellt dokuments fÀltvÀrde (i redigerarkontext)

Operatorer

// JÀmförelse
==  !=  <  <=  >  >=

// Logik
&&  ||  !

// TernĂ€r (om–annars)
villkor ? vÀrdeOmSant : vÀrdeOmFalskt

// Medlemskap
"value" in listOrMap

Vanliga funktioner

size(list)                    // RĂ€kna objekt
size(string)                  // StrÀnglÀngd
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Kontrollera om egenskapen finns
hasProperty(obj, "key")       // Kontrollera om objektet har nyckeln (alternativ syntax)

Felmeddelanden

Om nÄgot gÄr fel visas ett av dessa meddelanden:

FelVad det betyder
SYNTAX_ERRORSkrivfel i skriptet (saknat citationstecken, felaktig operator)
TYPE_ERRORDu blandar typer som inte fungerar tillsammans
RUNTIME_ERRORSkriptet kördes men stötte pÄ ett problem (odefinierad variabel)
FETCH_LIMIT_EXCEEDEDDu hÀmtar för mÄnga dokument (max 50)
TIMEOUTSkriptet tog för lÄng tid (max 5 sekunder)
AST_DEPTH_EXCEEDEDUttrycket Àr för djupt nÀstlat (maxdjup: 50)
SCRIPT_TOO_LONGSkriptet överskrider grÀnsen pÄ 5 000 tecken

Utbyggbarhet och framtida funktioner

CEL-motorn Àr utformad för att kunna byggas ut. Planerade framtida funktioner omfattar:

Planerat: MCP-serverintegration

// Framtid: Anropa externa tjÀnster via MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

Planerat: AI-funktioner

// Framtid: AI-driven innehÄllsgenerering
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"])

Dessa funktioner kommer att lÀggas till via systemet för registrerade funktioner, med bibehÄllen bakÄtkompatibilitet med befintliga skript.


Tips

  1. AnvĂ€nd autokomplettering – Skriv documents. eller meta. sĂ„ visar redigeraren tillgĂ€ngliga alternativ
  2. Börja enkelt – Testa först med documents.get("schema", "id") och lĂ€gg sedan till .fieldName
  3. Kontrollera null – Om ett dokument kanske inte finns, lĂ€gg till ett reservvĂ€rde med != null ? ... : ...
  4. HĂ€mta inte för mycket – Varje documents.get() eller documents.find() rĂ€knas mot grĂ€nsen pĂ„ 50 hĂ€mtningar
  5. Föredra meta.params framför meta.segments – Namngivna parametrar valideras och Ă€r mer tillförlitliga
  6. AnvĂ€nd has() för valfria parametrar – Kontrollera has(meta.params.category) innan Ă„tkomst
  7. AnvĂ€nd documents.ref() för dynamiska identifierare – Tydligare syntax nĂ€r schemat Ă€r statiskt men identifieraren dynamisk
  8. AnvĂ€nd doc.fieldName för sjĂ€lvreferenser – Åtkomst till det aktuella dokumentets fĂ€lt i berĂ€knade uttryck

Referenser mellan dokument

Det hÀr avsnittet behandlar avancerade mönster för att lÀnka samman dokument och bygga relationella innehÄllsstrukturer.

GrundlÀggande referensmönster

Den enklaste formen: ett dokument refererar till ett annat med hjÀlp av en identifierare.

// Artikeln lagrar författarens ID; hÀmta författarens namn
documents.get("author", documents.get("article", "intro").authorId).name

Kedjade uppslagningar med documents.ref()

För renare syntax nÀr identifieraren Àr dynamisk:

// Traditionellt tillvÀgagÄngssÀtt
documents.get("country", documents.get("airport", meta.params.code).countryCode).name

// Med ref() – tydligare nĂ€r schemat Ă€r kĂ€nt men identifieraren Ă€r dynamisk
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name

Referenskedjor pÄ flera nivÄer

Bygg djupa relationer genom att kedja flera uppslagningar:

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

Referens med översÀttning

Kombinera dokumentreferenser med översÀttningar:

// HÀmta lokaliserat landnamn för en flygplats
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Referensmönster efter anvÀndningsfall

Mönster 1: Uppslagning av frÀmmande nyckel

Dokumentet lagrar ett ID som refererar till ett annat dokument.

// article / tech-news
{ "title": "Tech Update", "authorId": "author-123", "categoryId": "cat-tech" }
// Lös upp författarens namn
documents.get("author", documents.get("article", meta.params.slug).authorId).name

// Lös upp kategori med reservvÀrde
documents.get("article", meta.params.slug).categoryId != null
  ? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
  : "Uncategorized"

Mönster 2: Kodbaserade referenser

Dokument refererar till varandra med semantiska koder i stÀllet för UUID:er.

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

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

// currency / usd
{ "code": "usd", "symbol": "$", "name": "US Dollar" }
// Kedja: Flygplats → Land → Valuta
documents.get("currency",
  documents.get("country",
    documents.get("airport", meta.params.code).countryCode
  ).currencyCode
).symbol
// För JFK: Returnerar "$"

Mönster 3: SjÀlvreferens med doc-kontext

AnvÀnd doc för berÀknade fÀlt som refererar till andra dokument baserat pÄ det aktuella dokumentets vÀrden.

// HĂ€mta relaterad kategorinformation i ett produktdokument
documents.get("category", doc.categoryId).description

// BerÀknad fraktkostnad baserad pÄ produktens ursprungsland
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Mönster 4: Dubbelriktade referenser

NÀr dokument refererar till varandra bör du vara uppmÀrksam pÄ hÀmtbegrÀnsningarna.

// HÀmta artikelns författare och sedan författarens övriga artiklar (hÄll koll pÄ antalet hÀmtningar!)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })

Mönster 5: Polymorfa referenser

NÀr ett fÀlt kan referera till olika scheman:

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

// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Dynamisk schemauppslagning baserad 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

BeroendespÄrning

Varje anrop till documents.get(), documents.find() och documents.ref().get() spÄras för cacheinvalidering. NÀr ett refererat dokument Àndras vet CMS:et vilka CEL-uttryck som behöver utvÀrderas igen.

SpÄrade beroenden omfattar:

  • get: schema:identifier – Beroende av ett specifikt dokument
  • ref: schema:identifier – Samma som get, via kedjad syntax
  • query: schema:* – Beroende pĂ„ schemanivĂ„ (alla dokument i schemat)

BÀsta praxis för referenser

  1. Minimera kedjedjupet – Varje nivĂ„ ökar fördröjningen och antalet hĂ€mtningar
  2. Cacha mellanresultat – Om du behöver samma nĂ€stlade vĂ€rde tvĂ„ gĂ„nger, hĂ€mta förĂ€ldern en gĂ„ng
  3. AnvĂ€nd null-kontroller – Referenser kan sluta fungera om dokument tas bort
  4. Föredra koder framför UUID:er – Koder Ă€r lĂ€ttlĂ€sta i uttryck och stabila mellan miljöer
  5. HĂ„ll koll pĂ„ hĂ€mtbegrĂ€nsningarna – Komplexa referenskedjor kan snabbt nĂ„ grĂ€nsen pĂ„ 50 hĂ€mtningar

Bilaga A: FullstÀndigt exempel pÄ parametrisk rutt

Den hÀr genomgÄngen skapar en flersprÄkig landningssida som nÄs via /{lang}/landingPage.

Steg 1: Skapa schemat för greeting-dokumentet

Skapa ett anpassat schema med namnet greeting i CMS-administrationen:

{
  "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" }
  ]
}

Steg 2: Skapa greeting-dokument

Skapa dokument för varje sprÄk:

Dokument: greeting/ko

{
  "code": "ko",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Get Started",
  "ctaUrl": "/ko/get-started"
}

Dokument: greeting/en

{
  "code": "en",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Get Started",
  "ctaUrl": "/en/get-started"
}

Dokument: greeting/ja

{
  "code": "ja",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Start",
  "ctaUrl": "/ja/get-started"
}

Steg 3: Skapa sidan

Skapa en sida med följande konfiguration:

  • SökvĂ€g/mönster: /{lang}/landingPage
  • TillstĂ„nd: Live
  • Mappningar av dynamiska segment: mappa lang → komponenten language
  {
    "lang": "language"
  }

Steg 4: LĂ€gg till block med CEL-skript

LÀgg till ett hero-block i rutten med följande CEL-skript för varje fÀlt:

RubrikfÀlt:

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

UnderrubrikfÀlt:

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

CTA-textfÀlt:

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

CTA-URL-fÀlt:

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

Steg 5: AnvÀnd i Next.js

LĂ€gg till en catch-all-rutt. ParametricRoutePage löser sidan, extraherar meta.params frĂ„n URL:en, utvĂ€rderar dina CEL-bindningar pĂ„ serversidan och renderar varje block genom ditt register – du behöver inte skapa meta-kontexten eller sjĂ€lv anropa klienten pĂ„ lĂ„g nivĂ„.

// 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 })}
    />
  );
}

Steg 6: Testa rutterna

Besök dessa URL:er för att se lokaliserat innehÄll:

URLFörvÀntad rubrik
/ko/landingPage환영
/en/landingPageWelcome
/ja/landingPageă„ă‚‰ăŁă—ă‚ƒă„ăŸă›

SÄ fungerar upplösningen

NÀr en anvÀndare besöker /ko/landingPage:

  1. Ruttmatchning: CMS:et matchar mönstret /{lang}/landingPage
  2. Parameterextrahering: meta.params.lang = "ko"
  3. Validering: CMS:et validerar att "ko" finns i schemat language
  4. CEL-utvÀrdering: Skript som documents.get("greeting", meta.params.lang) löses till koreanskt innehÄll
  5. Svar: Lokaliserade block returneras till klienten

Bilaga B: Teknisk referens

CelMeta-grÀnssnitt (TypeScript)

interface CelMeta {
  /** Aktuell lokalkod (t.ex. 'en-US') */
  locale: string;
  /** Ruttparametrar extraherade frÄn URL:en */
  params: Record<string, string>;
  /** URL-sökvÀgssegment */
  segments: string[];
  /** Aktuellt dokument-ID (om ett befintligt dokument redigeras) */
  docId: string | null;
  /** Aktuellt dokumentets titel */
  title: string;
}

Algoritm för parameterextrahering

Funktionen extractParams bearbetar URL-sökvÀgar:

Mönster: /{country}/{lang}/products
SökvÀg:  /us/en/products

Algoritm:
1. Normalisera bÄda (ta bort avslutande snedstreck)
2. Dela upp i segment: ["us", "en", "products"] och ["{country}", "{lang}", "products"]
3. Matcha antalet segment (mÄste vara lika)
4. För varje segmentpar:
   - Om mönstret börjar med : eller {}, extrahera det som parameter
   - Annars mÄste det matcha exakt
5. Returnera: { country: "us", lang: "en" }

Format för parameterbindningar som stöds

// Enkel bindning (anvÀnder fÀltet "code" för uppslagning)
{ "lang": "language" }

// Detaljerad bindning (anpassat slug-fÀlt)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Prioritet för dokumentuppslagning

NÀr du hÀmtar via documents.get(schema, identifier):

  1. UUID-matchning: Om identifieraren Àr ett giltigt UUID hÀmtas dokumentet via id
  2. Code-fÀlt: Kontrollera fÀltet content.code
  3. Slug-fÀlt: Kontrollera fÀltet content.slug
  4. Titelmatchning: Kontrollera fÀltet title

Detta möjliggör flexibla dokumentreferenser med valfri unik identifierare.

Continue Reading
Previousâ€čInstall Profound CMS as a proxyNextProject Scaffoldingâ€ș