Building a fullstack web app with AWS Amplify #AmplifyHashnode
Or, how AWS of all platforms has the most user-friendly tools for deploying your web apps. Seriously.
A few weeks ago, I saw a post on hashnode for the #AmplifyHashnode hackathon. The rules were simple: Build an app with a free-tier AWS Amplify tool, write a blog post about it, and use the #AmplifyHashnode hashtag in my post.
I was already planning on writing a particular little tool in React and was looking for a cloud hosting provider anyway, so this sounded like a win-win. Test out AWS Amplify's hosting service, build my app, maybe win the contest, and count my thousands of dollars in winnings.
Well, the first place prize is one thousand dollars , but still. It's the thought that counts.
It's not my first time deploying a webapp to a cloud provider though, so I had my concerns. Netlify failed me, Google Cloud scares me (because google shuts down everything), Heroku is too expensive, and Render.com is great, but it isn't exactly free.
The thought of building out a full project that works perfectly on my machine, only to end up spending days reading through cryptic, platform-specific build logs to figure out why the heck it won't even compile on the cloud provider's end, did not sound fun. Render may not have been free, but it was a known quantity. I was skeptical.
Building the project
I was also skeptical of my own abilities.
I had never coded anything in React before this, and a combination of Twitter chatter and some intimidating-looking code snippets had scared me into thinking it was going to be an undertaking on the level of learning a new language altogether. To make matters worse, the competition's deadline was February 28th, and I wasn't going to have free time to work on my app until the 21st.
Luckily, with some help from npm create-react-app, I was able to get a functioning project up and running immediately. After setting up my github repository, I was off! Just a few React tutorials was all it would take for me to get started on my masterpiece...
The NecronomiSearch! Mwahaha!
In a past life, I was a massive fan of Game of Thrones. That show quite literally changed my life, considering how heavily it influenced my ideas about what was possible in storytelling with enough ambition and artistic dedication. My passion is writing novels, so every time I come across one of those once-in-a-generation stories, I get twice as much education as entertainment out of it.
Anyway, loving the show led me to loving the books, which led me to loving the extremely vibrant, active and fun fandom. I came across countless youtube channels , blogs and apps people had poured their hearts and souls into in dedication to this story we all loved. One of those apps was A Search of Ice And Fire.
A Search of Ice and Fire was essentially a reference tool that allowed you to type in any term and immediately get all instances of that term across all A Song of Ice and Fire books. Legal? Probably not? Cool? Definitely! 95% of the fandom's content was based around fan theories, which were often structured like research papers; having a resource that provided all instances of any given term, in context, with the metadata about which books and chapters they occurred in, was extremely useful.
I wanted to recreate that for another little literary fandom I've found myself in lately: The world of HP Lovecraft.
So, NecronomiSearch was born!
Or at least the idea of it was. I still had to actually code the thing.
Coding the Thing
Beyond my fears of learning React, I had a few other things to cope with. In fact, I had a little list of questions to answer before I could finish the project:
- Will I be able to use React? (Frontend)
- How will I store the data about the books? (Database architecture)
- Which database will I use? (Database paradigm)
- How will I implement my API? (Data access)
- Where will I host my project?
After a few tutorials, I was pleasantly surprised to learn that React was fairly easy. Since I'm already comfortable with CSS, once I knew that using React to structure my code and design the logic wouldn't be a problem, my only major concerns had to do with backend issues. This is where AWS Amplify comes in.
Amplify Fixes LIterally Everything
Nothing is cooler than the fact that Amplify has its own API toolkit. If you've never used something like that, the phrase "API toolkit" may sound like jibberish--but I promise it's really cool. All you have to do is install the amplify CLI, initialize amplify in your project folder, and run
amplify add api.
Unlike many tools for setting up projects, amplify isn't awkward if you already have an existing project--in fact it fits in perfectly, installing an amplify folder in your root directory with all your files and information sorted for you. If you use the api tool, amplify's CLI will help you set up a GraphQL database using Amplify's Datastore tool, structure the schemas for your DB tables, and auto-generate your API code for you.
I repeat, you will never have to write a getter, setter, updater or deleter method if you don't want to. The CLI does all of that, bundles that code into a lovely folder, and even protects you from the messy business of handling API keys.
This thing even adds all the sensitive files to your .gitignore for you. The term plug and play is so overused that it basically refers to anything slightly better than absolutely nothing, but amplify is true plug-and-play software. I would recommend this tool wholeheartedly to beginners who want the API experience without the cumbersome learning process of setting up a DB and memorizing the particular way interfacing with that DB works.
Did I mention it updates your auto-generated API code for you whenever you change your schemas?
I will be using amplify in the future for quick apps that I don't want to stress myself too much about. Need to get up and running with a quick and dirty DB? Use amplify, dude. I will tell people that whether I win this competition or not.
Their CLI is also very similar to git's, so
amplify api add,
amplify api update, and
amplify api pull all do about what they sound like they would do. This was very important for me, because my schemas were constantly changing in the beginning as I was figuring out how I wanted to store this book data, and I didn't want to be fumbling around in cumbersome docs to do what should be extremely simple.
Anyway, once API is ready, you're plugged into their Datastore tool, which is a web GUI for handling the data in your GraphQL DB. This was what I used for manually entering the data about the Lovecraft books. Had I had more time to work on this, I would've come up with a clever tool to web scrape meta data about the books and store it all in lovely JSON objects, which I could've then used as schemas for storing them in my DB.
A lovely dream. But I didn't have time.
So instead, I came up with a system that would be good enough to get things running, require more labor, but ultimately take less time: Copy and pasting details manually. Gotta love it.
Getting Plugged In
Did I mentioned that I knew nothing about GraphQL before starting this project?
Well, it's true, and I was quite intent on still knowing nothing about GraphQL by the end. With only a week to get the project done in time for the competition, the last thing I wanted to do was spend a few days wrapping my mind around what I worried would be massively different from anything I was used to in the MySQL and MongoDB worlds.
Luckily, because Amplify created the API code for me, I didn't have to worry too much about that. My app's only goal was to read data from a DB based on search queries. No mutations whatsoever. The biggest hurdle would be figuring out how to look up specific items in specific tables based on search queries. Amplify's own documentation made that easy enough to do, so I was off to the races.
After ensuring I could read data successfully from the DB, I was free to focus on the fun part--actually putting the app together. And once I was done with the fun part, it was time for the darkness.
Deploying to the cloud.
Amplify App Hosting
Like all hosts, Amplify allows you to set up Continuous Integration and Continuous Delivery of your app by "plugging it into" the github repo for your app. Every time you push a new commit to your repo, the app will rebuild and redeploy. "Deploy," in this context, just means it will compile and serve the app up to its specified URL, which Amplify auto-generates, but which you can replace with your own custom domain.
This can be scary if you've only ever run a development build of your app on your local machine. So many things could go wrong, and you best believe you will have no idea what the problem is, let alone how to fix it.
My app was crashing immediately, as expected, and I spent a good few hours trying to understand the problem before I realized it was the same issue I run into with all hosting providers: Environment variables.
Amplify in particular is very strange about its Environment variable setup. In order to use them, you have to use thier GUI interface for adding the variables, but then you have to define the variables again in your build scripts. If not for reddit, I wouldn't have known this, and probably still wouldn't have the project up and running--at least not on amplify.
The core of the issue comes back to two things, one of which is Amplify's responsibility, and the other isn't.
The thing Amplify has to take blame for is the fact that, at least in the reading material I found, amplify encourages you to use a file called aws-exports.js to store the environment variables containing data about your auto-generated API. This acts like a sort of .env, though it's just a JS module that exports an object containing your API secrets.
There's nothing, at least that I saw, that warns you that this file is only relevant in a development environment, and that you will have to go through a different process to gain access to that data when it comes time to set up your production build. I'm sure experienced vets would know this instinctively, but to be quite honest, with how much amplify was already handling for me, I kind of hoped it would have my back on this one too.
Environment variables and how specifically to to gain access to them in production on each hosting platform are is legitimately a major issue for me, but at least I was able to resolve it--something I can't say for the same issues I faced with Netlify on a different project, even after getting help from its community forum.
The second issue was the fact that, if you use create-react-app, you can only access your environment variables by prefixing them with REACT_APP. I've seen the reasoning behind this, and I don't disagree with it, but I do disagree with the script not adding an empty.env file to the root directory with some commented out text that says, "Add REACT_APP to the front of your environment variables if you want to use them."
Again, that's not AWS's fault, but it still needs to be said.
Once I fixed the environment variables, everything went extremely smoothly. In fact, Amplify has its own built in integration with another Amazon service called Route53. If you buy your domain through them, for only about $3 more than it would cost on a service like Namecheap, they apparently set up everything for you in regards to the DNS--something I would've paid at least an extra $10 for.
I say apparently, though, because issues with my default payment option caused Route53 to jank out, and I was informed I wouldn't be able to get my domain from them for another 24 hours. Unacceptable, if you ask me--so I got it instantly at namecheap.
As for how the app itself turned out?
I think it came out pretty nice, both on Desktop and Mobile. I've got some changes I'd like to make, of course.
There's essentially 0 data validation, so... yikes. That means a malicious user could put some weird text into the search field and ptoentially damage my DB's, or dump all the data. That's fine since it's just a bunch of data about HP Lovecraft books, but it's still a security hole.
I'd also like to make some UI changes, and eventually add the rest of Lovecraft's books. If I have time, it'll definitely happen!
Be sure to let me know what you think of this article and the app on twitter ShaquilHansford!
Thanks for reading! Try checking out my series on Junior Developer interview questions, if you're interested in more of my web dev thought