How to create an email newsletter from an RSS feed
In this tutorial, we'll use Events in Maizzle to fetch the contents of an RSS feed and display them in an HTML email newsletter.
You can preview the final result on CodePen.
Initial setup
Open your CLI and run the new
command to scaffold a new project:
maizzle new
Follow the steps in the prompt and scaffold a new project in the example-rss
folder.
Once it finishes installing dependencies, open the project in your favorite editor.
rss-parser
We'll be using rss-parser fetch the contents of the RSS feed, so let's install it:
npm install rss-parser
RSS Feed
We'll need an RSS feed to work with, so let's go with the best site for learning Laravel.
The Laracasts feed is available at:
https://laracasts.com/feed
Let's add that feed URL inside the build
object in config.js
:
// config.js
module.exports = {
build: {
feed: {
url: 'https://laracasts.com/feed',
}
// ...
},
}
Fetch Items
We can use rss-parser
inside the beforeCreate
event to fetch feed data.
Edit config.js
, require rss-parser
, and use it in the beforeCreate
event:
const Parser = require('rss-parser')
module.exports = {
events: {
async beforeCreate(config) {
// create a new Parser instance
const parser = new Parser({
customFields: {
feed: ['subtitle'],
item: ['summary'],
}
})
// fetch and parse the feed
let feed = await parser.parseURL(config.build.feed.url)
// store the feed data in our config
config.feed = {
title: feed.title,
subtitle: feed.subtitle,
link: feed.link,
updated_at: feed.lastBuildDate,
posts: feed.items,
}
}
}
}
rss-parser
does not currently return by default. We include them through the customFields
option.Date Format
We'll probably need to format the date of a feed item to something more readable than what the feed provides.
We can add a function to config.js
and use it to format the item's date according to our audience's locale:
// config.js
module.exports = {
// ...
formattedDate(str) {
const date = new Date(str)
return date.toLocaleDateString('en-US', {day: 'numeric', month: 'short', year: 'numeric'})
}
}
'en-US'
dynamically, based on your subscriber's preference.Template
Let's use a simplified version of the promotional.html
template from the Starter, where we will show posts in full width cards.
Header
Let's update the header row:
<tr>
<td class="p-48 sm:py-32 sm:px-24 text-center">
<a href="https://laracasts.com" target="_blank" rel="noopener noreferrer">
<img src="laracasts-logo.png" width="157" alt="{{ page.feed.title }}">
</a>
<p class="m-0 mt-8 text-sm fonts-medium text-gray-600">{{ page.feed.subtitle }}</p>
</td>
</tr>
Items Loop
Let's use a full width card from the Promotional template to show a list of all items from the feed:
<each loop="post in page.feed.posts">
<tr>
<td class="p-24 bg-white hover:shadow-xl rounded transition-shadow duration-300">
<p class="m-0 mb-4 text-sm text-gray-500">{{ page.formattedDate(post.pubDate) }}</p>
<h2 class="m-0 mb-16 text-2xl leading-24">
<a href="{{ post.link }}" target="_blank" rel="noopener noreferrer" class="text-cool-gray-800 hover:text-cool-gray-700 no-underline transition-colors duration-300">{{ post.title }}</a>
</h2>
<p class="m-0 text-base">
<a href="{{ post.link }}" class="text-cool-gray-500 hover:text-cool-gray-700 no-underline transition-colors duration-300">{{ post.summary }}</a>
</p>
</td>
</tr>
<if condition="!loop.last">
<tr>
<td class="h-24"></td>
</tr>
</if>
</each>
That's it! Take a look at the final result on CodePen.
Resources
- Laracasts
- rss-parser
- Maizzle Events
- GitHub repo for this tutorial
- CodePen preview