Build a simple newsletter system with Directus

Learn how to build a simple newsletter system with Directus Flows. Featuring newsletter contacts & list management, along campaigns automations.

Build a simple newsletter system with Directus


Just a small disclaimer, keep in mind that what we are going to build is nowhere as efficient as a proper mailing system like Listmonk or other paid alternatives. This is just a demonstration of what Directus is capable of, but it's a good start if you wish to dive deeper in building your own mailing system.


Planning our newsletter system

Before we begin, we have to think about the skeleton of our newsletter system which is composed of three important things:

  • Contact list - the people who will receive our newsletter
  • Campaigns - the mailings that will be sent to our contacts
  • Automation - to send your campaigns to your contacts in one click

We need to define what are their purposes and how they will interact with each other

The newsletter contact list

As we said before, the contact list will contain a list of people that will receive our newsletter. Here's a simple structure for this:

  • Email - unique string corresponding to the contact email
  • Name (optional) - if you want to include the contact's name (for more proximity), you can also include depending on how you build your sign-up form
  • Status  (optional) - if you wish to save the contact's information after they unsubscribed from your newsletter, you can use this field to stop sending them newsletters and keep their information in your database instead of deleting the contact (of course check that you mention this information in your privacy policy)

The newsletter campaigns

This is where you will design your campaigns that will be sent to your contacts. Here's a simple structure for this:

  • Name - the name of your campaign
  • Subject - this is the title your client will see when they receive your e-mail
  • Content - the content of your e-mail

Sending your campaigns

To send our campaigns, we will use Directus' Flows. We will create 3 flows:

  • Trigger send campaign - this will be our entry point, it will parse the selected campaigns and run the second flow for each campaign
  • Send newsletter campaign - the second flow that will get all the data needed to send our newsletter, parse our contact list and trigger the third flow for each contact in our list
  • Send newsletter to contact - our final flow that will send the newsletter to each contact individually

So now that we have defined the structure of our system, let's build it.


Building the newsletter collections

Newsletter campaigns and contacts collections

Contact list collection

The newsletter contact collection

Create a collection named newsletter_contacts, add a unique field named email (and other fields if you want to) and you're good to go.


Newsletter campaigns collection

Newsletter campaign collection

Create a collection named newsletter_campaigns and add the following fields:

  • name - String
  • subject - String
  • content - Text (WYSIWYG or Markdown as you wish)

When everything is set-up, we can go forward and connect everything together.


Building the newsletter system

The 3 Flows for our newsletter system

Now that our collections are created, we will use Flows to interact with them. First, create the three Flows mentioned above. When it's done, you can continue


The first Flow

The first flow structure

This Flow will take an array of newsletter campaign ID, parse the list and trigger the second flow for each key in the array. It's a very simple Flow, set it up like this:

  • Trigger type - Manual
  • Collections - Newsletter Campaigns
  • Asynchronous - Enabled

Then, add a Trigger Flow operation and set it up like this:

  • Name - Send newsletter campaign
  • Payload - "{{ $trigger.body.keys }}"

Explanation: "{{ $trigger.body.keys }}" is an array corresponding to the array of campaign IDs you select from the dashboard. When you pass an array as payload to another Flow, the latter will run for each element in the array.


The second Flow

The second flow structure

This Flow will prepare and format all the datas needed to send our newsletter. Set it up like this:

  • Name - Send newsletter campaign
  • Trigger - Another Flow
  • Response Body - All data 

Then, add the following operations (following the order):

  1. Get campaign
    • Type - Read Data
    • Permission - Full access
    • Collection - Newsletter Campaigns
    • IDs - {{$trigger}}
  2. Get contacts
    • Type - Read Data
    • Permission - Full access
    • Collection - Newsletter Contacts
    • Query 
      "limit": -1
  3. Format newsletter data
    • Type - Run Script
    • Code
      module.exports = async function(data) {
          return => ({...res, campaign: data.get_campaign}));
  4. Trigger Flow
    • Type - Trigger Flow
    • Flow - Send newsletter to contact
    • Payload - "{{$last}}"

Explanation: we get information about the campaign that was passed from the previous Flow, then we get all our contacts, and we create an array composed of objects that have both the contacts and the campaign that we pass to our final Flow.


The third and final Flow

The final flow that just sends our newsletter to our contacts

This is the last piece of the puzzle. Its purpose is to send the newsletter to our contacts and it's a pretty simple one:

  • Name - Send newsletter to contact
  • Type - Another Flow
  • Response Body - All Data

Now, let's add the email sending operation:

  • Operation Type - Send Email
  • To - {{$}}
  • Subject{{$trigger.campaign.subject}}
  • Type - WYSIWYG or Markdown (as you wish)
  • Body 
    // Your custom content (ex: <img src={LOGO_URL}/>)


    // Your custom content


Sending our newsletter campaigns

Trigger our newsletter with Directus Flows

Now that everything is set-up, you can send your campaigns by selecting them from the collection page and clicking on the Trigger send campaign on the right sidebar, under the Flows section.



You have now built a (simple) working newsletter system. Don't hesitate to play around with it and add more features! You can for example add a CRON job to send your campaigns at a given time. Let me know in the comments if you want an in-depth article with more features.

Take care and if you have questions don't hesitate to comment!

Also built with Directus: