From HTML to JSON
Think of your pages as stack of sections from top to bottom.
Each section is self-contained and configurable with props.
Without a CMS, your templates might look something like this:
<!--home.vue-->
<template>
<SectionHero title="Orbitype" subtitle="A modern CMS"/>
<SectionFigure img=".../foo.png" caption="Lorem ipsum"/>
</template>To make this dynamic, start by moving the hard-coded content over to Orbitype.
Translate the HTML to an equivalent JSON structure holding the props.
Define the component to render in the special _orbi field.
// home.json
{
"sections": [
{
"title": "Orbitype",
"subtitle": "Lorem ipsum",
"_orbi": { "component": "SectionHero" }
},
{
"img": ".../foo.png",
"caption": "Lorem ipsum",
"_orbi": { "component": "SectionFigure" }
}
]
}Dynamic templates
By using a glob import and dynamic resolution,
you can create a dynamic AnySection component.
<!--AnySection.vue-->
<script setup lang="ts">
const all = import.meta.glob("~/components/sections/*.vue", { eager: true })
const components = Object.values(all).map((x) => x.default)
defineProps<{ data: Record<string, any> }>()
</script>
<template>
<component
:is=" components.find((x) => x.__name === data._orbi.component)"
v-bind="data"
/>
</template>Next, replace your hard-coded list of components with a loop of AnySection.
Pass the data from Orbitype as the array to loop over.
<!--home.vue-->
<script setup lang="ts">
const page = await $fetch(import.meta.env.VITE_S3_URL + "/pages/home.json")
</script>
<template>
<AnySection v-for="section of page.sections" :data="section"/>
</template>And you're done!
You can now add, remove, modify and reorder sections in Orbitype.
All without touching a single line of code.