Skip to content

Sections system¶

The sections system is part of the foundation of the Brekz Website project. It's used a lot throughout the project and thus important to fully understand how it works, which is what this document is about.


TL;DR¶

Since this system can be a bit complex to understand, here are some important takeaways.

Tip

It's still highly recommended to read this entire page at least once to get a better understanding of the system and why it is the way it is.

  • The sections system allows you to partially cache (pre-render) sections of a page, without losing support for dynamic content.
  • A page is divided in 1 or more sections.
    • You have static and dynamic sections.
    • Static sections allow you to render the section beforehand, reducing the request time and server load.
    • Dynamic sections allow you to execute PHP and render dynamic results.
    • Properly dividing the page in sections allows you to have the fastest possible page time, while still allowing for dynamic content.
  • New pages can be made inside Brekz CMS.
    • For a normal page, you can use the contentpage blueprint ("Pagina - Contentpagina" in the Statamic CP).
    • If you want to make multiple pages with the same layout, it's recommended to create a new collection and use section mapping instead.
      • Section mapping is a way to create the sections programmatically inside the blueprint.
      • You can think of this approach like defining a page template, this template will then automatically be applied to each page inside the collection.
  • Brekz Website relies on the URL key-value store to figure out if the page exists.
    • If it exists, it will check if sections for this page exist.
      • If the sections are available, it will use those to assemble the page.
      • If the sections aren't available, it will attempt to "rescue" the request by fetching the entry data from Brekz CMS and rendering the sections immediately on the Website (Also known as on-demand sections).
        • If this succeeds, the user's request should complete normally, just slower than usual.
        • If this fails, the request will fail with a 404 error code.
    • If something fails with the section system during a request (ContentController.php), you can check the X-DCL-FAIL (stands for: Dynamic Content Load failure) response header for the failure code.

What is the sections system?¶

The sections system is responsible for building the webpage the user sees, but in a faster way. The sections system allows us to cache (also called pre-rendering) specific parts of the page, without having to rely on full page caching solutions like Cloudflare for speed.


Why the sections system?¶

It allows us to have faster response times, without having the limitation of not being able to have dynamic content provided by the server.

It's of course possible to work around the dynamic content issue with full page caching by relying on API calls, but this will require the client to wait for another request before parts of the page are ready. With the sections system, the dynamic content is already processed inside the initial page request, making it immediately available for the client.


What type of sections are there and when do you use them?¶

There are 2 section types, static and dynamic.

It's possible to use each section type multiple times on a page, allowing you to put dynamic content between static content if needed.

By properly using these section types, you can achieve the best page performance, without losing the support for dynamic content or having to do an API request as soon as the page loads.

Static 📄¶

The static section type means the content doesn't have any dynamic parts and can be safely pre-rendered to save time during the request.

Dynamic Javascript content

Please note that when we talk about dynamic parts here, we mean dynamic parts handled by the server, not the client.

It's still possible to have some dynamic content inside a static section, for example a VueJS component that calls an API during runtime.

Example use case

You can use the static section type for the PDP to show the product name, images and description, as those will be the same for each user.

This allows you to fetch the data and render it beforehand, removing the requirement to do this for each request to this page, reducing the request time and server load.

Creating a custom static component¶

Static components are rendered by Brekz Website using Blade templates. Adding a new component requires two steps: creating the template and registering it.

Step 1 — Create the Blade template Create a new Blade file inside the appropriate subdirectory of app/Services/PrerenderedSectionsLoader/Views/Static/Components/Custom/ in Brekz Website.

Why the Custom directory?

All the components we (Flooris) made should be stored there.

The only non-custom components we have, are basic components that are default Statamic components. Think about thinks like headings, paragraphs, images, etc...

The subdirectories are organized by category, for example:

Directory Purpose
Breadcrumbs/ Breadcrumb navigation components
Category/ Category page specific components
Grids/ Grid and layout components
Marketing/ General marketing/content components
Pdp/ Product detail page specific components
Technical/ Non-visual technical components (meta tags, GTM events, Vue component loader, ...)

Your template receives the component's configuration via the $attrs variable. Use @props(['attrs' => []]) at the top of your template.

Example Blade template
@props(['attrs' => []])
@php
    // We assign it to variables in this way so we can also set a default value in case that attribute isn't set
    // It's important to do this, as otherwise we might run into runtime errors about missing variables
    $title = $attrs['title'] ?? '';
    $body  = $attrs['body'] ?? '';
@endphp

@if(!empty($title))
<section class="py-8 px-4">
    <h2 class="text-2xl font-bold">{{ $title }}</h2>
    @if(!empty($body))
        <p class="mt-2">{{ $body }}</p>
    @endif
</section>
@endif

Step 2 — Register the component Add your component to the $STATIC_CONTENT_TEMPLATES array in PrerenderedSectionsLoader.php, so the render system is aware of your component. The key is the component type name (as used in the blueprint or CMS), and the value is the path to the Blade file relative to the PrerenderedSectionsLoader class.

To make it easier to find components, we recommend grouping them by what sort of component it is. For example if you have a marketing related component, store it in the marketing directory and register it in the same "block" of code as the other marketing components.

private static array $STATIC_CONTENT_TEMPLATES = [
    // ...
    // Custom components (marketing)
    'my_new_component' => '/Views/Static/Components/Custom/Marketing/my_new_component.blade.php',
    // ...
];

Step 3 (optional) — Register the component in the Statamic editor If you also want content editors to be able to use the component from the Statamic Control Panel (rather than only via section mapping in a blueprint), add a set definition for it in the resources/fieldsets/sections/static.yaml fieldset in Brekz CMS.

Info

This step only affects the Statamic editor UI. The Website rendering is driven entirely by the $STATIC_CONTENT_TEMPLATES registration — not by anything in CMS.

Never edit static.yaml through the Statamic Control Panel

The static.yaml fieldset uses YAML anchors to share component definitions across multiple places (for example, making every component available inside column_grid without having to list them all manually).

The Statamic Control Panel does not understand YAML anchors and will silently expand or strip them when it saves the file. This permanently destroys the anchor structure and makes the fieldset much harder to maintain going forward.

Always edit static.yaml directly in a code editor (e.g. via the repository), never through the Statamic UI.

What are YAML anchors?¶

YAML anchors let you define a block of content once and reuse it elsewhere in the same file, without copy-pasting. In static.yaml this is used to automatically make every component available inside container components like column_grid.

# Define the anchor — every set listed here is "recorded"
sets: &bard_recursive_safe_sets
  my_new_component:
    display: My new component
    fields:
      - handle: title
        field:
          type: text

# Reuse the anchor — column_grid automatically gets all the same sets
column_grid:
  display: Column grid
  fields:
    - handle: columns
      field:
        type: replicator
        sets:
          <<: *bard_recursive_safe_sets  # expands to all sets defined above

Tip

If you aren't familiar with YAML anchors, this article by Atlassian explains them well.

Infinite recursion loop

Certain components are not safe to include inside the recursive anchor because Statamic's Antlers template engine can get confused resolving variables and jump to the root of the entry, causing an infinite render loop.

If your component is susceptible to this, define it outside the &bard_recursive_safe_sets anchor so it is not pulled into recursive containers like column_grid.

Dynamic ⚡¶

The dynamic section type means the content has dynamic parts and thus can't be rendered beforehand, it will need to be rendered again for each request.

Dynamic sections have the ability to execute PHP code and render content (returned as a string containing HTML code).

A component inside a dynamic section is called dynamic content, which is handled by a dynamic content handler. These are stored inside the app/Services/PrerenderedSectionsLoader/Views/Dynamic directory in Brekz Website.

Example use case

You can use the dynamic section type on the PDP for providing an accurate delivery estimate, without having to deal with the client's time zone or duplicating this logic for the back-end and front-end.

Since it's executed for each request, it should always be up-to-date with the latest estimation.

Creating dynamic content handlers¶

To add a new dynamic content handler, create a new PHP class inside the app/Services/PrerenderedSectionsLoader/Views/Dynamic directory in Brekz Website.

This class needs to implement the IDynamicContentHandler interface, this will tell you what you have to implement. The interface also includes some PHPDoc, which can help you understand what each function should do and return.

The definition of the dynamic content inside the section is available via $this->content. This allows you to pass configurations or other data to your dynamic content handler.

When your dynamic content handler has been made, you will have to register your handler in PrerenderedSectionsLoader. This is done by simply adding your class to the $DYNAMIC_CONTENT_HANDLERS array as a ::class.

It should now automatically call your handler's render function when your matches function returns true.

Example content handler

In this example we will create a CurrentTimeHandler that is triggered by the current_time content type.

You are able to configure the output format by defining format inside the attrs section of your content.

<?php

namespace App\Services\PrerenderedSectionsLoader\Views\Dynamic;

use Carbon\Carbon;

class CurrentTimeHandler implements IDynamicContentHandler
{
    private array $content;

    public static function matches(string $contentType): bool
    {
        return $contentType === 'current_time';
    }

    public function setContent(array $content): void
    {
        $this->content = $content;
    }

    public function getContent(): array
    {
        return $this->content;
    }

    public function render(): string
    {
        $formattedTime = Carbon::now()->format($this->content['attrs']['format']);

        return "<section class=\"flex w-full my-4\"><div class=\"px-4 py-2 bg-red-100 mx-auto rounded-md\"><p>PHP told me the time is currently <strong>{$formattedTime}</strong>.</p></div></section>";
    }
}

Then register our dynamic content handler in PrerenderedSectionsLoader by adding it to the $DYNAMIC_CONTENT_HANDLERS array.

<?php

namespace App\Services\PrerenderedSectionsLoader;

class PrerenderedSectionsLoader
{
    private static array $DYNAMIC_CONTENT_HANDLERS = [
        \App\Services\PrerenderedSectionsLoader\Views\Dynamic\CurrentTimeHandler::class,
        // ...
    ];

    // ...
}

We are now able to use this type on our pages.

---
title: Example page
blueprint: contentpage
sections:
  -
    enabled: true
    type: dynamic
    content:
      -
        type: "current_time",
        attrs:
          format: "Y-m-d H:i:s"

If you also want to make it accessible in the Statamic control panel, simply create a fieldset definition for your component in the resources/fieldsets/sections/dynamic.yaml fieldset in Brekz CMS.

main:
  display: Main
  sets:
    # ...
    current_time:
      display: "Current time (EXAMPLE)"
      icon: time-clock
      fields:
        - handle: format
          field:
            type: text
            display: 'Date format'
            instructions: 'Define the format as a PHP date format, see https://www.php.net/manual/en/function.date.php#example-3'
            placeholder: 'Y-m-d H:i:s'
            localizable: false
            validate:
              - required
    # ...

How does it work when looking at it from a page perspective?¶

In the following example, you see a page that has static content, but with some dynamic content in between. This allows you to better see the advantage of the sections system.

Brekz Search products Static section Dynamic section Static section

Note that if you don't need any dynamic content on that page, it's perfectly acceptable to have only 1 static section. You can use as many (or little) sections as you want.


How can I create a page using the sections system?¶

New pages can easily be created and managed inside Brekz CMS. Here you can use Statamic's bard component to use almost any component that is available in Brekz to build new pages.

You should always register new pages in CMS... right?

While you should always prefer creating new pages in CMS, sometimes it really doesn't make sense as the page is just too technical (Example: My account) or you are sure it will never be changed by Brekz.

In this case you can simply use the normal Laravel way to create a new route and view. Just make sure to register this route before the catch all at the bottom of the routes file, otherwise the request will never reach your custom route.

Please note that certain tools might not be available in manually created routes, like the CMS integration and sections system.

Regular page (CMS)¶

If you just want to create a regular page, simply create a new entry in the "Pages" collection in CMS using the contentpage blueprint. In the Statamic Control Panel it's shown as "Pagina - Contentpagina".

It will ask you to input a title for the page, and then you see a replicator for the sections. When you add a new section, it will ask you what section type you want, static or dynamic.

Inside each section here will be a large bard input field. In here you can simply start typing and using formatting as you would expect from a WYSIWYG editor, all the options shown at the top should be available.

But unlike a regular WYSIWYG editor, you can also add more complex components by clicking on the "+" symbol at the left. This allows you to insert a component that is made available by us.

For example, you can insert an image slider and select the images you want to add. When you then visit the page, it will look and feel exactly the same as other images sliders on the website.

Pages with reoccurring layout (Section mapping)¶

If you have a set of pages that all need to have the same layout, you can create a new Statamic collection and use the section mapping approach instead.

With the section mapping approach, you only have to define the sections once in the blueprint, and it will automatically apply this to all the pages inside the collection. Think of it like defining a template for the page itself, it then grabs information from the entry and fill it in on the page using your template.

This approach has been done for the PDP's and PLP's, since these should all have the same layout, but just with different content inside of them.

Section mapping to rendered page visual¶

Here is a visual how the section mapping on your blueprint can grab values from your Statamic entry, convert it into resolved sections which can then be used to render the page.

The section mapping inside the blueprint will be reused for every entry that uses that blueprint. This allows you to apply the same layout to an entire collection, without having to update every single entry of that collection by hand every time you change something.

Statamic Entry contentpage blueprint name "Hondenvoer Premium" description "Een top product voor honden" related_products [42, 57, 103] · · · other blueprint fields Blueprint · sections_mapping section 1 · static heading "Product name" text field:name section 2 · static heading "Description" set field:description set vue_component: RelatedProducts :product-ids: field:related_products Resolved Sections section 1 · static heading "Product name" text Hondenvoer Premium section 2 · static heading "Description" set Een top product voor honden set vue_component: RelatedProducts :product-ids: [42, 57, 103] Rendered Page SECTION 1 Product name Hondenvoer Premium SECTION 2 Description Een top product voor honden <related-products :product-ids="[42,57,103]" /> field binding resolves to Blade renders

Re-rendering the collection

If you changed something in the section mapping, don't forget to re-render every page that uses it.

You can do this in bulk using the php artisan prerendered-sections:render-collection command.

Otherwise you won't see your change, unless you have force page rendering enabled. (Development environment)

Special value prefixes¶

Inside a section mapping you can use special prefixes to resolve values dynamically at render time:

Prefix Example Description
field: field:description Reads the value of a field from the CMS entry
trans: trans:some.translation.key Resolves a Laravel translation key

Example blueprints¶

Basic section mapping example

In this example we will just create a simple page with some text. In this case we have 3 sections, all of them are static for simplicity.

A section can have multiple components to render, in this case the second section has 2 text fields it should render in that section. Each section will be cached separately, so in this case it will cache 3 items. But since they are all static, you could also just combine all of them into 1 larger section.

tabs:
  # We don't use any tabs or fields in this blueprint in this example, so just ignore this section ;)
sections_mapping:
  -
    type: static
    content:
      -
        mapped_type: 'text'
        text: 'This is some example text in the first section'
  -
    type: static
    content:
      -
        mapped_type: 'text'
        text: 'How about some more text?'
      -
        mapped_type: 'text'
        text: 'The twist here is that it is inside another section 👀'
      -
  -
    type: static
    content:
      -
        mapped_type: 'text'
        text: 'Use as many as you need!'
      -
        mapped_type: 'paragraph'
        content:
          -
            type: text
            text: 'You can also put some'
          -
            type: text
            marks:
              -
                type: bold
            text: 'oompf'
          -
            type: text
            text: 'in your text with marks, the same way as you would in Statamic's'
          -
            type: text
            marks:
              -
                type: link
                attrs:
                  href: 'https://prosemirror.net/'
                  rel: 'noopener noreferrer'
                  target: _blank
                  title: 'Prosemirror homepage'
              -
                type: underline
            text: 'Prosemirror'
          -
            type: text
            text: 'editor.'
Using data from the entry

In this example we will be creating a blueprint that stores name as text and description as a bard (similar to a WYSIWYG editor). The values of these fields will then be used in the sections mapping to automatically output it to the page.

The expected output on the page should be 2 headings, 1 heading with "Product name" and one with "Product description". Below these headings should be the value that you entered in the entry.

The way the sections system detects it should grab a value from the entry, is if the value is prefixed with field:. If it sees that value, it will grab the value after the : and use that as the key to search for inside the entry.

So for example field:description will cause the section system to search for the value of description inside the entry, and then inserts the value of description in your section.

tabs:
  main:
    display: Main
    sections:
      -
        fields:
          -
            handle: name
            field:
              type: text
              required: true
              localizable: false
              display: Name
              visibility: read_only
          -
            handle: description
            field:
              remove_empty_nodes: false
              type: bard
              display: Description
              localizable: false
sections_mapping:
  -
    type: static
    content:
      -
        mapped_type: heading
        attrs:
          level: 2
        content:
          -
            type: text
            text: 'Product name'
      -
        mapped_type: text
        text: 'field:name' # This will become the value of field "name"
      -
        mapped_type: heading
        attrs:
          level: 2
        content:
          -
            type: text
            text: 'Product description'
      -
        mapped_type: set
        is-prose: true              # If this is set to true, it will apply some default styling to make CMS content look better, should be disabled for non-CMS content
        values: 'field:description' # This will become the value of field "description"
Calling a Vue component

One of the more "advanced" components that is available, is our custom vue_component component. This allows you to tell to the sections system that you want to load a specific Vue component here, in this example we want to load the SearchWrapperCategory Vue component.

You can also provide props if your component needs them, and just like before, you can prefix them with field: if you want to grab a specific value from the entry itself.

If you want your value to be passed as a dynamic prop, just add : to the key of the prop, the same as you would also do in VueJS.

tabs:
  main:
    display: Main
    sections:
      -
        fields:
          -
            handle: search_category_id
            field:
              type: text
              localizable: false
              display: 'Category ID (search)'
              instructions: 'Category ID for filtering products'
sections_mapping:
  -
    type: static
    content:
      -
        mapped_type: set
        values:
          - type: vue_component
            component: SearchWrapperCategory
            props:
              "lang-iso": 'nl-NL' # A hardcoded static prop
              ":category-filters": '[]' # A hardcoded dynamic prop
              ":category-id": 'field:search_category_id' # A dynamic prop filled by our entry

Artisan commands¶

Brekz Website provides Artisan commands to pre-render sections directly, without waiting for a user request to trigger on-demand rendering or forcing a page to be re-rendered.

prerendered-sections:render¶

Renders and stores the sections for a single page.

php artisan prerendered-sections:render {site} {pageType} {slug}
Argument Description
site The Statamic site handle (e.g. nl)
pageType The page type value from PageTypeEnum (e.g. pages, pdp, plp, meta, category_pages)
slug The URL slug of the page
Example command
php artisan prerendered-sections:render nl pages homepage

prerendered-sections:render-collection¶

Renders and stores the sections for all entries in a given page type's collection.

php artisan prerendered-sections:render-collection {site} {pageType} [--continue-on-error]
Argument / Option Description
site The Statamic site handle (e.g. nl)
pageType The page type value from PageTypeEnum
--continue-on-error Skip failed entries and continue, instead of aborting on the first error
Example command
php artisan prerendered-sections:render-collection nl pdp --continue-on-error

Diagrams¶

To explain the more technical side of this system, a couple of diagrams have been provided that can assist in understanding the system.

Flowchart¶

In this flowchart you can see how a page render is executed.

Show diagram
---
config:
    theme: redux
    flowchart:
        curve: bumpY
---
flowchart TD
    INCOMING_REQUEST(("Incoming request"))


    INCOMING_REQUEST --> CHOICE_SLUG_IN_KEY_VALUE_STORE

    CHOICE_SLUG_IN_KEY_VALUE_STORE{"Is the URL slug in the key-value store?"}
    CHOICE_SLUG_IN_KEY_VALUE_STORE -->|"Yes"| CHOICE_DO_WE_UNDERSTAND_THE_PAGE_TYPE
    CHOICE_SLUG_IN_KEY_VALUE_STORE -->|"No"| ABORT_REQUEST

    CHOICE_DO_WE_UNDERSTAND_THE_PAGE_TYPE{"Do we understand this page type?"}
    CHOICE_DO_WE_UNDERSTAND_THE_PAGE_TYPE -->|"Yes"| CHOICE_DO_WE_HAVE_THE_PAGE_SECTIONS
    CHOICE_DO_WE_UNDERSTAND_THE_PAGE_TYPE -->|"No"| ABORT_REQUEST

    CHOICE_DO_WE_HAVE_THE_PAGE_SECTIONS{"Do we have the sections for this page?"}
    CHOICE_DO_WE_HAVE_THE_PAGE_SECTIONS -->|"Yes"| LOAD_AND_RENDER_SECTIONS
    CHOICE_DO_WE_HAVE_THE_PAGE_SECTIONS -->|"No"| CHOICE_DID_WE_ALREADY_REQUEST_SECTIONS_IN_PREVIOUS_ATTEMPT

    CHOICE_DID_WE_ALREADY_REQUEST_SECTIONS_IN_PREVIOUS_ATTEMPT{"Did we already request on-demand sections in the previous attempt?"}
    CHOICE_DID_WE_ALREADY_REQUEST_SECTIONS_IN_PREVIOUS_ATTEMPT -->|"Yes"| ABORT_REQUEST
    CHOICE_DID_WE_ALREADY_REQUEST_SECTIONS_IN_PREVIOUS_ATTEMPT -->|"No"| RENDER_ON_DEMAND_SECTIONS

    RENDER_ON_DEMAND_SECTIONS("Fetch entry data from CMS and render sections on Website")
    RENDER_ON_DEMAND_SECTIONS --> CHOICE_DID_WE_RECEIVE_PAGE_SECTIONS

    CHOICE_DID_WE_RECEIVE_PAGE_SECTIONS{"Were the sections successfully rendered?"}
    CHOICE_DID_WE_RECEIVE_PAGE_SECTIONS -->|"Yes"| RETRY_REQUEST
    CHOICE_DID_WE_RECEIVE_PAGE_SECTIONS -->|"No"| ABORT_REQUEST

    LOAD_AND_RENDER_SECTIONS("Load pre-rendered sections and execute dynamic sections")
    LOAD_AND_RENDER_SECTIONS ---> FINISH_REQUEST


    subgraph FLOW_CHART_END_ALIGNMENT[" "]
        direction LR
        style FLOW_CHART_END_ALIGNMENT fill:transparent,stroke:transparent

        FINISH_REQUEST((("Return completed page")))
        RETRY_REQUEST((("Retry the request")))
        ABORT_REQUEST((("Abort request")))
    end

Sequence diagram¶

In these diagrams you can see a couple of situations and how they interact with other services.

Show diagram (Unsuccessful flow, URL slug not in key-value store)
sequenceDiagram
    participant Client as Client
    participant BrekzWebsite as Brekz Website
    participant BrekzCMS as Brekz CMS
    participant Filesystem as Filesystem

    Client->>+BrekzWebsite: Page request

    BrekzWebsite->>+Filesystem: Read key-value store
    Filesystem-->>-BrekzWebsite: Key-value store

    BrekzWebsite-->>-Client: Return 404 page
Show diagram (Unsuccessful flow, Unknown page type)
sequenceDiagram
    participant Client as Client
    participant BrekzWebsite as Brekz Website
    participant BrekzCMS as Brekz CMS
    participant Filesystem as Filesystem

    Client->>+BrekzWebsite: Page request

    BrekzWebsite->>+Filesystem: Read key-value store
    Filesystem-->>-BrekzWebsite: Key-value store

    BrekzWebsite-->>-Client: Return 404 page
Show diagram (Successful flow, sections already available)
sequenceDiagram
    participant Client as Client
    participant BrekzWebsite as Brekz Website
    participant BrekzCMS as Brekz CMS
    participant Filesystem as Filesystem

    Client->>+BrekzWebsite: Page request

    BrekzWebsite->>+Filesystem: Read key-value store
    Filesystem-->>-BrekzWebsite: Key-value store

    BrekzWebsite->>+Filesystem: Glob JSON/HTML sections directory for slug
    Filesystem-->>-BrekzWebsite: List of JSON/HTML file paths

    loop For each section
        BrekzWebsite->>+Filesystem: Read JSON/HTML file contents
        Filesystem-->>-BrekzWebsite: JSON/HTML file contents
        BrekzWebsite->>BrekzWebsite: Execute / append section
    end

    BrekzWebsite->>BrekzWebsite: Insert sections in page template

    BrekzWebsite-->>-Client: Return complete page
Show diagram (Successful flow, sections not already available, required on-demand rendering)
sequenceDiagram
    participant Client as Client
    participant BrekzWebsite as Brekz Website
    participant BrekzCMS as Brekz CMS
    participant Filesystem as Filesystem

    Client->>+BrekzWebsite: Page request

    BrekzWebsite->>+Filesystem: Read key-value store
    Filesystem-->>-BrekzWebsite: Key-value store

    BrekzWebsite->>+Filesystem: Glob JSON/HTML sections directory for slug
    Filesystem-->>-BrekzWebsite: List of JSON/HTML file paths (Empty)

    BrekzWebsite->>+BrekzCMS: Request entry data and blueprint for slug
    BrekzCMS-->>-BrekzWebsite: Entry data and blueprint

    loop For each section
        BrekzWebsite->>BrekzWebsite: Render section using Blade templates
        BrekzWebsite->>Filesystem: Write rendered section (HTML/JSON)
    end

    BrekzWebsite-->>-Client: Return redirect to same page (retry)