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

Tanpa kepala

Mulai CepatSplit Screen JSON Component Builder with LLMPenarikan Komponen Zod

REST API

ikhtisar API RESTgetConnect 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

Panduan praktis untuk menulis ekspresi CEL di CMS.

Panduan praktis untuk menulis ekspresi CEL di CMS.


Cara Kerja CEL

CEL (Common Expression Language) adalah bahasa skrip ringan yang terintegrasi di CMS kami. CEL memungkinkan Anda menulis ekspresi dinamis yang dapat mengambil data dari dokumen, membaca parameter URL, dan menghitung nilai secara langsung.

Berikut yang terjadi saat skrip CEL dijalankan:

Skrip Anda                     Mesin                         Hasil
    |                            |                            |
    v                            v                            v
documents.get("article", "intro") --> Mengambil dari basis data --> { headline: "Welcome", body: "..." }
         .headline                --> Mengekstrak bidang       --> "Welcome"

Anggap CEL sebagai bahasa kueri hanya-baca. CEL tidak dapat mengubah apa pun di basis data—hanya membaca data dan mengembalikan hasil yang dihitung. Hal ini membuatnya aman digunakan di mana saja dalam CMS.


Komponen Dasar

Setiap ekspresi CEL dapat mengakses tiga hal:

ObjekPenjelasanContoh
documentsMengambil dokumen apa pun dari CMSdocuments.get("country", "us")
metaInformasi tentang permintaan saat ini (lokal, parameter URL)meta.locale, meta.params.slug
schemaDefinisi bidang dokumen saat inischema.fields

Referensi Mandiri dengan doc

Saat menulis ekspresi CEL di dalam editor dokumen, Anda dapat mengakses nilai bidang dokumen saat ini menggunakan objek doc. Ini memungkinkan pembuatan bidang terhitung dan referensi lintas bidang.

// Mengakses bidang harga dokumen saat ini
doc.price

// Menghitung total dari bidang dokumen saat ini
doc.price * doc.quantity

// Kondisi berdasarkan status dokumen saat ini
doc.status == "published" ? doc.title : "Draft: " + doc.title

Objek doc berisi semua nilai bidang dari dokumen yang sedang diedit. Ini berguna untuk:

  • Bidang terhitung (misalnya, doc.price * doc.quantity)
  • Logika tampilan kondisional berdasarkan status dokumen
  • Ekspresi bergaya validasi

Mengambil Dokumen

Fitur CEL yang paling kuat adalah mengambil dokumen dari mana saja di CMS Anda.

Mendapatkan Satu Dokumen

Sintaks: documents.get(schemaName, identifier)

Misalkan Anda memiliki dokumen article yang disimpan dengan identifier "welcome-post":

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

Untuk mengambil seluruh dokumen:

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

Mengembalikan:

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

Untuk mengambil hanya headline:

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

Mengembalikan: "Welcome to Our Platform"

Untuk mengambil penulis:

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

Mengembalikan: "Sarah Chen"


Menggunakan Parameter URL

Saat halaman Anda memiliki rute dinamis (seperti /articles/[slug]), Anda dapat menggunakan meta.params untuk mendapatkan parameter URL dan mengambil dokumen yang tepat.

Jika seseorang mengunjungi /articles/welcome-post:

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

Mengembalikan: "Welcome to Our Platform"

Beginilah cara Anda membuat halaman dinamis—skrip CEL yang sama berfungsi untuk artikel apa pun, dengan menggunakan slug yang terdapat dalam URL.


Mengambil Banyak Dokumen

Sintaks: documents.find(schemaName) atau documents.find(schemaName, filter)

// Mendapatkan semua negara
documents.find("country")

Mengembalikan:

[
  { "code": "us", "name": "United States", "flag": "US" },
  { "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
  { "code": "gb", "name": "United Kingdom", "flag": "GB" }
]
// Mendapatkan negara dengan filter
documents.find("country", { "where": { "code": "us" } })

Mengembalikan:

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

Terjemahan

CEL mendukung pengambilan konten dokumen yang diterjemahkan dengan dua cara: terjemahan otomatis berdasarkan lokal dan pencarian terjemahan eksplisit.

Terjemahan Otomatis melalui meta.locale

Saat meta.locale diatur (misalnya dari parameter rute atau preferensi pengguna), documents.get() secara otomatis menggabungkan konten yang diterjemahkan:

// Jika meta.locale adalah "fr", mengembalikan terjemahan bahasa Prancis yang digabungkan dengan dokumen dasar
documents.get("greeting", "welcome").headline

Cara kerjanya:

  1. Mengambil konten dokumen dasar
  2. Jika meta.locale bukan "en" atau "en-US", mencari terjemahan di tabel translations
  3. Menggabungkan bidang terjemahan di atas konten dasar: { ...baseContent, ...translatedContent }

Artinya, bidang yang diterjemahkan akan menggantikan bidang dasar, sedangkan bidang yang belum diterjemahkan menggunakan nilai dari dokumen dasar.

Terjemahan Eksplisit dengan documents.translated()

Untuk kasus ketika Anda perlu mengambil terjemahan tertentu terlepas dari lokal saat ini:

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

// Selalu mengambil terjemahan bahasa Spanyol
documents.translated("greeting", "welcome", "es").headline

// Mengambil terjemahan berdasarkan parameter URL
documents.translated("product", meta.params.id, meta.params.lang).description

// Membandingkan terjemahan
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Contoh Terjemahan

Dokumen sapaan Anda dengan terjemahan:

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

// Terjemahan (bahasa: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }

// Terjemahan (bahasa: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }

Skrip CEL:

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

// Terjemahan bahasa Spanyol eksplisit
documents.translated("greeting", "welcome", "es").headline
// Mengembalikan: "Bienvenido"

// Pola fallback untuk terjemahan yang tidak tersedia
documents.translated("greeting", "welcome", meta.params.lang) != null
  ? documents.translated("greeting", "welcome", meta.params.lang).headline
  : documents.get("greeting", "welcome").headline

Contoh di Dunia Nyata

Contoh 1: Judul Blok Hero dari Dokumen Lain

Anda memiliki hero-block yang harus menampilkan headline dari dokumen article.

Dokumen artikel Anda (identifier: "homepage-hero"):

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

Skrip CEL pada bidang judul blok hero:

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

Hasil: Hero menampilkan "Build Faster, Ship Smarter"


Contoh 2: Nama Negara dari Kode

Anda membuat halaman di /countries/[code] dan ingin menampilkan nama negara lengkap.

Dokumen negara Anda:

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

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

Skrip CEL:

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

Saat seseorang mengunjungi /countries/us:

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

Saat seseorang mengunjungi /countries/sa:

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

Contoh 3: Konten Kondisional Berdasarkan Lokal

Tampilkan headline yang berbeda berdasarkan lokal pengguna.

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

Jika lokal adalah "ar-SA": Mengembalikan "Welcome, everyone" Jika lokal lainnya: Mengembalikan "Welcome"


Contoh 4: Pencarian Dokumen Berantai

article Anda memiliki bidang countryCode, dan Anda ingin mendapatkan nama negara lengkap.

Dokumen artikel:

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

Skrip CEL:

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

Yang terjadi:

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

Hasil: "United States"


Contoh 5: Nilai Fallback

Jika dokumen mungkin tidak ada, Anda dapat memberikan fallback:

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

Atau periksa apakah bidang tertentu ada:

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

Contoh 6: Bekerja dengan Daftar

Artikel Anda memiliki tag, dan Anda ingin memeriksa apakah tag tertentu ada:

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

Mengembalikan: true jika artikel memiliki tag "featured"

Mendapatkan tag pertama:

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

Mengembalikan: "announcement" (tag pertama)

Menghitung jumlah tag:

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

Mengembalikan: 2 (jumlah tag)


Rute Parametris dan meta.params

Rute parametris adalah kunci untuk membuat halaman dinamis dan terlokalisasi. Saat Anda menentukan pola rute seperti /{lang}/landingPage, CMS mengekstrak parameter dari URL dan membuatnya tersedia melalui meta.params.

Cara Kerja Parameter Rute

Definisi Pola Rute: Rute menggunakan sintaks :paramName atau {paramName} untuk menentukan segmen dinamis:

PolaContoh URLParameter yang Diekstrak
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Pengikatan Parameter: Setiap parameter rute dapat diikat ke skema dokumen untuk validasi:

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

Pengikatan ini memberi tahu CMS untuk:

  1. Mengekstrak segmen lang dari URL
  2. Memvalidasinya terhadap skema language (mencari dokumen dengan content.code yang cocok)
  3. Jika valid, menyediakan dokumen lengkap dalam parameter yang telah diselesaikan

Contoh: Landing Page Berbasis Bahasa

Konfigurasi rute:

  • Path: /{lang}/landingPage
  • Pola: /{lang}/landingPage
  • Pengikatan parameter: { "lang": "language" }

Dokumen sapaan Anda:

// 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" }

Skrip CEL untuk mengambil konten terlokalisasi:

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

Cara penyelesaiannya:

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

Pola Lanjutan: Rute Negara + Bahasa

Untuk rute seperti /{country}/{lang}/products:

Konfigurasi rute:

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

Skrip CEL:

// Mendapatkan nama negara
documents.get("country", meta.params.country).name

// Mendapatkan daftar produk berdasarkan negara
documents.find("product", { "where": { "country": meta.params.country } })

// Gabungan: Menampilkan sapaan khusus negara dalam bahasa pengguna
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name

Rangkaian validasi: CMS memvalidasi parameter secara hierarkis. Untuk rute /{country}/{lang}:

  1. Memvalidasi parameter country terhadap skema country
  2. Memvalidasi parameter lang terhadap skema language
  3. Secara opsional memvalidasi bahwa lang ada dalam array country.languages[] (validasi hierarkis)

meta.segments - Akses Path URL Mentah

meta.segments menyediakan path URL mentah sebagai array, berguna ketika Anda memerlukan akses berdasarkan posisi tanpa parameter bernama.

Cara kerjanya:

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

Kapan Menggunakan meta.segments atau meta.params

Kasus PenggunaanPendekatan Terbaik
Parameter bernama dari pola rutemeta.params.lang
Akses berdasarkan posisimeta.segments[0]
Mendapatkan kedalaman pathsize(meta.segments)
Memeriksa apakah path berisi segmen"admin" in meta.segments

Contoh dengan meta.segments

// Mendapatkan segmen pertama (sering kali kode bahasa)
meta.segments[0]

// Memeriksa kedalaman path
size(meta.segments) > 2 ? "deep" : "shallow"

// Memeriksa apakah berada di bagian admin
"admin" in meta.segments ? "admin mode" : "public mode"

// Fallback: Gunakan segmen jika parameter tidak diikat
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Referensi Lengkap Objek meta

Objek meta berisi seluruh konteks tentang permintaan saat ini:

PropertiTipeDeskripsi
meta.localestringKode lokal saat ini (misalnya, "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Parameter rute yang diekstrak dari pola URL
meta.segmentsstring[]Path URL yang dipecah menjadi beberapa segmen
meta.docId`string \null`UUID dokumen saat ini (null untuk dokumen baru)
meta.titlestringJudul dokumen saat ini

meta.locale

Kode lokal mengikuti format BCP 47 (bahasa-wilayah):

// Memeriksa lokal untuk bahasa RTL
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Mendapatkan bagian bahasa saja
meta.locale.split("-")[0]  // Tidak didukung - gunakan meta.params.lang sebagai gantinya

meta.params

Parameter rute selalu berupa string. CMS memvalidasinya terhadap skema yang terikat sebelum evaluasi:

// Mengakses parameter bernama
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Memeriksa apakah parameter ada
has(meta.params.category)  // true/false

// Menggunakannya dalam pengambilan dokumen
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Segmen URL mentah sebagai array:

// Mengakses berdasarkan indeks (berbasis 0)
meta.segments[0]           // Segmen pertama
meta.segments[1]           // Segmen kedua

// Memeriksa panjang
size(meta.segments)        // Jumlah segmen

// Memeriksa keanggotaan
"products" in meta.segments  // Apakah path menyertakan "products"?

meta.docId

UUID dokumen saat ini, berguna untuk skrip referensial mandiri:

// Hanya tersedia saat mengedit dokumen yang sudah ada
meta.docId != null ? "editing" : "creating new"

// Menggunakannya dalam logika kondisional
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Judul dokumen saat ini:

// Menggunakannya untuk tampilan
"Editing: " + meta.title

// Kondisional berdasarkan judul
meta.title.contains("Draft") ? "work in progress" : "published"

documents.ref() - Pencarian Berantai

Untuk sintaks yang lebih bersih ketika skema sudah diketahui tetapi identifier bersifat dinamis:

// Pendekatan tradisional
documents.get("airports", meta.params.code).name

// Menggunakan ref() - skema dipisahkan dari identifier dinamis
documents.ref("airports").get(meta.params.code).name

Keduanya setara, tetapi ref() membuat bagian dinamis lebih jelas.


Referensi Cepat

Pengambilan Dokumen

documents.get("schema", "identifier")       // Mendapatkan satu dokumen
documents.get("schema", "id").fieldName     // Mendapatkan bidang tertentu
documents.find("schema")                    // Mendapatkan semua dokumen
documents.find("schema", { "where": {...}}) // Kueri terfilter
documents.ref("schema").get(identifier)     // Pencarian berantai
documents.translated("schema", "id", "fr")  // Mendapatkan dengan lokal eksplisit

Variabel Konteks

meta.locale          // "en-US", "ar-SA", dll.
meta.params.xyz      // Parameter URL bernama "xyz"
meta.segments        // Path URL sebagai array: ["articles", "intro"]
meta.segments[0]     // Segmen path pertama
meta.docId           // ID dokumen saat ini (atau null)
meta.title           // Judul dokumen saat ini
doc.fieldName        // Nilai bidang dokumen saat ini (dalam konteks editor)

Operator

// Perbandingan
==  !=  <  <=  >  >=

// Logika
&&  ||  !

// Ternary (if-else)
condition ? valueIfTrue : valueIfFalse

// Keanggotaan
"value" in listOrMap

Fungsi Umum

size(list)                    // Menghitung item
size(string)                  // Panjang string
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Memeriksa apakah properti ada
hasProperty(obj, "key")       // Memeriksa apakah objek memiliki kunci (sintaks alternatif)

Pesan Kesalahan

Jika terjadi kesalahan, Anda akan melihat salah satu pesan berikut:

KesalahanArtinya
SYNTAX_ERRORKesalahan ketik dalam skrip (kutip tidak ada, operator salah)
TYPE_ERRORAnda mencampur tipe yang tidak dapat digunakan bersama
RUNTIME_ERRORSkrip berjalan, tetapi mengalami masalah (variabel tidak terdefinisi)
FETCH_LIMIT_EXCEEDEDAnda mengambil terlalu banyak dokumen (maksimal 50)
TIMEOUTSkrip berjalan terlalu lama (maksimal 5 detik)
AST_DEPTH_EXCEEDEDEkspresi terlalu dalam (kedalaman maksimal: 50)
SCRIPT_TOO_LONGSkrip melebihi batas 5000 karakter

Ekstensibilitas dan Kemampuan Mendatang

Mesin CEL dirancang agar dapat diperluas. Kemampuan yang direncanakan di masa mendatang meliputi:

Direncanakan: Integrasi Server MCP

// Mendatang: Memanggil layanan eksternal melalui MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

Direncanakan: Kemampuan AI

// Mendatang: Pembuatan konten bertenaga AI
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"])

Kemampuan ini akan ditambahkan melalui sistem fungsi terdaftar dengan tetap menjaga kompatibilitas mundur dengan skrip yang sudah ada.


Tips

  1. Gunakan pelengkapan otomatis - Ketik documents. atau meta. dan editor akan menampilkan opsi yang tersedia
  2. Mulai dari yang sederhana - Uji terlebih dahulu dengan documents.get("schema", "id"), lalu tambahkan .fieldName
  3. Periksa null - Jika dokumen mungkin tidak ada, tambahkan fallback dengan != null ? ... : ...
  4. Jangan mengambil data berlebihan - Setiap documents.get() atau documents.find() dihitung dalam batas 50 pengambilan
  5. Utamakan meta.params dibanding meta.segments - Parameter bernama telah divalidasi dan lebih andal
  6. Gunakan has() untuk parameter opsional - Periksa has(meta.params.category) sebelum mengaksesnya
  7. Gunakan documents.ref() untuk identifier dinamis - Sintaks lebih jelas ketika skema bersifat statis, tetapi identifier dinamis
  8. Gunakan doc.fieldName untuk referensi mandiri - Akses bidang dokumen saat ini dalam ekspresi terhitung

Referensi Antardokumen

Bagian ini membahas pola lanjutan untuk menghubungkan dokumen dan membangun struktur konten relasional.

Pola Referensi Dasar

Bentuk paling sederhana: satu dokumen mereferensikan dokumen lain berdasarkan identifier.

// Artikel menyimpan ID penulis, lalu mengambil nama penulis
documents.get("author", documents.get("article", "intro").authorId).name

Pencarian Berantai dengan documents.ref()

Untuk sintaks yang lebih bersih ketika identifier bersifat dinamis:

// Pendekatan tradisional
documents.get("country", documents.get("airport", meta.params.code).countryCode).name

// Menggunakan ref() - lebih jelas ketika skema diketahui tetapi identifier dinamis
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name

Rantai Referensi Multi-Level

Bangun hubungan yang mendalam dengan merangkai beberapa pencarian:

// Bandara → Negara → Wilayah → Benua
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Referensi dengan Terjemahan

Gabungkan referensi dokumen dengan terjemahan:

// Mendapatkan nama negara terlokalisasi untuk sebuah bandara
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Pola Referensi Berdasarkan Kasus Penggunaan

Pola 1: Pencarian Foreign Key

Dokumen menyimpan ID yang merujuk ke dokumen lain.

// article / tech-news
{ "title": "Tech Update", "authorId": "author-123", "categoryId": "cat-tech" }
// Menyelesaikan nama penulis
documents.get("author", documents.get("article", meta.params.slug).authorId).name

// Menyelesaikan kategori dengan fallback
documents.get("article", meta.params.slug).categoryId != null
  ? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
  : "Uncategorized"

Pola 2: Referensi Berbasis Kode

Dokumen saling merujuk menggunakan kode semantik, bukan UUID.

// 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" }
// Rantai Bandara → Negara → Mata Uang
documents.get("currency",
  documents.get("country",
    documents.get("airport", meta.params.code).countryCode
  ).currencyCode
).symbol
// Untuk JFK: Mengembalikan "$"

Pola 3: Referensi Mandiri dengan Konteks doc

Gunakan doc untuk bidang terhitung yang merujuk ke dokumen lain berdasarkan nilai dokumen saat ini.

// Dalam dokumen produk, mengambil detail kategori terkait
documents.get("category", doc.categoryId).description

// Biaya pengiriman terhitung berdasarkan negara asal produk
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Pola 4: Referensi Dua Arah

Saat dokumen saling merujuk, berhati-hatilah terhadap batas pengambilan data.

// Mendapatkan penulis artikel, lalu artikel lain milik penulis tersebut (perhatikan jumlah pengambilan!)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })

Pola 5: Referensi Polimorfik

Saat sebuah bidang dapat merujuk ke skema yang berbeda:

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

// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Pencarian skema dinamis berdasarkan 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

Pelacakan Dependensi

Setiap pemanggilan documents.get(), documents.find(), dan documents.ref().get() dilacak untuk invalidasi cache. Saat dokumen yang dirujuk berubah, CMS mengetahui ekspresi CEL mana yang perlu dievaluasi ulang.

Dependensi yang dilacak meliputi:

  • get: schema:identifier - Dependensi dokumen tertentu
  • ref: schema:identifier - Sama seperti get, melalui sintaks berantai
  • query: schema:* - Dependensi tingkat skema (dokumen apa pun dalam skema)

Praktik Terbaik untuk Referensi

  1. Minimalkan kedalaman rantai - Setiap tingkat menambah latensi dan jumlah pengambilan
  2. Simpan hasil antara dalam cache - Jika memerlukan nilai bertingkat yang sama dua kali, ambil induknya sekali
  3. Gunakan pemeriksaan null - Referensi dapat gagal jika dokumen dihapus
  4. Utamakan kode dibanding UUID - Kode lebih mudah dibaca dalam ekspresi dan stabil di berbagai lingkungan
  5. Perhatikan batas pengambilan - Rantai referensi kompleks dapat segera mencapai batas 50 pengambilan

Lampiran A: Contoh Rute Parametris Lengkap

Panduan ini membuat landing page multibahasa yang dapat diakses di /{lang}/landingPage.

Langkah 1: Membuat Skema Dokumen Greeting

Di admin CMS, buat skema khusus bernama greeting:

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

Langkah 2: Membuat Dokumen Greeting

Buat dokumen untuk setiap bahasa:

Dokumen: greeting/ko

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

Dokumen: greeting/en

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

Dokumen: greeting/ja

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

Langkah 3: Membuat Halaman

Buat halaman dengan konfigurasi berikut:

  • Path/Pola: /{lang}/landingPage
  • Status: Live
  • Pemetaan Segmen Dinamis: petakan lang → komponen language
  {
    "lang": "language"
  }

Langkah 4: Menambahkan Blok dengan Skrip CEL

Tambahkan blok hero ke rute dengan skrip CEL berikut untuk setiap bidang:

Bidang Headline:

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

Bidang Subheadline:

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

Bidang Teks CTA:

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

Bidang URL CTA:

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

Langkah 5: Menggunakan di Next.js

Tambahkan rute catch-all. ParametricRoutePage menyelesaikan halaman, mengekstrak meta.params dari URL, mengevaluasi binding CEL Anda di sisi server, dan merender setiap blok melalui registry Anda—Anda tidak perlu membuat konteks meta atau memanggil klien tingkat rendah sendiri.

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

Langkah 6: Menguji Rute

Kunjungi URL berikut untuk melihat konten terlokalisasi:

URLHeadline yang Diharapkan
/ko/landingPage환영
/en/landingPageWelcome
/ja/landingPageいらっしゃいませ

Cara Kerja Resolusi

Saat pengguna mengunjungi /ko/landingPage:

  1. Pencocokan Rute: CMS mencocokkan pola /{lang}/landingPage
  2. Ekstraksi Parameter: meta.params.lang = "ko"
  3. Validasi: CMS memvalidasi bahwa **"ko" ada dalam skema language
  4. Evaluasi CEL: Skrip seperti documents.get("greeting", meta.params.lang) diselesaikan menjadi konten bahasa Korea
  5. Respons: Blok terlokalisasi dikembalikan ke klien

Lampiran B: Referensi Teknis

Antarmuka CelMeta (TypeScript)

interface CelMeta {
  /** Kode lokal saat ini (misalnya, 'en-US') */
  locale: string;
  /** Parameter rute yang diekstrak dari URL */
  params: Record<string, string>;
  /** Segmen path URL */
  segments: string[];
  /** ID dokumen saat ini (jika sedang mengedit dokumen yang sudah ada) */
  docId: string | null;
  /** Judul dokumen saat ini */
  title: string;
}

Algoritme Ekstraksi Parameter

Fungsi extractParams memproses path URL:

Pola: /{country}/{lang}/products
Path:    /us/en/products

Algoritme:
1. Normalisasi keduanya (hapus garis miring di akhir)
2. Pecah menjadi segmen: ["us", "en", "products"] dan ["{country}", "{lang}", "products"]
3. Cocokkan jumlah segmen (harus sama)
4. Untuk setiap pasangan segmen:
   - Jika pola diawali : atau {}, ekstrak sebagai parameter
   - Jika tidak, harus cocok persis
5. Kembalikan: { country: "us", lang: "en" }

Format Pengikatan Parameter yang Didukung

// Pengikatan sederhana (menggunakan bidang "code" untuk pencarian)
{ "lang": "language" }

// Pengikatan terperinci (bidang slug khusus)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Prioritas Pencarian Dokumen

Saat mengambil melalui documents.get(schema, identifier):

  1. Pencocokan UUID: Jika identifier merupakan UUID yang valid, ambil berdasarkan id
  2. Bidang kode: Periksa bidang content.code
  3. Bidang slug: Periksa bidang content.slug
  4. Pencocokan judul: Periksa bidang title

Hal ini memungkinkan referensi dokumen yang fleksibel menggunakan identifier unik apa pun.

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