Skip to main content
RapidDev - Software Development Agency
lovable-integrationsEdge Function Integration

How to Integrate Lovable with Kentico

Connect your Lovable app to Kentico Xperience by calling the Kentico Delivery API (or Headless Channel API) from a Supabase Edge Function with your Kentico API key. Fetch content items, assets, taxonomies, and custom content types from Kentico's .NET enterprise DXP. Kentico differs from TYPO3 in being a .NET-based commercial DXP with digital marketing and personalization features built in, while TYPO3 is a PHP open-source enterprise CMS.

What you'll learn

  • How to configure Kentico Xperience's headless delivery channel and get an API key
  • How to write a Supabase Edge Function that fetches Kentico content items
  • How to query Kentico content by content type, taxonomy, and custom filters
  • How to handle Kentico's content item structure with system fields and custom type fields
  • How Kentico Xperience differs from TYPO3 as an enterprise DXP choice
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate12 min read40 minutesCMSMarch 2026RapidDev Engineering Team
TL;DR

Connect your Lovable app to Kentico Xperience by calling the Kentico Delivery API (or Headless Channel API) from a Supabase Edge Function with your Kentico API key. Fetch content items, assets, taxonomies, and custom content types from Kentico's .NET enterprise DXP. Kentico differs from TYPO3 in being a .NET-based commercial DXP with digital marketing and personalization features built in, while TYPO3 is a PHP open-source enterprise CMS.

Build a headless Kentico Xperience frontend with Lovable

Kentico Xperience is a commercial .NET enterprise DXP aimed at organizations that need content management plus digital marketing in one platform. Unlike pure CMS tools, Kentico includes A/B testing, multivariate testing, marketing automation, email campaigns, personalization rules, and a built-in customer data platform. For marketing teams running on Kentico, the DXP houses both content and campaign data in one system.

The headless delivery layer in Kentico Xperience (versions 26+, formerly known as Kentico Kontent now rebranded as Xperience by Kentico) provides a cloud-based content delivery API. Content is organized into Content Types (defining the schema of a content item, like Blog Post with title, body, author, and featured image fields), and Content Items (instances of those types). The Delivery API returns content items with their field values in a predictable JSON structure, making it straightforward to map to React components.

Kentico's headless API differs from WordPress or Ghost in its strong typing — each content item has a known content type with defined fields, similar to Contentful. This makes it predictable to build React components against: you know exactly what fields a 'BlogPost' content item has because the type is defined in Kentico. The tradeoff is that content type changes in Kentico require corresponding updates to your React rendering components. For enterprises with stable content models, this is not a problem; for rapidly evolving content structures, the rigidity can be limiting.

Integration method

Edge Function Integration

Kentico integrates with Lovable through a Supabase Edge Function that calls Kentico Xperience's Delivery API (for Kentico 12 and Xperience by Kentico) or Headless Channel content delivery API using an API key from Cloud → Secrets. The Edge Function fetches content items by content type, filters by taxonomy, and returns structured content data to the React frontend. Kentico's content API returns items with system metadata and fields following your content type schema.

Prerequisites

  • A Kentico Xperience installation (version 26+ for Xperience by Kentico headless, or Kentico 12 Cloud for the older Delivery API)
  • A Headless Channel configured in Kentico administration with an API key
  • Your Kentico instance URL and the Content Delivery API URL
  • Knowledge of your content type codenames (visible in Kentico Content Type management)
  • A Lovable account with an active Lovable Cloud project

Step-by-step guide

1

Configure a Kentico Headless Channel and get the API key

Kentico Xperience uses 'Channels' to configure delivery endpoints. A Headless Channel provides a REST API for content delivery. If your organization has not set up a Headless Channel, a Kentico administrator needs to create one. To create a Headless Channel in Kentico Xperience: Log in to Kentico administration (typically at your-instance.xperience.io/admin). Go to Content delivery → Headless channels. Click 'Create headless channel'. Give it a name (e.g., 'Lovable App') and configure: - Allowed content types — select which content types are exposed through this channel - API key — Kentico auto-generates this, or you can set a custom one - Allowed origins for CORS — add your Lovable app domain Once created, note the Headless Channel API key and the Content Delivery API base URL (format: https://deliver.kontent.ai/{environment-id} for older Kontent/Kentico Cloud, or https://your-instance.xperience.io/api/ for self-hosted Xperience). In Lovable, click '+' next to Preview to open the Cloud panel, then click 'Secrets'. Add: - KENTICO_DELIVERY_URL — the Content Delivery API base URL - KENTICO_API_KEY — the Headless Channel API key - KENTICO_CHANNEL_NAME — the channel name or environment ID Kentico API keys are typically UUIDs (format: 00000000-0000-0000-0000-000000000000). They grant read access to content items published in the configured channel. Store them in Cloud → Secrets — Lovable's security blocks approximately 1,200 hardcoded API keys daily.

Pro tip: Request the Kentico administrator to share the full API key and the exact Delivery API URL. Kentico configurations vary between on-premise and cloud-hosted versions, and the URL structure differs significantly between Kentico 12, Kentico Kontent (SaaS), and Xperience by Kentico.

Expected result: KENTICO_DELIVERY_URL, KENTICO_API_KEY, and KENTICO_CHANNEL_NAME are stored in Cloud → Secrets. A test request to the Kentico Delivery API with the API key in an Authorization header returns content items.

2

Create the Kentico Delivery API proxy Edge Function

Kentico's Content Delivery API uses Bearer token authentication with the API key. For Xperience by Kentico (self-hosted), the API URL pattern is: GET /api/delivery/pages?channelName={channel}&contentTypeCodename={type}&languageName={lang}. For Kentico as a Service (KaaS / formerly Kontent.ai), the pattern is: GET https://deliver.kontent.ai/{environmentId}/items?system.type={type}. Content item responses contain two levels: the 'system' object (with id, name, codename, language, type, collection, workflow_step, last_modified) and the 'elements' or 'fields' object containing your custom content type field values (field codename: { type: 'text', value: '...' }). The Edge Function below handles Xperience by Kentico's self-hosted delivery format. Adapt the URL pattern and response mapping for your specific Kentico version. Your Kentico developer can share the exact endpoint format and a sample response payload.

Lovable Prompt

Create a Supabase Edge Function at supabase/functions/kentico-proxy/index.ts that calls the Kentico Xperience Content Delivery API. Read KENTICO_DELIVERY_URL, KENTICO_API_KEY, and KENTICO_CHANNEL_NAME from Deno.env.get(). Accept a POST request with 'contentType' string (codename of the content type), optional 'slug' string (for single item by URL slug), optional 'language' string (language code, defaults to 'en'), optional 'limit' and 'offset' integers for pagination, and optional 'taxonomyFilter' object. Build the Kentico API URL and call it with 'Authorization: Bearer {key}' header. Return the content items data array and pagination info.

Paste this in Lovable chat

supabase/functions/kentico-proxy/index.ts
1// supabase/functions/kentico-proxy/index.ts
2const corsHeaders = {
3 'Access-Control-Allow-Origin': '*',
4 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
5};
6
7Deno.serve(async (req) => {
8 if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders });
9
10 try {
11 const { contentType, slug, language = 'en', limit = 10, offset = 0, taxonomyFilter } =
12 await req.json() as {
13 contentType?: string; slug?: string; language?: string;
14 limit?: number; offset?: number; taxonomyFilter?: Record<string, string>;
15 };
16
17 const deliveryUrl = Deno.env.get('KENTICO_DELIVERY_URL')!.replace(/\/$/, '');
18 const apiKey = Deno.env.get('KENTICO_API_KEY')!;
19 const channelName = Deno.env.get('KENTICO_CHANNEL_NAME')!;
20
21 const params = new URLSearchParams({
22 channelName,
23 languageName: language,
24 });
25
26 if (contentType) params.set('contentTypeCodename', contentType);
27 if (slug) params.set('urlSlug', slug);
28 if (limit) params.set('limit', String(limit));
29 if (offset) params.set('offset', String(offset));
30 if (taxonomyFilter) {
31 Object.entries(taxonomyFilter).forEach(([key, value]) => {
32 params.set(`taxonomies[${key}]`, value);
33 });
34 }
35
36 const url = `${deliveryUrl}/api/delivery/pages?${params.toString()}`;
37 console.log(`Kentico API request: ${url}`);
38
39 const kenticoResponse = await fetch(url, {
40 headers: {
41 'Authorization': `Bearer ${apiKey}`,
42 'Accept': 'application/json',
43 },
44 });
45
46 if (!kenticoResponse.ok) {
47 const errText = await kenticoResponse.text();
48 console.error(`Kentico API error ${kenticoResponse.status}:`, errText);
49 return new Response(JSON.stringify({ error: `Kentico API returned ${kenticoResponse.status}` }), {
50 status: kenticoResponse.status,
51 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
52 });
53 }
54
55 const result = await kenticoResponse.json();
56 return new Response(JSON.stringify({
57 items: result.items ?? result.webPageItems ?? result,
58 pagination: result.pagination ?? { totalCount: result.items?.length ?? 0 },
59 }), {
60 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
61 });
62 } catch (error) {
63 console.error('kentico-proxy error:', error);
64 return new Response(JSON.stringify({ error: String(error) }), {
65 status: 500,
66 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
67 });
68 }
69});

Pro tip: Log the raw Kentico API response in Cloud → Logs during your first test request. Kentico's response structure varies between versions — seeing the actual JSON helps you adapt the field mapping quickly rather than guessing from documentation.

Expected result: The kentico-proxy Edge Function deploys. A test request with contentType='article' returns a structured items array from Kentico with system metadata and content type field values. Cloud → Logs confirms 200 responses from the Kentico API.

3

Build the Kentico content display components

With the Edge Function deployed, build the React components that render Kentico content items. Kentico content items have a predictable structure — each item has system fields and element/field values keyed by their codename. Your Kentico administrator can share the content type schema showing all codenames and types. For Xperience by Kentico content items, fields are accessed as item.fields.{field_codename}.value for text and number fields, item.fields.{field_codename}.asset for file/image fields, and item.fields.{field_codename}.pages for linked content items. For rich text fields (body text with formatting), Kentico returns HTML content in the value field. Sanitize with DOMPurify and render with dangerouslySetInnerHTML. For asset fields (images, documents), the URL is in item.fields.field_name.asset.url. For taxonomy fields, Kentico returns an array of taxonomy term objects. Use these for category badges and filtering. Ask Lovable to build the content display components by sharing your content type schema. For complex Kentico deployments with dozens of content types, linked items, and rich text with embedded components, RapidDev's team can help build a complete content rendering engine for all your Kentico content types.

Lovable Prompt

Build a Kentico article listing and detail component. The article content type has fields: title (text), summary (text), body_richtext (rich_text HTML), teaser_image (asset with url), publication_date (date), url_slug (text), and categories (taxonomy array). For the listing (/blog): fetch items with contentType='article', display as cards with teaser_image.url, title, summary, formatted publication_date, and category badges. For the detail (/blog/:slug): fetch with slug parameter, render: large image hero, h1 title, categories chips, publication date, body_richtext as DOMPurify-sanitized dangerouslySetInnerHTML.

Paste this in Lovable chat

Pro tip: Create a TypeScript interface for each Kentico content type you use. Define the expected field codenames and types as an interface so TypeScript provides autocomplete and catches field name typos at compile time.

Expected result: Kentico article content items render correctly with images, rich text body, and taxonomy category badges. The listing and detail views display the Kentico-managed content in the Lovable app's design system.

Common use cases

Render Kentico content items in a Lovable React app

An enterprise website manages all editorial content in Kentico Xperience with a structured content model of articles, product pages, team members, and case studies. The Lovable app fetches these content items via the Delivery API, maps each content type to a React component, and renders the full site. Marketing editors continue working in Kentico while the Lovable frontend provides a modern user experience.

Lovable Prompt

Build a content router for Kentico Xperience. Create a page component that accepts a URL path and calls the kentico-proxy Edge Function to find the matching content item by URL slug. Based on the returned content_type_codename, render the appropriate component: ArticleDetail, ProductPage, TeamMember, or CaseStudy. Each component maps Kentico field codenames to display properties. Show a 404 component if no content item matches the slug.

Copy this prompt to try it in Lovable

Display a Kentico blog with category and tag filtering

Kentico manages a corporate blog with articles organized by categories (taxonomies). The Lovable app fetches articles from Kentico's Delivery API filtered by content type and optionally by taxonomy group. Article cards display the title, teaser image, publication date, and category. Clicking an article fetches the full article details from Kentico and renders them with all custom fields.

Lovable Prompt

Build a blog listing page fetching Article content items from Kentico via the kentico-proxy Edge Function. Request items of type 'article' with fields: title, summary, teaser_image, publication_date, url_slug, and taxonomy:categories. Display articles as a card grid. Add category filter chips from the Kentico taxonomy. On filter change, refetch articles with taxonomy filter applied. Clicking a card navigates to /blog/:slug which fetches the full article with all fields including body_richtext.

Copy this prompt to try it in Lovable

Localize Kentico content using language variants

Kentico supports multiple language variants for each content item. The Lovable app reads the user's preferred language from URL prefix or browser settings and passes the corresponding language code to the Kentico Delivery API. Content editors manage all language versions in Kentico's dual-language editor, and the Lovable frontend automatically serves the correct language.

Lovable Prompt

Add multilingual support to the Kentico frontend. Detect the language from the URL prefix (/en/, /de/, /fr/). Pass the language code as a header or query parameter to the kentico-proxy Edge Function which forwards it to the Kentico Delivery API. Build a language switcher dropdown in the header that changes the URL prefix and triggers page content refetch. Fall back to the default language if a translation is not available.

Copy this prompt to try it in Lovable

Troubleshooting

Kentico API returns 401 Unauthorized or 403 Forbidden

Cause: The KENTICO_API_KEY is incorrect, the Headless Channel is not published or activated, or the content type is not included in the channel's allowed content types.

Solution: Verify the API key in Kentico administration → Content delivery → Headless channels → your channel → API key. Also confirm the channel is in 'Active' status and that the content types you are requesting are listed in the channel's allowed content types. A Kentico administrator may need to publish the channel if it was recently created.

Content items return empty items array even though content exists in Kentico

Cause: Content items must be in 'Published' workflow state to appear in the Delivery API. Draft or archived items are excluded. Also, the channelName parameter may not match the configured headless channel.

Solution: In Kentico administration, navigate to the content item and check its workflow state — it must be in the 'Published' state (not Draft, Scheduled, or Archived). Also verify the KENTICO_CHANNEL_NAME in Cloud → Secrets exactly matches the channel's codename in Kentico (not the display name — channel codenames are lowercase with underscores).

Rich text field returns HTML with Kentico-specific data attributes that render incorrectly

Cause: Kentico's rich text fields can include data-asset-id and data-id attributes for inline linked items and asset references. These render as broken elements outside Kentico's rendering pipeline.

Solution: For assets embedded in rich text (images), the Kentico Delivery API response includes a linkedItems section with asset URLs. Map the data-asset-id attributes to their resolved URLs before rendering. For text-only display, strip all data- attributes and custom Kentico markup using a DOMPurify configuration that removes them.

typescript
1// DOMPurify config to strip Kentico data attributes
2const clean = DOMPurify.sanitize(html, {
3 ADD_TAGS: ['figure', 'figcaption'],
4 FORBID_ATTR: ['data-asset-id', 'data-id', 'data-codename'],
5});

Best practices

  • Create TypeScript interfaces for each Kentico content type you use, mapping codenames to typed properties — this prevents typos in field codename access and makes React component props self-documenting.
  • Cache Kentico content in Supabase with a sensible TTL (15-60 minutes for article listings) — Kentico Delivery API has rate limits and content changes rarely require real-time freshness.
  • Request only the fields you need using Kentico's field projection parameters when available — large content items with many fields and embedded assets increase response size and parsing time.
  • Handle Kentico workflow states gracefully — only published items appear in the Delivery API, but if you have a preview mode, you can use Kentico's Preview API (requires a separate Preview API key) to fetch draft content for staging environments.
  • Use Kentico's taxonomy codenames for filters rather than display names — taxonomy codenames are stable identifiers while display names can change in Kentico without affecting the API.
  • Verify the channelName parameter matches your Kentico channel's codename exactly — channel codenames are case-sensitive and different from the human-readable display name shown in the Kentico administration UI.
  • For enterprise Kentico deployments with personalization and A/B testing, the Delivery API returns the base content. Marketing automation and personalization rules run on the Kentico server side — when going headless, you lose Kentico's built-in personalization engine and need to implement it separately or via a client-side personalization tool.

Alternatives

Frequently asked questions

What is the difference between Kentico Xperience and Kentico Kontent?

Kentico had two products: Kentico Xperience (formerly EMS, an on-premise/.NET DXP) and Kentico Kontent (now Kontent.ai, a cloud-native headless CMS). In 2022, Kentico merged both product lines into 'Xperience by Kentico'. The current product is a hybrid — self-hosted .NET application with a cloud option. Older Kentico 12/13 installations use the original EMS API. Kontent.ai is now an independent product under a separate brand. This tutorial primarily covers Xperience by Kentico (the current merged product).

Does Kentico Xperience require a license for the headless API?

Yes. Kentico Xperience is commercial software requiring a license. The headless delivery channel is included in most Xperience editions (Business, Business+, Enterprise). The Delivery API access is tied to your licensed Kentico installation. Contact Kentico sales at kentico.com for pricing — enterprise licenses are typically negotiated, not listed publicly.

How does Kentico's content structure differ from WordPress?

Kentico uses a strongly typed content model where each piece of content is an instance of a defined Content Type with specific fields (codename, type, required, etc.). WordPress uses a flexible content model with posts, pages, and custom post types, with optional custom fields added via plugins. Kentico's approach is more like Contentful — predictable, schema-enforced, and typed. WordPress is more flexible but less structured. For enterprise environments where content consistency matters, Kentico's typed model reduces errors.

Can I use Kentico's personalization features in a Lovable headless frontend?

Partially. Kentico's Delivery API returns base content — the personalization engine runs server-side in Kentico's .NET application. When you go headless, Kentico's built-in personalization (showing different content to different segments based on Kentico's contact tracking) does not work through the Delivery API. To implement personalization in the Lovable app, you need to either: use Kentico's Preview API with personalization parameters, implement personalization in the Lovable frontend using contact attributes stored in Supabase, or use a third-party personalization tool like Segment or a feature flag service.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.