DEV Community

Farmin Farzin for AWS Community Builders

Posted on • Originally published at farmin.dev

Building my blog with AWS Amplify and Next.JS

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 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 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 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 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 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 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

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

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

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

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, I'll create our app running:

> yarn create next-app

? What is your project named? › my-blog
Enter fullscreen mode Exit fullscreen mode

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

then make sure I have Amplify CLI installed on your computer.

npm install -g @aws-amplify/cli
Enter fullscreen mode Exit fullscreen mode

Downgrade Next.JS and Webpack

As of today, Amplify doesn't support Next.JS@12 fully 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:

/** @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;
Enter fullscreen mode Exit fullscreen mode

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.

amplify pull --appId {you-app-id} --envName staging
Enter fullscreen mode Exit fullscreen mode

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

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:

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;

Enter fullscreen mode Exit fullscreen mode

Ok, now we can query some data in our index.js page to show it on the main page of our web app.

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

Amazing, now I see all my post titles.

post title preview

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.

Top comments (0)