Skip to content

Sections

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

Text (text)

{
"type": "text"
}

Number (number)

{
"type": "number"
}

Object (object)

{
"type": "object",
"props": {} // define the object's props here
}

List (list)

{
"type": "list",
"listType": {} // define the list item type here
}

Entity (select)

Usage in props
{
"type": "select",
"options": {
"references": "the_module"
}
}
Type schema for params

An entity object with id.

type EntityParams = {
id: string | number
};

Entities (entities)

Usage in props

An object with optional property module (the module identifier).

{
"type": "entities",
"module": "the_module"
}
Example for section code
const entities = props.entities;
Type schema for params
type EntitiesParams = {
module?: string;
filters?: Array<Record<string, unknown>> | Array<Array<Record<string, unknown>>>;
results?: number;
}

Module (module)

Example for section code
const module = props.module;
module.fields.forEach(field => {
console.log(field);
})
Type schema for params
type ModuleParams = {
identifier: string;
};

Image (image)

Example for section code
const {src, alt} = props.image;
Type schema for params
type ImageParams = {
id: string | number;
module?: string;
}

Code

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

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 rem as 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 our Image component.
  • Prevent usage of the style rule “background-image”, use our Image component instead. The Image can be made position: absolute; object-fit: cover and the wrapper element position: relative to achieve the same effect. Reason is that Astro optimizes these images and uses srcset for optimal performance.
  • Prevent usage of fixed colors, likebg-white or text-black. You should preferably use the colors provided by the theme, e.g. text-primary-contrast, bg-page etc.
  • 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 a Suspense in the parent component, even if your component has no client_directive set 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

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