Step-by-Step Guide: Dynamically Displaying Hero Quotes with Statamic and Alpine.js
In this blog post, we’ll walk through how to dynamically display content from a collection in Statamic using Alpine.js for front-end interactivity. Specifically, we’ll focus on displaying hero quotes with randomization, and we'll leverage Tailwind CSS for styling along the way. If you're looking to combine dynamic content fetching, randomization, and responsive design, this step-by-step breakdown will give you all the tools you need to achieve it. Let’s dive in!
Prerequisites:
Before we get started, make sure you have basic knowledge of:
- Using Statamic CMS
- HTML and basic templating with Antlers
- Tailwind CSS for layout and styling (optional but very helpful)
- Alpine.js for lightweight JavaScript-driven interactivity
Step 1: Setting Up Statamic and the heros
Collection
To begin, we need a collection in Statamic named heros
to store the hero quotes we want to display. In this case, each entry in the heros
collection should have the following fields:
-
quote
: A rich text field for the quote itself -
quote_attribution
: A text field to attribute the quote source -
content
: Optional additional content, such as a longer explanation or background for the quote
Example heros
Collection Entry
Here’s what one entry in the heros
collection might look like:
title: "Simplicity is the key to sophistication"
quote: "Simplicity is the ultimate sophistication."
quote_attribution: "Leonardo da Vinci"
content: "<p>Simplicity is the key to effective writing. By using clear and concise language, your message becomes more impactful. Complex ideas don't need complicated words to resonate.</p>"
In practice, we’re going to randomly display one hero quote out of this collection using Alpine.js on the front end.
Step 2: Setting Up the Blade/Antlers Template with Tailwind CSS
Now let’s move to create the layout where these hero quotes will be displayed. The following template ensures we can pull in random items from the heros
collection and display them in a visually appealing manner using Tailwind CSS.
Here’s what the context will look like in the Antlers template:
Template Structure with Collections and Tailwind
{{ collection:heros id:not:id as="heros" }}
<div class="max-w-screen-xl mx-auto" x-data="{ heros: {{ heros | to_json | sanitize:true }} }">
<template x-for="hero in heros.sort(() => 0.5 - Math.random()).slice(0, 1)" :key="hero.id">
<div>
<!-- Display the hero's quote -->
<h1 class="text-4xl lg:text-5xl font-light text-center mb-6" x-html="hero.quote"></h1>
<!-- Display the quote attribution, right-aligned -->
<div class="text-2xl lg:text-3xl text-gray-500 mt-6 block text-right">
<span x-text="hero.quote_attribution"></span>
</div>
<!-- Display additional content -->
<p class="text-xl text-left text-gray-600 mx-auto mt-6" x-html="hero.content"></p>
</div>
</template>
</div>
{{ /collection:heros }}
Key Explanation
-
{{ collection:heros as="heros" }}
: This fetches the collection of hero entries from Statamic. -
Alpine.js’s
x-data
: We use Alpine.js to dynamically fetch and manipulate the collection data inline, converting it into JSON via{{ heros | to_json | sanitize:true }}
. -
Randomization with
x-for
: Thex-for
directive works like a loop in Alpine.js. By combining.sort(() => 0.5 - Math.random())
with.slice(0, 1)
, we randomly shuffle the collection data and display only one item. -
Tailwind CSS styling: We use Tailwind classes for layout, typography, and spacing that make the quotes visually appealing.
-
.text-right
aligns the attribution to the right. -
.mt-6
provides top margin to space elements effectively.
-
Step 3: Enabling Alpine.js in the Project
At this stage, we need to ensure that Alpine.js is loaded correctly on the page. Without this, the interactive features (like random selection) won’t work. Here’s how you load Alpine.js in your project.
Loading Alpine.js
Add the following script tag in the <head>
section (or just before the closing </body>
tag) of your template to ensure Alpine.js is included:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
This will load Alpine.js version 3.x on the page, making it possible to use x-data
, x-for
, and other Alpine directives to dynamically manipulate content.
Verifying Alpine.js is Loaded
You can check if Alpine.js is loaded properly by typing Alpine.version
into the Developer Console in your browser:
- If you see a version number (like
3.12.0
), Alpine.js is loaded correctly, and you can move on. - If you get an error (like
Alpine is not defined
), it means Alpine is not loaded properly.
Step 4: Adding More Dynamic Hero Entries
Beyond random selection, you can add as many hero entries as you like to the heros
collection. Below is an example we'll add to the template:
Example Hero Entry in YAML:
title: "Make It Simple"
quote: "Make everything as simple as possible, but not simpler."
quote_attribution: "Albert Einstein"
content: "<p>Simplicity is powerful when it cuts to the essence while maintaining integrity. Stray too far into simplicity, and value can be lost. The true challenge is balancing clarity and complexity.</p>"
This will automatically pull in and be displayed under the random selection logic!
Step 5: Customizing the Layout Further — Adding Margins
If you’d like to style or add space between elements—or perhaps even add interactivity—you can easily do so with Tailwind and Alpine.js.
For example, to add some spacing above the quote content, we added this code:
<p class="text-xl text-left text-gray-600 mx-auto mt-6" x-html="hero.content"></p>
Here, the class mt-6
adds a 1.5rem top margin, but you can adjust it to mt-4
, mt-8
, etc., depending on how much spacing you need.
Step 6: Debugging and Logging the Data
To make sure the data is loading correctly in Alpine.js, you can use the x-init
directive to log your heroes collection to the console:
<div class="max-w-screen-xl mx-auto" x-data="{ heros: {{ heros | to_json | sanitize:true }} }" x-init="console.log(heros)">
This helps you verify whether the heros
collection is being passed correctly from Statamic to Alpine.js and how the data is structured.
Final Thoughts
With Statamic + Alpine.js + Tailwind CSS, you can easily create dynamic and interactive portions of your website, like random quotes from a collection. This approach allows for flexibility, fast performance without heavy JavaScript frameworks, and dynamic manipulation right on the DOM without the need for complex backend code.
By simply using x-data and x-for, Alpine.js turns a collection fetched in Statamic into a live, interactive experience. Combined with Tailwind CSS, the quotes are styled responsively with a minimal amount of custom CSS required.
Full Code Example:
Here’s the full working code after putting everything together:
{{ collection:heros id:not:id as="heros" }}
<div class="max-w-screen-xl mx-auto" x-data="{ heros: {{ heros | to_json | sanitize:true }} }">
<template x-for="hero in heros.sort(() => 0.5 - Math.random()).slice(0, 1)" :key="hero.id">
<div>
<!-- Display the hero's quote -->
<h1 class="text-4xl lg:text-5xl font-light text-center mb-6" x-html="hero.quote"></h1>
<!-- Display the quote attribution, right-aligned -->
<div class="text-2xl lg:text-3xl text-gray-500 mt-6 block text-right">
<span x-text="hero.quote_attribution"></span>
</div>
<!-- Display additional content -->
<p class="text-xl text-left text-gray-600 mx-auto mt-6" x-html="hero.content"></p>
</div>
</template>
</div>
{{ /collection:heros }}
Use this approach and feel free to extend it by adding more functionality, modifying styles, or adding more interaction! 😊