Sections
Sections
Section titled “Sections”A section is the most basic building block, and is basically nothing more than a component in Astro or Vue.
In fact, a section in PageDepot is directly converted to a component file during the provisioning step, be it
an .astro file or .vue single-file-component.
Sections have a name, a type, props and code.
The type can be one of astro or vue.
It decides what type of code you can write.
The props define the input parameters your section can receive.
This is used for Brezel to be able to define a fitting UX to edit these props.
It is also used by PageDepot to prepare the prop values accordingly.
For example, if the prop’s type is select, PageDepot loads the respective entity from Brezel.
The syntax is
{ "propName": { "type": "propType" }}or its shorthand
{ "propName": "propType"}For types like object or list, you can nest prop definitions:
{ "myObject": { "type": "object", "props": { "someProp": "text" } }, "myList": { "type": "list", "listType": { "type": "object", "props": { "someProp": "text" } } }}Then, when using the section in a page slot, you would give the params like this:
[ { "slot": "default", "sections": [ { "section": { "id": 10 }, "myObject": { "someProp": "lorem ipsum" }, "myList": [ { "someProp": "dolor sit amet" } ] } ] }]Available types
Section titled “Available types”Text (text)
Section titled “Text (text)”{ "type": "text"}Number (number)
Section titled “Number (number)”{ "type": "number"}Object (object)
Section titled “Object (object)”{ "type": "object", "props": {} // define the object's props here}List (list)
Section titled “List (list)”{ "type": "list", "listType": {} // define the list item type here}Entity (select)
Section titled “Entity (select)”Usage in props
Section titled “Usage in props”{ "type": "select", "options": { "references": "the_module" }}Type schema for params
Section titled “Type schema for params”An entity object with id.
type EntityParams = { id: string | number};Entities (entities)
Section titled “Entities (entities)”Usage in props
Section titled “Usage in props”An object with optional property module (the module identifier).
{ "type": "entities", "module": "the_module"}Example for section code
Section titled “Example for section code”const entities = props.entities;Type schema for params
Section titled “Type schema for params”type EntitiesParams = { module?: string; filters?: Array<Record<string, unknown>> | Array<Array<Record<string, unknown>>>; results?: number;}Module (module)
Section titled “Module (module)”Example for section code
Section titled “Example for section code”const module = props.module;module.fields.forEach(field => { console.log(field);})Type schema for params
Section titled “Type schema for params”type ModuleParams = { identifier: string;};Image (image)
Section titled “Image (image)”Example for section code
Section titled “Example for section code”const {src, alt} = props.image;Type schema for params
Section titled “Type schema for params”type ImageParams = { id: string | number; module?: string;}The code is the actual code that defines your section. Here, you write the markup and any logic you need for the rendering. You also need to define the props again. For example:
<template> <article> <h3>{{ post.title }}</h3> <WYSIWYG :content="post.content"/> <ShareButtons :post="post"/> </article></template>
<script setup>import {defineProps} from 'vue';import WYSIWYG from '~/components/WYSIWYG.vue';import ShareButtons from '~/components/sections/ShareButtons.vue';
const props = defineProps({ post: Object, astro: Object,});</script>Here, there is also the astro property, which gives access to
the global Astro object.
You can also import other sections you have defined, like ShareButtons in this case.
General design rules and recommendations
Section titled “General design rules and recommendations”This section explains which parts of sections/components should be styled. It also lays out some general rules how sections should be styled in the future.
- Properties that are configurable through “Style” attributes should, in most cases, not use Tailwind classes. This is because Tailwind classes get tree-shaked, so something like
w-${widthProp}would not work. - Just like Tailwind, for fonts, widths, heights, paddings, margins etc. you should use
remas your unit of choice. There are exceptions, for example border widths or values that refer to breakpoints. - Make sure that, when changing a section and its props, fallbacks are always in place so that existing websites still look the same or at least similar after deployment.
- Prevent usage of the
<img>tag, instead use ourImagecomponent. - Prevent usage of the style rule “background-image”, use our
Imagecomponent instead. TheImagecan be madeposition: absolute; object-fit: coverand the wrapper elementposition: relativeto achieve the same effect. Reason is that Astro optimizes these images and usessrcsetfor optimal performance. - Prevent usage of fixed colors, like
bg-whiteortext-black. You should preferably use the colors provided by the theme, e.g.text-primary-contrast,bg-pageetc. - Prevent usage of arbitrary Tailwind classes (something like
border-[#ffffff29]). - When extracting a component and you use a top-level
await, preferably wrap this component in aSuspensein the parent component, even if your component has noclient_directiveset and Page Depot is rendering everything correctly. This is useful for other developers, so that they are aware that this is an async component.
Common problems
Section titled “Common problems”My Image, Icon etc. component is not showing up!
Section titled “My Image, Icon etc. component is not showing up!”In sections that aren’t rendered on the server (i.e. that have a client_directive set), components are rendered on the client side. However, some sections load data asynchronously. This is indicated by them using the await keyword on the top level.
Solution: Wrap the component usage in a suspense