DEV Community

Pete
Pete

Posted on

Adding additional services into Amplify

Michael Liendo's post Serverless Contact Form Using AWS Amplify reminded me of something I learnt about adding additional "not natively supported" services into Amplify.

When I say "not natively supported", I mean you can't create the resources with the cli. Rather than, Amplify doesn't support them at all. Of course your application will, you've access to the AWS SDK after all...

Sending a simple templated email...

Like Michael's example, I wanted to simply create an email to invite people to an organisation in the slate. The difference was I wanted to use an SES email template, so that I could have different environmental versions.

SES templates?

Rather than have the actual email template like so

await ses
  .sendEmail({
    Destination: {
      ToAddresses: [process.env.SES_EMAIL],
    },
    Source: process.env.SES_EMAIL,
    Message: {
      Subject: { Data: 'Candidate Submission' },
      Body: {
        Text: { Data: `My name is ${candidateName}. You can reach me at ${candidateEmail}` },
      },
    },
  })
  .promise()
Enter fullscreen mode Exit fullscreen mode

You can do something like this,

var emailTemplate = {
  Destination: {
    ToAddresses: []
  },
  Source: `The Slate <${inviteEmail}>`,
  Template: 'SLATE_INVITE',
  TemplateData: `{ \"invited_by\":\"${userDetails.name}\", \"invite_url\": \"${url}\" }`, // THIS HAS TO BE A JSON ESCAPED STRING!?
  ReplyToAddresses: [
    `The Slate <${inviteEmail}>`
  ],
};

await ses.sendTemplatedEmail(emailTemplate).promise();
Enter fullscreen mode Exit fullscreen mode

SLATE_INVITE is a reference to an HTML and Text email template held in SES, and it will accept the references and data in TemplateData to be rendered in the template. To me it's a nice / clearer way of making changes to the template.

Kicking it up a notch

For some reason, I've no idea why, I decided to put the HTML and text templates into /amplify/backend/email.

Then in my infinite wisdom I wondered, could I make a Cloudformation template for this?

My rational was that I could deploy environmental/versioned templates alongside everything else, and if I had to spin the slate up on a different AWS account, it wouldn't be a problem. The short answer is yes, yes you can.

As you can imagine, it didn't take long to go "If I have a cloudformation template, could add it to the existing Amplify cloudformation set-up?". Again, turns out you can do this too.

Extending your Amplify Cloudformations

You may have never have noticed, but there is a file at /amplify/backend/backend-config.json that describes your amplify resources, e.g.

"storage": {
  "slate": {
    "service": "DynamoDB",
    "providerPlugin": "awscloudformation"
  }
},
Enter fullscreen mode Exit fullscreen mode

The format of the json describes two things;

  1. "Storage" is both the "Category" you see in the cli and a folder (/amplify/backend/storage)
  2. "slate" is "Resource name" you see in the cli and a folder (/amplify/backend/storage/slate) holding the cloudformation template

If you were to add something like

"email": {
  "invite": {
    "service": "SES",
    "providerPlugin": "awscloudformation"
  }
},
Enter fullscreen mode Exit fullscreen mode

In theory it will be picked up.

In theory you say?
Yes - because you need to have /amplify/#current-cloud-backend/amplify-meta.json refreshed to see your new service in the cli.

Once that happens, when you will see your new custom service and it will execute as part of the cloudformation stack. If it isn't there, it won't.

Top comments (2)

Collapse
 
focusotter profile image
Michael Liendo

This is an awesome post! Thanks for taking the time to showcase folks how to extend Amplify. Our team is making some big improvements when it comes to extensibility this year. Stay tuned 😉

Collapse
 
mcvicar profile image
Pete

No problem at all - it was an interesting curiosity that snowballed, then I promptly forgot about it. After I read your post I remembered that I had done it!

I figured documenting would be worthwhile as I hadn't come across anyone mentioning it was even possible.