Building my blog with AWS Amplify and Next.JS
Tags: nextjs, amplify, webdev, tutorial
Published: 2022-09-26 21:17:53

Is it me or everyone has the experience of going back and forth between having a custom personal blog or writing on a platform like `Dev.to`?!

I changed my mind multiple times in the last decade, I had my blogs done with WordPress, Jekyll, and Gatsby but then I moved to Dev.to and Medium and to be honest I might have put more effort into building blog sites rather than writing the blogs.

This time I want to have both, I'm gonna keep writing on Dev.to but also I want to re-build my new blog because I want to have a place to try new tech and enjoy building stuff. (instead of browsing on different social media at least I'd learn something eh?)

## AWS Amplify

I'm a huge AWS and Serverless fan and because of that, I decided to have my blog built and deployed by AWS . Plus I'm an [AWS Community Builder](https://aws.amazon.com/developer/community/community-builders/) so it makes sense to have something to explore and build related to that. 

So how exactly? I could just write my backend with services such as API Gateway, Lambda, and DynamoDB and host my frontend on S3, but I decided to make it a little bit more powerful (even though it's a blog and I don't need to) by using [Amplify](https://aws.amazon.com/amplify/) as my full-stack solution to build, test and deploy the app.
AWS Amplify is an amazing tool that I can easily provision my backend with IoC (infrastructure as code) and have my pipelines ready to work and connected to GitHub. 
Amplify offers this great tool called [Amplify Studio](https://aws.amazon.com/amplify/studio/) where you can graphically build your backend such as adding services or modeling your DB. I'm going to use it for:
- build my data model
- add file storage (S3 bucket)
- add authentication (If needed)
- add content (I can generate some mock data in case too)
and more importantly, I'm gonna use it as my "headless CMS" since I can easily write my blogs there instead of implementing an editor on my frontend or writing directly on the DB!!

There is also Amplify Service in AWS Console that would help to configure my pipelines and environments and connect them to my GitHub branches.

It is worth mentioning that Amplify has a [CLI](https://docs.amplify.aws/cli/) tool that offers everything that we can do (and more) on the Studio and Console in CLI and it has a lot of options for scaffolding the code.
In general, I find two ways to implement the backend with Amplify:

1. Configuring and changing things on the Studio or Web Console (Getting deployed with CloudFormation) and then `pull` them on your local to have them as code and commit them to the Git
2. Implementing everything locally using Amplify CLI or just manually and `push` them to AWS (AWS CloudFormation Deployment) then commit to the Git

## Next.js
On the Frontend side, I can easily scaffold a React app using AWS CLI but it uses [create-react-app](https://create-react-app.dev/) and will be deployed as SPA on S3.
Since I want to build a blog, **SEO** is a huge deal to me and I need **SSR**(server side) app to help me in that. because of this, my choice would be Next.js.(I'd go with SSG)
At this moment, Next.js is on version 12 but I will use version 11 since I know there are issues with Amplify and Next.js@12 (I will mention in another post)

## Enough talking, let's code!

### Backend

Let's head to Amplify Service in AWS Console [here](https://us-east-1.console.aws.amazon.com/amplify) and create a new app (build a new app). Choose a name and click next. Now Amplify will prepare everything and creates the Amplify studio and some resources needed for the project.
After finishing setting up, you should see this page and you can launch your Studio.

![Amplify Studio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zsukjkbr5aoo8gqm8cw.png)

Now we can do some data modeling easily. I just need a table for my post so I'll create one with this schema and deploy it.

![Data Modelling using Amplify Studio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7bhl9edfd82hpeon0m7.png)

After successful deployment, I have my backend fully ready to use this schema. what it means is that I have my APIs ready to do CRUD operations on the DB using this schema. 

![successful deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l61tcr3k06burrkngbii.png)

If you're wondering what has happened in the background, I have a plan to write a blog about `What do we build on our AWS account with Amplify Data Model deployment?`

The last thing to do in the Studio is to make some mock data to use on the frontend. To be honest, this is an amazing feature that will save a lot of time in the development process. Browse to `content` menu on the right and click on `Actions` => `Auto-generate data` and generate 10 rows of data.
Awesome, now I have some mocked data and actually, I will use this dashboard later as my "headless CMS" feature to write my blogs.

![Mocked Content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xw2k7lpdcsv53pttwi84.png)


It's time to move to frontend and build my app and configure it to use my APIs.

### Frontend

Yet, I don't have any code on our local and this is the time to build `Full-Stack` project locally.
Let's create a Next.JS app and then transform it into a full-stack app by pulling backend configuration.

Following [Next.JS docs](https://nextjs.org/docs/getting-started#automatic-setup), I'll create our app running:
```
> yarn create next-app

? What is your project named? › my-blog
```
after setup is finished, if you run `yarn dev`, you should be able to see the app running on `localhost:3000`.

![Next.JS boilerplate page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tefcnj3vbi12p9k66fq.png)

then make sure I have [Amplify CLI](https://docs.amplify.aws/cli/start) installed on your computer. 
```bash
npm install -g @aws-amplify/cli
```

### Downgrade Next.JS and Webpack

As of today, [Amplify doesn't support Next.JS@12 fully](https://github.com/aws-amplify/amplify-hosting/issues/2343) and because of that, it'd be better and safer to downgrade to version 11 (of course we'd miss some of the awesome features from v12 but that's fine). So I'm making it `"next": "11.1.4"` in the `package.json`. Since we're downgrading it to v11, we need to downgrade usage of `webpack` from 5 to 4 and for doing that we need to add `webpack5: false` to our `next.config.js` file. I also add `SVG` support to that file for the future and it looks like this:

```js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  webpack5: false,
  webpack: (config) => {
    config.module.rules.push({
      test: /\.svg$/,
      use: ["@svgr/webpack"],
    });

    return config;
  },
};

module.exports = nextConfig;
``` 

### Connecting Frontend to our backend
As you could see on your Amplify Studio, there's a command for pulling the backend code and everything you need to connect your webapp to backend services.
```bash
amplify pull --appId {you-app-id} --envName staging
```
if this is the first time, it will authenticate you on the web and goes back to the terminal. You'll be prompted for your IDE, language, framework and source folder.

![amplify cli prompts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w65rt7ruccvg38ypzhki.png)

after the setup finishes, I'd have a lot of file changes on the repo. Let's commit the code to Git to make sure we keep track of the work that I'm doing.

Alright, let's do some coding and get the mocked blog posts that we have and show it on the blog.
let's install `Amplify` library: `yarn add aws-amplify`

open `_app.js` file and add amplify setup:
```js
import Amplify from "aws-amplify";
import "../styles/globals.css";
import config from "../aws-exports";

Amplify.configure({
  ...config,
  ssr: true,
});

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;

```

Ok, now we can query some data in our `index.js` page to show it on the main page of our web app.
```js
import React from "react";
import Head from "next/head";
import Link from "next/link";
import styles from "../styles/Home.module.css";
import { DataStore } from "aws-amplify";
import { Post } from "../models";

export default function Home() {
  const [posts, setPosts] = React.useState([]);

  React.useEffect(() => {
    async function fetchPosts() {
      const postData = await DataStore.query(Post);
      setPosts(postData);
    }
    const subscription = DataStore.observe(Post).subscribe(() => fetchPosts());
    fetchPosts();
    return () => subscription.unsubscribe();
  }, []);

  return (
    <div className={styles.container}>
      <Head>
        <title>My Blog</title>
      </Head>

      <main className={styles.main}>
        <h1>My Blog</h1>
        {posts.map((post) => (
          <Link key={post.id} href={`/posts/${post.id}`}>
            <a>
              <h2>{post.title}</h2>
            </a>
          </Link>
        ))}
      </main>
    </div>
  );
}

```

Amazing, now I see all my post titles.

![post title preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zxyig452xgcy7l9h00l.png)

I have everything I need to write/move my blogs now, I just need to do some coding on the frontend side to show them and style them as I want.
Let's commit the code to GitHub so I can build my pipeline for the deployment.

## Continuous Deployment and Pipeline

In the next post, I'm gonna set up my [CD](https://en.wikipedia.org/wiki/Continuous_deployment).