AWS project — A server-less web application that converts texts to speech and connects to Alexa skill to play those texts

Let me tell you a little background about this project. In 2021, I decided to learn AWS and implement lots of projects on AWS. The best part, in Dec-2020 itself, I took a yearly subscription of “A Cloud Guru” platform. I knew I am not going to go through lectures and labs only, this time, I will build some projects that I can showcase and relate to real-world scenarios. Right away, I found an awesome section on A Cloud Guru, #ACGProjects. Thats it, I started and this is going to be my first blog on step-by-step instructions that I followed to implement this project. I will write everything that I did, what worked and whatnot. Let's do it.

Step-0: I am assuming you will be having some basic knowledge of AWS and this blog will help you to implement and see how a small use-case can be implemented on AWS.

Things you need — AWS account (free tier will work), GitHub for code repository.

Use-case: Building a Serverless website that uses Polly service to convert the text that we put on this website to an mp3 file and Alexa skill will read those mp3 files.

All Source code files provided by A Cloud Guru can be found:

AWS Services: S3, Lambda, API Gateway, DynamoDB, SNS, Polly, Alexa Skill

All the resources that we are going to use will be created in the same AWS region.

Below is the high-level architecture diagram for this project. It's pretty self-explanatory. If not, it's going to be clear as we move along.

Two Most important functionality of the website:-

  1. The post that you write on the website in the form of text will be saved in the DynamoDB table and later converted to an mp3 file and these mp3 files will be saved to an S3 bucket. This is shown in the bottom part of the architecture diagram, which is numbered with blue color from 1 to 8.
  2. Retrieve those posts and mp3 files to display on the website. This is shown in the top part of the architecture diagram, which is numbered with red color from 1 to 3.

Note: This project is currently created using AWS management console. Hence, all steps in this blog needs to be performed manually on AWS management console.

Step-1: Create DynamoDB table

table name: posts and primary key: “Id” (string — data type)

Use all other default settings and create table. Remember, the primary key field name of the DynamoDB table is case-sensitive and in “A Cloud Guru” Github code they named the primary key as “id”. Be very careful with this. I faced issues because of this and in a later part, I will explain to you how I troubleshoot these issues.

Step-2: Create two S3 buckets

  • one for storing mp3 files (create with default settings)
  • one for storing website files. (follow steps and screen-shots below)

2.1 This will be public, so that you can access website from browser.

2.2 Enable Static Website Hosting functionality. This can be found under the properties section of your bucket.

2.3 Apply bucket policy permissions, so that AWS resources can access this bucket. This can be done under the permissions section.

This Diagram shows 2 S3 bucket that we need to create
settings that you need to perform for enabling static website hosting

Step 3: Create an SNS topic

Purpose: this SNS topic is used to trigger a lambda function whenever a post text has been posted on website to convert it into speech format. Refer architecture diagram for better understanding.

This is pretty straightforward, under management console, search for this service and just give topic name and description and create it with all default settings.

Step 4: Create an IAM role

Purpose: this IAM role allows lambda to perform various operations, like fetch mp3 files from s3 bucket, store files to s3 bucket, connects with polly service, store and retrieve data from dynamodb table.

4.1 Need to create policy for Lambda function

policy document for lambda function

4.2 Create IAM Role and attach earlier created policy with the role

Step 5: Create 3 lambda functions and attach earlier created IAM role. Runtime environment would be Python 3.8

Below diagram shows the lambda function name created

5.1 Go to Basic settings and apply settings as shown below, in respective lambda functions: (each picture is for different lambda function)

5.2 Copy code for each function from github repository=

5.3 Create Environment variables for each lambda function

Here we created environment variable for dynamodb table
Here we created environment variable for dynamodb table and s3 bucket where we storing mp3 files
Here we created environment variable for dynamodb table and for SNS topic that was created earlier

5.4 Create SNS Trigger for “ConvertToAudio” lambda function

Step 6: Create API Gateway and make sure to select RestAPI from various available API options

6.1 Need to create 2 methods for our API (Get and Post)

Integration type: Lambda function

Lambda Region: us-east-1

6.2 Enable CORS for an API Gateway Resource, keep default settings, and just enable it.

It’s important to understand, Why are we doing it:

specifically, we need to enable CORS when API receives calls from a domain other than API’s own domain

6.3 Create “URL Query String Parameter” for Get method

Click on “Get” method → click on “Method Request” hyperlink Tile → Create “PostId” as query string parameter. “PostId” is case sensitive, it should be same everywhere.

6.4 Click on “Get” method → click on “Integration Request” hyperlink Tile → Go to “Mapping Template” section and select “When there are no templates defined (recommended)” option → and type “application/json” in Content-Type section → place highlighted text in General template textbox section as shown below

6.5 Deploy API → Click on Actions and click “Deploy API”. Follow the steps and finish the deployment.

Step 7: Place website files to S3 bucket. Remember to copy and paste the API invoke URL into scripts.js file before you upload. This needs to be done at the first line on the scripts.js file, (var API_ENDPOINT = “YOUR-API-GATEWAY-HERE”)

All 4 website html, css and javascript file can be found on github repo:

“index.html, error.html, scripts.js, styles.css”

Step 8: Play around with the website using S3 bucket web hosting URL

You should see your website looks something like this.

Hope you enjoyed this project and learned something new.


  1. Make sure you delete all resources after completing this project Or at-least remove public access from services.
  2. Delete items from dynamodb table.
  3. Delete mp3 files from S3 bucket and if you done with this project you can completely delete the bucket.

Pending part or Enhancement:

  • Connect these mp3 files created by polly service to AWS Alexa Skill. As soon as I finish that part of project, I will update this blog. Feel free to try it by yourself. It shouldn’t be too hard to implement.

Below are few errors that I encountered and how I solved them:

  1. In github repo print function was written in python 2.7 version but i am using python 3.8 version. So, need to correct the syntax.
  2. DynamoDb table query was wrong, the key field name is case-sensitive and hence needs to correct it. (example, was written as “id”, which was incorrect, the correct is “Id” in my case.)
  3. while writing the mp3 file, the open function written in lambda function should open file in byte (or binary) mode. Using syntax like “with open(output, “ab+”) as file:” needs to be corrected.
  4. “An error occurred (AccessDenied) when calling the PutObjectAcl operation: Access Denied” , for S3 bucket. Solution:- S3 bucket permission should be set appropriately to accommodate this code.
  5. table.update_item function in lambda function code file for dynamodb should also has correct key for dynamodb table.
  6. postID is not displaying at the webpage. because “id” field of dynamodb is case sensitive, and in scripts.js file has it in incorrect format. Needs to correct it in my case.

Things I learned in this project

  • How to setup Lambda function
  • AWS architecture overview and how different services communicate with each other
  • I feel, it’s good that all these issues came. It’s good that I made one small mistake of dynamodb key “id”. That allowed me to troubleshoot so many issues and that allowed me to learn these important part of the project. Otherwise, i could have just implemented everything by coping from ACloudGuru.

A side note: Why I am writing this blog:

Firstly, because I like to document my project that gives me clear picture of what I did and i can have quick review of it as and when needed.

Secondly, This can help someone, who is interested in learning it.

In the end, just wanted to thank you for reading it and hope you enjoyed it. Please feel free to share your love.

Data Analytics Engineer, crossing paths in Data Science, Data Engineering and DevOps. Bringing you lots of exciting projects in the form of stories. Enjoy-Love.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store