Kontent ♥ Svelte ♥ Custom elements
Yuriy Sountsov
Posted on February 24, 2021
Photo by Clément Hélardot on Unsplash
The power of Kontent
Kontent is a headless CMS platform that allows enterprises to reach more customers, unify content across the business, and structure content for future content needs, all in one place. As a headless CMS, all content delivery is API-driven, so the same content can show up on any device or channel. 🧠
But what is content? How do you define content? Kontent solves this by creating a reliable structure of items composed of elements. The elements range from plain text to dates to tags to lists of references to other items. Nearly anything can be modeled by combining these elements like LEGO pieces to represent a website, a training manual, a sport directory, you name it. ✨
With great power comes great exploration, and it sometimes happens that you want to model something outside of the known elements. Some examples are geolocation, a video, or a structured list of items. Kontent provides a way to model these and other types of content using custom elements. 🎉
Custom elements run on a host of your choice and only need a browser SDK to communicate with Kontent. This way they have their own UI and their own behavior, and give you freedom to model any content. We will come back to custom elements later... ⌚
The power of Svelte
Svelte is a state-of-the-art JavaScript application compiler that takes a lot of boilerplate out of writing browser apps so that you can focus on the reactive user experience. To learn more about Svelte check out the tutorial for a rundown of the basics. 🎓
The best way to deliver a good user experience is to be extremely fast. But why repeat what has already been well said by the creator himself? Just give this a watch: 👀
Along with Svelte comes Sapper, an easy way to create static sites running Svelte. Sapper can also quickly deploy to Vercel, a modern app host with unlimited deployments. 🔮
By their powers combined...
With Svelte, we have a way to rapidly create Kontent custom elements. While Svelte takes away the application boilerplate, there is still some boilerplate needed to make custom elements work - initialization, converting a rich object to a string value, reacting to changes in the context (e.g. we want to disable the element when the Kontent item is also disabled), and keeping up with the improving UI. 🤔
Introducing kontent-custom-element-app
. 🎆
kontent-custom-element-app
(KCEA for short) is a tool that maintains a template to make Kontent custom elements in Svelte as easy as a .svelte
component in the src/routes/elements
directory using <CustomElement />
to wrap the component's HTML. 🌯
<CustomElement bind:value bind:config bind:disabled>
// Inputs and values here...
</CustomElement>
KCEA comes with one starter custom element showing different ways to store custom values. It bundles four types of content: text, number, date, and object: 🎭
KCEA also optionally installs two sample custom elements that show more possibilities: color and list. ⚡
Would you like to know more?
Photo by Stefan Steinbauer on Unsplash
KCEA comes with some bonus features!
-
VERCEL - The template is already set up for deployment to Vercel. Just install the Vercel CLI and then run
vercel
in the root of the app. Follow the prompts and you'll be good to share the element outside of localhost! 🌍 -
TYPESCRIPT - The template is also set up for TypeScript, and supports type annotation in components. It will evolve TypeScript support alongside Svelte's TypeScript support. It is a best practice to type
value
andconfig
within your custom elements. 💪 -
UPDATES - When you update with
npm i kontent-custom-element-app
, the tool will update template files that have not been changed, and let you know which ones have so you can merge changes manually. An example of what that looks like: 🔍
File at 'C:\ ... \src\routes\_layout.svelte' has been modified.
Please manually merge changes from '_layout.svelte' into '_layout.svelte.new' and remove the '.new' extension.
-
USEFUL STUFF -
<CustomElement />
has two named slots:loading
andinvalid
. They let you pass in anything that you want to show when the element is loading (between page load and custom element initialization) and when the element's route is visited outside of Kontent. KCEA comes with the components<Loading />
and<Invalid />
to make these slots painless. KCEA also installs the following optional helpful things: 👍- A
<Filter />
component, which is a filtering text input with autocomplete and other features. - An
<ObjectTile />
component, which is styled to match asset references in Kontent and helps make custom elements blend into the Kontent UI. - A
localStorage
store to reactively store values in the browser's local storage. - A
translate
store to separate translations from the custom element presentation. - A
property
action to remove some boilerplate around CSS variables on HTML nodes.
- A
- THE KONSERVATORY - If you want some inspiration, the author maintains a site with many KCEA custom elements at The Konservatory. The Konservatory itself runs on KCEA and thus hosts both a gallery and the elements themselves, showing how KCEA can be a base for more routes and more possibilities! 🤩
TL;DR Quickstart
Photo by Braden Collum on Unsplash
In an empty folder for the app:
npm init kontent-custom-element-app -n custom-element -s -r
Want a basic custom element component to start with? Go to the src/routes/elements
directory and add this in a .svelte
file:
Script, markup, and style code
<script lang="ts">
import { fade } from "svelte/transition";
import CustomElement from "../../shared/components/customElement/customElement.svelte";
import Invalid from "../../shared/components/customElement/invalid.svelte";
import Loading from "../../shared/components/loading.svelte";
let value: string = "";
let disabled: boolean;
</script>
<CustomElement bind:value bind:disabled>
<div class="group column root" transition:fade>
<input
class="input"
type="text"
placeholder="Type here..."
bind:value
{disabled} />
</div>
<div slot="loading">
<Loading />
</div>
<div slot="invalid">
<Invalid />
</div>
</CustomElement>
<style>
.root {
padding: 1em;
background-image: linear-gradient(
135deg,
hsl(111, 10%, 98%),
hsl(111, 35%, 90%)
);
border-radius: 0.5em;
}
input {
background: none;
}
</style>
Let me know down below if you have any questions or would like to start a discussion!
Posted on February 24, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.