Statamic Google-Ads pages comparison

Statamic Google-Ads pages comparison

This is a comparison between my Statamic project and the one that Manuel and Cedric did which is live. For simplicity’s sake i will reference them as “my project” and “live project”.

Statamic Comparison of the Live Statamic Project and My Project

Overall architecture

Both projects follow the same core architecture. They use a Replicator to build pages from independent content sections and separate page content, reusable offers, blueprints, fieldsets, and frontend templates. Both also keep offers in their own collection instead of embedding product information directly into the landing page, and each section is rendered through its own Antlers partial.

The main difference is that the Live project uses a generic Page blueprint with a flexible page builder, making it reusable for different landing pages. My project uses a dedicated Webhosting blueprint with a fixed set of section types, making it more specific to a single landing page.

Page sections

My project provides six predefined section types:

  • Information
  • Company
  • Selected Offers
  • Trust Reason
  • Contact
  • Comments

The Live project provides a much larger collection of reusable builder blocks:

  • Hero
  • Certificate
  • Plans Table
  • Feature Grid
  • Standalone CTA
  • Split Section
  • Testimonials
  • Logo Cloud
  • Support Card
  • FAQ
  • Spacer

Because of this, the Live project can build much more complex landing pages without introducing additional blueprints.

CTA implementation

My project stores CTA fields directly inside multiple sections, usually as separate fields for the button label and destination link. These fields are duplicated across sections such as Information, Trust Reason, Contact, and Offers.

The Live project extracts the common button fields into a reusable CTA fieldset. This fieldset is reused by multiple builder components, while individual components can extend it with additional options such as button size, visual variants, icons, or descriptions. This reduces duplicated field definitions while remaining flexible.

Features

The two projects model features differently.

My project imports a reusable Features fieldset, which contains repeatable feature items along with layout and styling options.

The Live project does not use a separate Features fieldset. Instead, the Feature Grid builder defines its own feature structure directly within the builder. Each feature contains its own title, description, and icon, making the entire structure self-contained.

Testimonials / Comments

The testimonial sections are conceptually very similar in both projects. Both store review text, star ratings, reviewer information, and profile images before rendering responsive testimonial cards.

The main structural difference is how reviewer information is organised.

My project stores the reviewer name, profile image, star rating, and comment together inside each testimonial entry.

The Live project separates the reviewer information into a dedicated author group, keeping author metadata separate from the testimonial content.

Company / Certificate section

Both projects include a section dedicated to trust signals such as star ratings, reviewer information, and certification imagery.

My project stores the star rating and reviewer links together through the shared Stars fieldset.

The Live project separates these responsibilities. The rating is stored through a reusable Rating fieldset, while tester or reviewer links are stored in their own repeatable Grid. This creates a clearer separation between the rating itself and the reviewer data.

Offer implementation

Both projects separate product information into a dedicated Offers collection.

My project stores offer features as Markdown alongside pricing, discount information, currency, duration, and CTA fields.

The Live project organises offer data into logical groups. Pricing is stored in a Billing Information group, the CTA is stored in its own group, and product features are stored as a structured Grid containing a value and description for each feature. This creates a more structured data model and makes feature information easier to display consistently.

Offer selection

Both projects allow landing pages to display products from the Offers collection, but they differ in how products are selected.

My project provides an interface for selecting specific offers, but the frontend ignores those selections and instead displays all available offers sorted by price.

The Live project uses an Entries field that respects both the selected offers and the order chosen by the editor, giving complete editorial control over which products appear on the page.

Fieldsets

Both projects make use of reusable fieldsets, although they focus on different areas.

My project includes reusable fieldsets for:

  • Features
  • Stars
  • Contact Card
  • Support Card

The Features fieldset is reused across multiple landing pages.

The Live project keeps its fieldsets smaller and more focused by primarily reusing:

  • CTA Button
  • Rating Stars

Rather than extracting larger page structures into fieldsets, the Live project defines more complex content directly inside builder components.

Support section

My project imports its contact content from a reusable Contact Card fieldset. A wrapper template applies page-specific styling while the content remains fully editable through the CMS.

The Live project includes a Support Card builder that contains no editable fields. The text, checklist, images, and button are hardcoded inside the template, allowing editors only to control where the component appears within the page.

FAQ

My project does not include a dedicated FAQ section.

The Live project introduces a dedicated FAQ builder containing editable questions and Markdown answers. Accordion behaviour is handled through Livewire, allowing questions to expand and collapse without requiring a page reload.

Layout and rendering

Both projects render pages dynamically using Replicator content and Antlers partials.

My project renders the page in two passes, first displaying the dark sections and then rendering the remaining light sections before loading the appropriate partial based on the Replicator type.

The Live project loops through a generic page builder and dispatches each builder block directly to its corresponding component. This creates a more reusable rendering pipeline that can easily support additional builder components.

Notable implementation differences

Some additional implementation differences include:

  • My project stores offer features as Markdown, while the Live project stores them as a structured Grid.
  • My project uses a reusable Features fieldset, while the Live project defines feature structures directly within the Feature Grid builder.
  • The Live project introduces a reusable CTA fieldset instead of duplicating CTA fields across multiple sections as My project does.
  • The Live project groups reviewer information separately from testimonial content, whereas My project stores all reviewer data directly inside each testimonial.
  • The Live project respects manually selected and ordered offers, whereas My project automatically displays all available offers sorted by price.
  • The Live project introduces Livewire to provide interactive FAQ functionality, while My project does not include a dedicated FAQ section.
  • The Live project is centred around a reusable page builder capable of supporting multiple landing pages, whereas My project is more closely tailored to a specific Google Ads Webhosting page.

Code Comparison of the Live Statamic Project and My Project

Overall architecture

Both projects follow the same general concept. A Statamic entry acts as the landing page, while a Replicator determines which sections are rendered. Each section is displayed through its own Antlers partial, meaning the page itself primarily controls composition while the individual partials handle presentation.

The primary architectural difference is how the page is rendered.

The Live project uses a generic builder Replicator inside a reusable Page blueprint. The main layout loops through every builder block and explicitly checks its type before rendering the matching component.

PHP
{{ builder }}
    {{ if type == "hero_section" }}
        {{ partial:components/builder/hero_section }}
    {{ /if }}

    {{ if type == "plans_table" }}
        {{ partial:components/builder/plans_table }}
    {{ /if }}
{{ /builder }}

Because the builder itself determines the page structure, sections are rendered exactly in the order stored within the Control Panel.

My project instead stores its content inside the page_sections Replicator. Rather than checking every possible section type individually, it dynamically loads the matching partial using the Replicator’s type.

PHP
{{ partial src="sections/google_ads/webhosting/{type}" }}

This naming convention keeps the page template much smaller, since adding a new section only requires creating a matching partial.

Another important difference is that My project renders the page in two separate passes:

  1. Information, Company, and Selected Offers
  2. All remaining sections

Although editors can reorder sections inside each group, these two rendering passes always place the first three section types above the remaining ones. The Live project does not have this limitation because it renders sections directly from the stored builder order.

Layout and builder dispatch

Both projects rely on Antlers partials to render individual sections, but they dispatch those sections differently.

The Live project

The layout acts as the central dispatcher. Every builder type is checked individually before loading the corresponding partial.

PHP
{{ if type == "hero_section" }}
    {{ partial:components/builder/hero_section }}
{{ /if }}

{{ if type == "plans_table" }}
    {{ partial:components/builder/plans_table }}
{{ /if }}

This makes every supported builder block explicit within the layout. Adding a completely new builder type requires updating both the blueprint and the layout to recognise the new block.

Unknown builder types simply render nothing.

My project

My project uses a dynamic partial path instead.

PHP
{{ partial src="sections/google_ads/webhosting/{type}" }}

As long as a Replicator set has a corresponding Antlers partial with the same name, Statamic automatically loads the correct template. This approach removes the need to maintain multiple conditional statements inside the page template.

Enabled state and ordering

Both projects rely on Statamic’s built-in Replicator ordering and enabled state.

Neither project performs additional sorting on builder sections or nested Replicators. Instead, items are rendered in the same order that editors arrange them inside the Control Panel.

The main difference is how the page itself is processed.

The Live project preserves the exact order of every builder block because it loops directly over the stored builder field.

My project preserves the order only within its two rendering groups, since the template intentionally separates the hero area from the remaining content before rendering.

Asset handling

Both projects make extensive use of Statamic asset fields but retrieve image URLs differently.

The Live project

The Live project primarily relies on Statamic’s asset augmentation. Printing an asset field automatically resolves the asset URL, while additional metadata is accessed using sub-properties.

PHP
<img src="{{ right:image }}" alt="{{ right:image:alt }}">

For multiple assets, each item exposes its own URL and alt text.

PHP
{{ logos }}
    <img src="{{ url }}" alt="{{ alt }}">
{{ /logos }}

This makes the templates relatively compact because the augmentation process automatically resolves the required asset information.

My project

My project instead relies heavily on Glide when rendering images.

PHP
{{ if certificates }}
    <img src="{{ glide:certificates }}" alt="{{ certificates:alt }}">
{{ /if }}

Using Glide allows Statamic to generate processed image URLs while still exposing asset metadata through the normal asset field.

Both approaches achieve similar results, although the Live project generally outputs augmented asset URLs directly, whereas My project explicitly processes many images through Glide before rendering them.

In both projects, decorative assets such as blur backgrounds remain hardcoded inside the templates rather than being editable through the CMS.

Hero / Information section

The Hero section serves the same overall purpose in both projects but differs significantly in how content is modelled.

Content structure

My project uses a relatively flat structure containing dedicated fields for:

  • Headline
  • Subheadline
  • Bullet points
  • Offer price
  • Special offer text
  • CTA text
  • CTA link
  • Background image

Bullet points are stored in a Grid.

PHP
{{ bullet_points }}
    <li>{{ text }}</li>
{{ /bullet_points }}

Optional values such as prices and buttons are wrapped in conditional statements before being rendered.

PHP
{{ if offer_price }}
    <p>ab {{ offer_price }} / Monat</p>
{{ /if }}

{{ if cta_text }}
    <a href="{{ cta_link }}">{{ cta_text }}</a>
{{ /if }}

Nested content system

The Live project takes a much more flexible approach.

Instead of storing fixed hero fields, the left side of the Hero contains a nested Replicator called content. Editors can freely arrange different block types, including:

  • Heading
  • Markdown text
  • Checklist
  • CTA button

The template renders different markup depending on each nested block’s type.

PHP
{{ left:content }}
    {{ if type == "heading" }}
        <h2>{{ heading }}</h2>
    {{ /if }}

    {{ if type == "text" }}
        {{ text | markdown }}
    {{ /if }}

    {{ if type == "checklist" }}
        {{ checklist }}
            <strong>{{ label }}</strong> {{ value }}
        {{ /checklist }}
    {{ /if }}
{{ /left:content }}

This makes the Hero considerably more flexible because editors are no longer restricted to a predefined sequence of heading, text, checklist, and button.

CTA implementation inside the Hero

Another implementation difference is how the Hero button is handled.

My project stores the button directly as two fields:

  • cta_text
  • cta_link

The template outputs a standard anchor element whenever button text exists.

PHP
{{ if cta_text }}
    <a href="{{ cta_link }}">{{ cta_text }}</a>
{{ /if }}

The Live project imports the shared CTA fieldset instead. The Hero automatically forces the button to use the shared button component with predefined styling, while optionally displaying an icon and descriptive text underneath the button when a description has been entered.

This keeps Hero buttons visually consistent with buttons used throughout the rest of the project.

Markdown support

The Hero sections also differ in how text content is stored.

My project stores separate headline and subheadline values as plain text.

The Live project stores text blocks as Markdown and converts them during rendering.

PHP
{{ text | markdown }}

This allows editors to apply formatting inside the CMS while keeping the rendering logic relatively simple.

Background imagery

Both projects use editor-selected images for the Hero, but the implementation differs.

My project renders the background image separately from the section itself. The main page template searches for the Information section and places its image inside a shared background layer.

The Live project stores the Hero image directly as part of the Hero builder block, while decorative blur images remain fixed within the template.

This keeps editable content and decorative design assets clearly separated.

Offers implementation

Both projects separate product information into a dedicated Offers collection, preventing pricing and feature information from being duplicated across landing pages. The implementation of the offer data, however, differs considerably.

Offer structure

My project stores offer information in a relatively flat blueprint. Each offer contains fields such as:

  • Offer price
  • Discounted price
  • Discount end date
  • Currency
  • Duration
  • Quote
  • CTA text and link
  • Markdown features

A typical offer is stored as:

Markdown
title: Hosting L
offer_price: '12.90'
discount_offer_price: '9.90'
discount_date: '2026-06-10'
currency: CHF
duration: Mo.
cta_text: Top-Paket wählen
features: |-
  - **150 GB** Speicherplatz
  - **100% SSD** Turbo-Hosting

The Markdown field is converted into HTML, allowing editors to create feature lists using simple Markdown syntax rather than a structured data model.

The Live project groups related values together inside the blueprint.

Offer information is divided into:

  • Billing Information
  • CTA
  • Features Grid

A typical offer is stored like this:

Markdown
title: 'Hosting L'
billing_information:
  regular_price: 12.9
  sale_price: 9.9
  sale_expiration_date: '2026-10-31'
  billing_period: monthly

category: webhosting

Instead of storing features as Markdown, every feature becomes a structured Grid row containing a value and a description. This creates a more structured data model and makes it easier to display individual feature values consistently.

Offer selection

One of the largest implementation differences appears in how landing pages retrieve their offers.

My project

The Webhosting blueprint contains an offers Grid intended to allow editors to select specific products.

However, the frontend ignores those selections completely.

Instead, every published offer is queried directly from the collection.

PHP
{{ collection:offers sort="offer_price:asc" }}
    <h3>{{ title }}</h3>
    <p>{{ offer_price }} {{ currency }} / {{ duration }}</p>
{{ /collection:offers }}

As a result:

  • Every published offer is displayed.
  • Cards are automatically sorted by price.
  • The order chosen inside the editor has no effect.
  • Publishing another Offer automatically adds it to the page.

Because offer_price is stored as text, numeric sorting may become unreliable when prices have different digit lengths.

The Live project

The Live project takes a different approach.

The page stores references to specific Offer entries using an Entries field.

PHP
offers:
  - 03bdd800-57f6-48cd-a2ab-e9469844154f
  - 34fdbb7a-0dac-47c0-9ac6-0f84d7440d70
  - e7ae286f-7ec7-4ad1-b794-4cbfaa7f4a78

The template simply loops over those selected entries.

PHP
{{ offers }}
    ...
{{ /offers }}

This means:

  • Editors choose exactly which offers appear.
  • Editors control the display order.
  • No automatic collection query is performed.
  • No additional sorting logic is required.

This implementation gives complete editorial control over the pricing table.

Discount handling

Both projects support discounted pricing, but the implementation differs slightly.

My project

A card becomes a promotional offer whenever a discounted price exists.

PHP
{{ if discount_offer_price }}
    <p>Aktion bis {{ discount_date format="d.m.Y" }}</p>
    <s>{{ offer_price }}</s>
    <strong>{{ discount_offer_price }}</strong>
{{ else }}
    <strong>{{ offer_price }}</strong>
{{ /if }}

The template formats the promotion banner and crossed-out regular price whenever a discount exists.

The discount end date is only displayed it is not checked to determine whether the promotion has expired.

The Live project

The Live project calculates promotion status slightly differently.

PHP
{{ has_sale = billing_information:sale_price > 0 }}

{{ if has_sale }}
    {{ billing_information:sale_price }}
{{ else }}
    {{ billing_information:regular_price }}
{{ /if }}

Promotion styling depends entirely on whether the sale price is greater than zero.

When a sale exists, the pricing card:

  • Displays a promotion banner.
  • Formats the expiration date.
  • Crosses out the regular price.
  • Switches the CTA to the primary style.

Like My project, the expiration date itself is not validated before displaying the promotion.

Features

The projects model offer features very differently.

My project

Offer features are stored as Markdown.

Markdown
- **150 GB** Speicherplatz
- **100% SSD** Turbo-Hosting

Statamic converts the Markdown into HTML before the template applies styling.

This keeps the blueprint very simple while giving editors some formatting flexibility.

The Live project

The Live project stores every feature as structured data.

Each Grid row contains:

  • value
  • description

The template renders both values independently.

This approach removes the need to parse Markdown and makes individual values much easier to style consistently.

Feature sections

The landing page feature sections also differ considerably.

My project

The Trust Reason section imports the reusable Features fieldset.

Each feature is stored inside a nested Replicator.

PHP
{{ feature }}
    <article>
        <img src="{{ glide:feature_image }}">
        <h3>{{ feature_title }}</h3>
        <p>{{ feature_description }}</p>
    </article>
{{ /feature }}

Although the fieldset provides settings such as:

  • columns_amount
  • feature_background

the Webhosting template currently ignores those values and always renders the same two-column layout.

The Live project

The Feature Grid builder stores features directly inside the builder itself.

PHP
{{ features }}
    <article>
        <img src="{{ image }}" alt="{{ image:alt }}">
        <h3>{{ title }}</h3>
        <p>{{ description }}</p>
    </article>
{{ /features }}

Unlike My project, there is no imported Features fieldset. The builder owns its own data structure, making it self-contained.

The Live project also relies on Statamic’s asset augmentation instead of Glide when rendering feature icons.

CTA implementation

Both projects reuse buttons throughout the site, but they organise them differently.

My project

Most sections define their own CTA fields.

For example:

  • cta_text
  • cta_link

These fields are duplicated across several blueprints and rendered directly within the section templates.

PHP
<a href="{{ cta_link }}">
    {{ cta_text }}
</a>

Because every section owns its own button fields, changing the button structure would require updating multiple blueprints.

The Live project

The Live project centralises button behaviour inside a reusable button component.

Builder blocks import a shared CTA fieldset and pass the values into the component.

PHP
{{ partial:components/button
    :link="link"
    :size="size"
    :variant="variant"
}}
    {{ display_text }}
{{ /partial:components/button }}

The shared component also provides sensible defaults.

PHP
{{ size = size ?? 'md' }}
{{ variant = variant ?? 'primary' }}

<a target="_blank"
   class="{{ classes | trim }}"
   href="{{ link }}">

This allows every CTA throughout the project to share identical rendering logic while still allowing individual builder blocks to customise the button’s appearance through parameters such as size or visual variant.

Another noteworthy difference is that the shared button component always opens links in a new browser tab because target="_blank" is hardcoded into the component.

Pricing card rendering

Although both projects display pricing cards, they generate them differently.

My project primarily renders pricing information directly from individual offer fields, while Markdown generates the feature checklist inside each card.

The Live project relies much more heavily on structured data. Billing information, CTA information, and feature values are each organised into their own logical groups before being combined into the final pricing card.

This results in a more modular implementation where pricing, CTA behaviour, and product features are clearly separated instead of existing as one flat collection of fields.

Contact section vs Support section

One of the largest differences between the two projects is how customer contact is implemented.

My project

My project includes a fully functional Statamic Form inside the Contact section.

The contact section imports a reusable contact_card fieldset and delegates the rendering to a shared partial. The wrapper only provides page-specific presentation settings such as spacing, blur images, and image placement.

PHP
{{ partial:google_ads/contact_card
    contact_section_class="relative px-6 py-12"
    contact_blur_image="/assets/google-ads/webhosting/blur-support@3x.webp"
    contact_image_placement="after_details"
}}

The reusable partial then opens a native Statamic form.

PHP
{{ form:contact in="contact" }}

    {{ if success }}
        <p>Vielen Dank, deine Nachricht wurde gesendet.</p>
    {{ /if }}

    {{ partial:components/contact_form }}

    <button type="submit">
        {{ contact_button_text }}
    </button>

{{ /form:contact }}

Because the form uses Statamic’s built-in form handling, submissions automatically support:

  • Validation
  • Error messages
  • Restoring previously entered values
  • Success messages
  • Email notifications

For example, submitted values are restored after validation errors.

PHP
<input
    name="first_name"
    value="{{ old:first_name }}"
    required
>

Server-side validation is also defined through the form blueprint.

PHP
handle: first_name

field:
  type: text
  validate:
    - required

This creates a fully editable contact section whose functionality is almost entirely driven through Statamic.

The Live project

The Live project approaches customer contact very differently.

Instead of a contact form, it contains a Support Card builder.

Interestingly, the builder itself contains no editable fields.

PHP
support_card:
  display: "Support Card"
  fields: {}

All visible content is hardcoded inside the template:

  • Heading
  • Body text
  • Checklist
  • Staff information
  • Support image
  • Button label
  • Destination

The CTA is simply a predefined external link rendered through the shared button component.

PHP
{{ partial:components/button
    variant="primary"
    size="lg"
    link="https://hosttech.ch"
}}

    Support kontaktieren

{{ /partial:components/button }}

Unlike My project, this section does not submit any data and does not make use of Statamic Forms.

Testimonials / Comments

Both projects implement customer testimonials using nested Replicators, but the data structure differs.

My project

Each testimonial contains:

  • Comment text
  • Star rating
  • Reviewer image
  • Reviewer name

Testimonials are rendered in the same order they appear inside the Replicator.

PHP
{{ comment }}

    <article>

        <p>{{ comment_text }}</p>
        <p>{{ reviewer_name }}</p>

    </article>

{{ /comment }}

The template also contains presentation-specific logic.

For example, the second testimonial receives a different layout position on tablet screens.

PHP
{{ if index == 1 }}
    featured-tablet-position
{{ /if }}

The testimonial heading and decorative quote blur remain hardcoded inside the template.

The Live project

The Live project structures testimonials slightly differently.

Each testimonial consists of:

  • Quote text
  • Rating
  • Author group
    • Name
    • Avatar

Rendering is delegated to the reusable Stars component.

PHP
{{ entries }}

    <p>{{ text }}</p>

    {{ partial:components/stars stars=stars }}

    <img
        src="{{ author:author_avatar }}"
        alt="{{ author:author_avatar:alt }}"
    >

    <p>{{ author:author_name }}</p>

{{ /entries }}

Unlike My project, the Live implementation separates reviewer information into a dedicated author group and reuses a shared Stars component instead of calculating star icons inside every testimonial template.

Rating implementation

Both projects store ratings using a 0–10 scale, where every point represents half a star.

The implementation differs significantly.

My project

The Company section and Comments section both calculate stars directly inside their templates.

PHP
{{ loop from="1" to="5" }}

    {{ if star_amount >= (value * 2) }}

        <i class="fa-solid fa-star"></i>

    {{ elseif star_amount == ((value * 2) - 1) }}

        <i class="fa-solid fa-star-half-stroke"></i>

    {{ else }}

        <i class="fa-regular fa-star"></i>

    {{ /if }}

{{ /loop }}

Each template performs its own conversion from the stored rating into visible star icons.

The Live project

The Live project performs the same calculation using variables.

PHP
{{ rating = stars ?? 0 }}
{{ full = (rating / 2) | floor }}
{{ has_half = rating % 2 == 1 }}
{{ empty = max - full - (has_half ? 1 : 0) }}

However, testimonials do not repeat this calculation.

Instead, they call a reusable component.

PHP
{{ partial:components/stars stars=stars }}

The Certificate block still performs the calculation directly, making it the one exception to this shared approach.

FAQ implementation

This is one of the most significant functional differences between the projects.

My project

My project does not include a dedicated FAQ implementation.

The Live project

The Live project introduces an interactive FAQ builder powered by Livewire.

The layout converts the Replicator entries into JSON before passing them into the Livewire component.

PHP
{{ livewire:faq
    :faqJson="entries | to_json"
}}

The PHP component stores the FAQ entries together with the currently opened question.

PHP
public array $entries = [];

public ?int $openIndex = null;

public function toggle(int $index): void
{
    $this->openIndex =
        ($this->openIndex === $index)
            ? null
            : $index;
}

Each FAQ item then toggles its own visibility.

PHP
<button
    wire:click="toggle({{ id }})"
>

{{ question }}

</button>

Answers are only rendered while their question is open.

PHP
{{ if is_open }}

    <div>
        {{ answer | markdown }}
    </div>

{{ /if }}

This keeps both the FAQ content and the interaction state cleanly separated.

Shared frontend components

The projects differ considerably in how reusable frontend components are organised.

My project

My project primarily reuses:

  • Contact Card partial
  • Contact Form partial

Many other elements, such as star rendering, remain embedded directly inside individual templates.

The Live project

The Live project extracts more functionality into reusable presentation components.

These include:

  • Shared Button component
  • Shared Stars component

Builder sections simply pass data into these shared components rather than duplicating rendering logic.

This reduces duplicated markup while making styling changes easier to maintain.

Asset rendering

Another implementation difference is how images are handled.

My project primarily renders images through Glide.

PHP
{{ glide:feature_image }}

This generates processed image URLs before rendering them.

The Live project relies mostly on Statamic’s asset augmentation.

PHP
<img
    src="{{ image }}"
    alt="{{ image:alt }}"
>

Both methods retrieve asset metadata, although the Live implementation generally produces simpler template code.

Hardcoded vs CMS-managed content

Both projects intentionally leave certain content outside the CMS.

My project

Hardcoded content includes:

  • Decorative blur images
  • Hero labels such as “ab” and “/ Monat”
  • Comments heading
  • Responsive layout decisions
  • Typography
  • Card styling

At the same time, the editable content including contact information and form behaviour is largely managed through Statamic.

The Live project

The Live project also keeps several elements in code, including:

  • Decorative blur images
  • Support Card content
  • FAQ heading
  • FAQ introduction
  • Support links
  • SVG icons
  • Layout styling

The difference is that entire sections, such as the Support Card, are intentionally fixed rather than editor-managed.

Shared implementation behaviour

Despite their differences, both projects share several implementation patterns.

Both:

  • Use Replicators as the primary page-building mechanism.
  • Render nested content in the same order editors define in the Control Panel.
  • Separate blueprints from presentation templates.
  • Keep decorative styling inside Antlers rather than the CMS.
  • Store offers separately from landing pages.
  • Use reusable fieldsets where appropriate.
  • Keep responsive layout decisions inside the templates rather than inside blueprint configuration.

Notable implementation differences

Some additional implementation differences include:

  • The Live project uses a reusable Button component throughout the project, while My project generally renders CTA buttons directly inside section templates.
  • The Live project reuses a shared Stars component for testimonials, whereas My project performs the star calculation inside each relevant template.
  • My project includes a fully functional Statamic Form with validation, submission handling, and email notifications, while the Live project uses a hardcoded Support Card that simply links to an external page.
  • The Live project introduces a Livewire-powered FAQ with interactive expand/collapse behaviour, while My project does not contain a dedicated FAQ implementation.
  • My project relies primarily on Glide when rendering assets, whereas the Live project mainly uses Statamic’s asset augmentation.
  • The Live project extracts more reusable presentation logic into shared frontend components, reducing duplicated markup across builder sections.
  • My project keeps several section-specific implementations, such as testimonial rendering and button generation, directly inside the individual templates rather than centralising them in shared components.

Tags: