PageDepot
PageDepot is a service that builds and hosts static sites configured by Brezel.
Installation
Section titled “Installation”-
Install the following prerequisites first:
-
Clone the PageDepot repository:
Terminal window git clone git@gitlab.kiwis-and-brownies.de:kibro/brezelproducts/kab/page-depot.git -
Install dependencies:
Terminal window npm installGo to the
templatesdirectory and install dependencies for each template:Terminal window cd templates/astrowind && npm install -
Fill out your PageDepot
.env:APP_ENV=localDEPOT_SECRET=<choose a secret># WEBSOCKET_PORT=6001# PORT=3000# REDIS_HOST=127.0.0.1# REDIS_PORT=6379REDIS_PASSWORD=<specify the password># Only needed when you want to use ingress management in your Kubernetes cluster:# DEPOT_BASE_DOMAIN=kab.page# DEPOT_INGRESS_NAMESPACE=page-depot# DEPOT_INGRESS_NAME=external-domains# DEPOT_SERVICE_NAME=page-depot# Only needed when you want to use hostnames in your Cloudflare zones:# CLOUDFLARE_ZONE_ID=# CLOUDFLARE_TOKEN=In your Brezel
.env, specify the following environment variables:PAGE_DEPOT_URL: the full URL to the PageDepot service. Usuallyhttps://kab.page.PAGE_DEPOT_WS_HOST: the hostname of the PageDepot websockets service. Usuallyws.kab.page.PAGE_DEPOT_SECRET: the secret used to access the PageDepot service (DEPOT_SECRET).
-
To start the web and websocket servers, run the following inside PageDepot:
Terminal window npm run start
Usage in Brezel
Section titled “Usage in Brezel”You can use PageDepot in Brezel via the action/buildSite
and action/buildSite workflow elements.
For building a site, you need the following modules:
- a templates module with SiteBuilderTemplate and PageDepotTemplate capabilities
- a layouts module with PageDepotLayout capability
- a pages module with PageDepotPage capability
- a sections module with PageDepotSection capability
:::note In KAB Tools, there is also a domains and a posts module. Because domains are just a way to group pages together, they are not needed for PageDepot per se. A similar reason applies to posts. :::
Templates
Section titled “Templates”A template has a name and a base template. It is just a logical entity to specify what base template a layout should use. The actual contents and structures of base templates are not configurable. But choosing the base template has consequences for how to write the code of sections and choosing a **base layout **.
Available base templates in Astro are:
- Astrowind (
astrowind)
Layouts
Section titled “Layouts”A layout has a name, a base layout, scripts and slots. The base layout always refers to a layout file inside the base template. This file is usually an Astro file that defines slots that you can fill. While the layout can fill slots defined by the base layout, the layout can also provide slots to be filled by pages that inherit from it.
Available base layouts are:
Astrowind
Section titled “Astrowind”PageLayout.astro (extends BaseLayout.astro)
Section titled “PageLayout.astro (extends BaseLayout.astro)”Slots: announcements, header, default, footer
This is the recommended base layout.
BaseLayout.astro
Section titled “BaseLayout.astro”Slots: default
MarkdownLayout.astro
Section titled “MarkdownLayout.astro”Slots: default
Pages define what pages of the static site are generated. A page has a name, a layout, slots, parameters as well as a title, description and scripts.
Layout
Section titled “Layout”The layout specifies what layout the page inherits, and thus also what slots the page can fill.
The slots specify the filling of the slots of the parent layout with sections, and what parameters the sections are initialized with.
The slot name defines what slot should be overwritten.
Each slot can have a list of sections.
Each section, in turn, is an object that has a section definition, section parameters, and section subslots.
The section definition is an entity of the module defining the sections (usually called sections).
The Section parameters are the inputs to that section, and correspond to the section entity’s props.
Example section entity “Post”:
{ "id": 10, "name": "Post", "type": "vue", "props": { "post": { "type": "select", "options": { "references": "posts" } } }, "code": "<template><div>{{ post.title }}</div></template><script>export default { props: { post: Object } }</script>"}Example value of a page’s slots where this section entity is used:
[ { "slot": "default", "sections": [ { "section": { "id": 10 }, "params": { "post": { "id": 42 } } } ] }]This means that the default slot in the page’s layout is filled with one section, a “Post”, with its post prop filled
with the post entity 42.
The name defines the route where the page will be accessible.
For example, the name posts will make the page available at https://mysite.kab.page/posts.
The name posts/[lang]/[post] will, for example, make the page available
at https://mysite.kab.page/posts/en/lorem-ipsum, depending on parameters given for [lang] and [post].
Parameters
Section titled “Parameters”What parameter values you can have in your page URL is configured using the parameters. But, because PageDepot uses Astro, and Astro is mainly a static site builder, all possible parameter values must be known at build time. Therefore, Astro needs to be told every combination of parameters that should be possible. Fortunately, you don’t actually need to write every combination down, you can just specify the possible parameter values. PageDepot generates the combinations for Astro when building your site.
Instead, you can add a post parameter and make it refer to the posts module, and say that the parameter value comes
from the slug field.
You can also add a lang parameter for example, where you define the value en, and then add a new entry for lang,
where you define de.
Assuming you have posts with slugs lorem-ipsum, dolor and oppenheimer, the resulting paths would be:
/posts/en/lorem-ipsum/posts/de/lorem-ipsum/posts/en/dolor/posts/de/dolor/posts/en/oppenheimer/posts/de/oppenheimer
However, even moderate amounts of parameters can add up to huge amounts of combinations, so much that even when PageDepot generates them for you, the runtime and memory requirements become too high to handle. In that case, you need server-side rendering (SSR) for your page. This has the benefit of evaluating each parameter when the page is accessed, instead of generating them all in advance. Currently, the SSR feature is under construction.
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.