DEV Community

Cover image for Building a collection of Tech Blogs using React JS and HarperDB
Bonnie
Bonnie

Posted on

Building a collection of Tech Blogs using React JS and HarperDB

As a developer or Technical Writer, what is the first thing you do when you run into an error or bug while coding?

You will probably Google the issue to see if someone else has faced a similar problem and solved it. If someone has found a solution to the problem they have encountered and has good writing skills, they will most likely write a blog post or an article explaining how they solved it.

As we all know, Google will only display blogs with Search Engine Optimization on the first page of search results. Unfortunately, there might be good blogs with a better solution to your problem, but you may never discover them.

For this reason, I want to show you how to create a dynamic web page with a collection of awesome blogs of your choice. In this case, you will learn how to create a collection of your favorite technical blogs over the internet based on these web development technologies.

  • HTML
  • CSS
  • Javascript
  • React

We will use React for the frontend and HarperDB as our database in this project. HarperDB is where all the dynamic data displayed on the front end will be stored.

What is HarperDB?

HarperDB is a SQL/NoSQL data management platform. In addition, HarperDB Studio, a web-based GUI where you can control and manage instances, will be used to handle data for this project.

You will then learn how to use HarperDB’s Custom Functions to create API endpoints that will help us to make an API request to a standalone API server inside HarperDB. The API request will get the dynamic blogs data stored in HarperDB, and then React will display it on the frontend.

In the end, you will learn how to create something, as shown below.

Image description

Setting up a HarperDB Account

Step 1: Start by creating your HarperDB Studio account. It's completely free to use, so sign up here: studio.harperdb.io

Image description

Creating Your First Cloud Instance

Step 2: Now select "Create New HarperDB Cloud Instance," which will be used for this project.

Image description

Step 3: Select the Instance type. We'll use the cloud instance in this case.

Image description

Step 4: Fill out the Instance details as per your preferences:

Image description

Image description

Step 5: After that, choose the specs. For the time being, we'll go with free options:

Image description

Step 6: Your first cloud instance is successfully created!

Image description

It's time to populate the cloud instance with your own data.

Creating Schema & Table data

  • Open the instance tech-blogs we just established.
  • We need to develop a schema for our blog list data before we can add it.
  • We will name our schema collection
  • Name a table as blogs and save it. This will hold all of the data from the blog records that we require.
  • Each record (here, blogs) will now require a hash_Attribute. Think of hash_Attribute as a "key."
  • Name the hash_Attribute: id

Image description

  • In HarperDB, you can add queries (sql, nosql) as data, import a CSV, or just add a json object.
  • We'll use a JSON object to store data in our app.
[
    {
        "title": "Overreacted",
        "icon": "🔥",
        "description": "Dan Abramov writes about UI engineering, software development practices, and concepts in React.js",
        "tags": "react",
        "blog_url": "https://overreacted.io/",
        "twitter_url": "https://twitter.com/dan_abramov"
    },
    {
        "title": "Robin Wieruch's Blog",
        "icon": "☕",
        "description": "Robin writes guides and tutorials about React.js, Node.js, GraphQL and JavaScript. ",
        "tags": "javascript",
        "blog_url": "https://www.robinwieruch.de/blog/",
        "twitter_url": "https://twitter.com/rwieruch"
    },
    {
        "title": "Dave Ceddia's Blog",
        "icon": "⚛️",
        "description": "Dave's articles help you learn and master frontend development with React.",
        "tags": "react",
        "blog_url": "https://daveceddia.com/archives/",
        "twitter_url": "https://twitter.com/dceddia"
    },
    {
        "title": "Lee Robinson's Blog",
        "icon": "😄",
        "description": "He writes mostly about web development and tech careers.",
        "tags": "html",
        "blog_url": "https://leerob.io/blog",
        "twitter_url": "https://twitter.com/leeerob"
    },
    {
        "title": "Josh W. Comeau's Blog",
        "icon": "👋",
        "description": "He writes articles with a focus on React, Gatsby, CSS, and animation.",
        "tags": "react",
        "blog_url": "https://joshwcomeau.com/",
        "twitter_url": "https://twitter.com/JoshWComeau"
    },
    {
        "title": "CSS Tricks",
        "icon": "⭐",
        "description": "Daily articles about CSS, HTML, JavaScript, and all things related to web design and development.",
        "tags": "css",
        "blog_url": "https://css-tricks.com/",
        "twitter_url": "https://twitter.com/css"
    },
    {
        "title": "Smashing Magazine",
        "icon": "👊",
        "description": "Articles all around CSS, JavaScript, front-end, UX and design.",
        "tags": "css",
        "blog_url": "https://www.smashingmagazine.com/",
        "twitter_url": "https://twitter.com/smashingmag"
    }
]
Enter fullscreen mode Exit fullscreen mode
  • Let's use HarperDB Studio to add this data to our schema.
  • Go to the blogs table and select the + icon:

Image description

  • It will open a blank page where you just need to paste the above JSON data as follows:

Image description

Save this data by clicking on the green button below. You will see the table like this:

Image description

Creating your first Custom Function with HarperDB Studio

What are Custom Functions?

HarperDB introduced the concept of Custom Functions in the 3.1+ release. They are customizable API endpoints that you can create and manage from within the HarperDB Studio.

  • Now we have to create API endpoints to use in our app. Let's begin by making our first custom function.
  • To access the functions option, go to the instance you created and select it from the navigation links:

Image description

  • Click on the Enable Custom Functions button and name the project as api.

Image description

  • You'll now be directed to a page where you can create routes and helper functions based on your app's requirements:

Image description

  • Let's test the endpoint first.

Replace the pre-written code in the ‘examples’ API routes file with the following:

'use strict';

module.exports = async (server) => {

  server.route({
    url: '/',
    method: 'GET',
    handler: () => {
      return "A blogs API";
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

The URL is set to /, which can be accessed at {custom_functions_server_url}/{project_name}.

Your custom_functions_server_url can be found on the custom functions page, simply copy it:

Image description

  • Now open a new tab in your browser and test the endpoint:

Image description

  • Great, it works perfectly!

Setting up API endpoints

For now, this API does not fetch any blog data. This route will help us in developing an API endpoint to retrieve this information.

Creating the API endpoint:

module.exports = async (server, { hdbCore, logger }) => {

    server.route({
        url: '/blogs',
        method: 'GET',
        handler: (request) => {
          logger.debug(request);
          request.body= {
            operation: 'sql',
            sql: 'SELECT * FROM collection.blogs'
          };
          return hdbCore.requestWithoutAuthentication(request);
        }
      });
}
Enter fullscreen mode Exit fullscreen mode

As you can see, we've changed the URL to /blogs this time. The handler function will make a SQL request which will return the blog's data.

Again, this route can be accessed at {custom_functions_server_url}/{project_name}/{url_route}

Image description

We're getting the data from the blogs. Now let's make another endpoint that will display blogs according to tags:

// GET blogs by tags

module.exports = async (server, { hdbCore, logger }) => {

    server.route({
        url: '/blogs/:tags',
        method: 'GET',
        handler: (request) => {
          logger.debug(request);
          request.body= {
            operation: 'sql',
            sql: `SELECT * FROM collection.blogs WHERE tags LIKE '%${request.params.tags}%'`

          };
          return hdbCore.requestWithoutAuthentication(request);
        }
      });
}
Enter fullscreen mode Exit fullscreen mode

Because we've implemented a custom handler here, you must use prevalidation methods to avoid bypassing user authentication. Read more about it here.

Testing our endpoint:

Image description

The final route file is as follows:

'use strict';

module.exports = async (server, { hdbCore, logger }) => {

    // GET blogs data
    server.route({
        url: '/blogs',
        method: 'GET',
        handler: (request) => {
          logger.debug(request);
          request.body= {
            operation: 'sql',
            sql: 'SELECT * FROM collection.blogs'
          };
          return hdbCore.requestWithoutAuthentication(request);
        }
      });

    // GET blogs by tags    
    server.route({
        url: '/blogs/:tags',
        method: 'GET',
        handler: (request) => {
          logger.debug(request);
          request.body= {
            operation: 'sql',
            sql: `SELECT * FROM collection.blogs WHERE tags LIKE             
                    '%${request.params.tags}%'`

          };
          return hdbCore.requestWithoutAuthentication(request);
        }
      });
}
Enter fullscreen mode Exit fullscreen mode

Our API has been set up now. Let's make a project and put it into action.

Designing The Frontend

Initialize the React app using create-react-app:

npx create-react-app tech-blogs-harperdb
cd tech-blogs-harperdb
npm start
Enter fullscreen mode Exit fullscreen mode

To begin, make a Header component for the Title and Description section:

import "./Header.css";
const Header = () => {
    return (
        <div className="header">
            <h1>🔥Tech Blogs</h1>
            <p>
                A collection of amazing technical blogs found on web for
                developers.
            </p>
        </div>
    );
};
export default Header;
Enter fullscreen mode Exit fullscreen mode

All the CSS files can be found here: tech-blogs

We've included a Footer component as well. You can find the code here: tech-blogs-github

Image description

After that, make the card component. I'm going to call it BlogCard:
For now, all the values we're passing are hard-coded.

import React from "react";
import "./BlogCard.css";

function BlogCard({ icon, title, description, twitter_url, blog_url, tags }) {
    return (
        <div>
            <div className="blogs-list">
                <div className="container">
                    <div className="card">
                        <div className="head">
                            <div className="icon">
                                <span>🚀</span>
                            </div>
                            <div className="title">
                                <h2>title</h2>
                            </div>
                        </div>
                        <div className="tags">
                            <p>react</p>
                        </div>
                        <div className="description">
                            <p>description</p>
                        </div>

                        <div className="flex-bottom">
                            <div className="social-icons">
                                <div className="twitter">
                                    <a href="#">
                                        <i className="fa-brands 
                                        fa-twitter"></i>
                                    </a>
                                </div>
                            </div>
                            <div className="visit-btn">
                                <a
                                    href="#"
                                    target="_blank"
                                    rel="noreferrer"
                                 >
                                    <button>Visit Blog</button>
                                </a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default BlogCard;
Enter fullscreen mode Exit fullscreen mode

Image description

This was all for the front-end.

It's time to put the API endpoints we developed in HarperDB Studio to work.

Display All Blogs from API:

Step 1: Create a file Blogs/Blogs.js under components folder:

Image description

Step 2: Create a component called Blogs and initialize the states:

import React, { useState, useEffect } from "react";

const Blogs = () => {
    const [isLoading, setIsLoading] = useState(true);
    const [blogs, setBlogs] = useState([]);
    }

export default Blogs;
Enter fullscreen mode Exit fullscreen mode

Step 3: To fetch the blogs data from our API, initialize the useEffect method:

Your fetch url will be as follows:
{custom_functions_url}/{project_name}/{route_url}

useEffect(() => {
        fetch("<CUSTOM_FUNCTIONS_URL>/api/blogs")
            .then((response) => response.json())
            .then((data) => {
                setBlogs(data);
                setIsLoading(false);
            });
    });
Enter fullscreen mode Exit fullscreen mode

Step 4: Render the blog component:

return (
        <div className="blogs_data">
            <Header />
            <div>
                {isLoading ? (
                    <h2
                        style={{
                            display: "flex",
                            alignContent: "center",
                            justifyContent: "center",
                            padding: "5rem",
                        }}
                    >
                        Loading.. ⌛
                    </h2>
                ) : (
                    <div>
                        {blogs.map((blog) => {
                            return (
                                <BlogCard
                                    title={blog.title}
                                 description={blog.description}
                                    icon={blog.icon}
                                  twitter_url={blog.twitter_url}
                                    blog_url={blog.blog_url}
                                    tags={blog.tags}
                                />
                            );
                        })}
                    </div>
                )}
            </div>
        </div>
    );
Enter fullscreen mode Exit fullscreen mode

Here's what our final Blogs component will look like:

import React from "react";
import { useState, useEffect } from "react";
import "./Blogs.css";
import BlogCard from "../BlogCard/BlogCard";
const Blogs = () => {
    const [isLoading, setIsLoading] = useState(true);
    const [blogs, setBlogs] = useState([]);
    const [tags, setTags] = useState([]);
    useEffect(() => {
        fetch(
            `https://functions-tech-blogs-shreya.harperdbcloud.com/api/blogs/${tags}`
        )
            .then((res) => res.json())
            .then((data) => {
                setBlogs(data);
                setIsLoading(false);
            });
    }, [tags]);

    const allTags = ["HTML", "CSS", "JavaScript", "React"];
    function chooseTag(tag) {
        setTags(tag);
    }

    return (
        <div>
            {isLoading ? (
                <h2 className="loading_el">Loading.. ⌛</h2>
            ) : (
                <div>
                    <div className="nav_tags">
                        {allTags.map((tag) => {
                            return (
                                <div
                                    className="tags_el"
                                    onClick={() => chooseTag(tag)}
                                >
                                    <p>{tag}</p>
                                </div>
                            );
                        })}
                    </div>
                    <div>
                        {blogs.map((blog) => {
                            return (
                                <div>
                                    <BlogCard
                                        key={blog.id}
                                        title={blog.title}
                                        description={blog.description}
                                        icon={blog.icon}
                                        twitter_url={blog.twitter_url}
                                        blog_url={blog.blog_url}
                                        tags={blog.tags}
                                    />
                                </div>
                            );
                        })}
                    </div>
                </div>
            )}
        </div>
    );
};

export default Blogs;
Enter fullscreen mode Exit fullscreen mode

Step 5: Congratulations! You've successfully used your first API endpoint:

Image description

Step 6: Now let's use the second endpoint which returns blogs according to tags requested from the route URL /blogs/:tags

const [tags, setTags] = useState([]);

useEffect(() => {
        fetch(
            `https://functions-tech-blogs-shreya.harperdbcloud.com/api/blogs/${tags}`
        )
            .then((res) => res.json())
            .then((data) => {
                setBlogs(data);
                setIsLoading(false);
            });
    }, [tags]);

    const allTags = ["HTML", "CSS", "JavaScript", "React"];

    function chooseTag(tag) {
        setTags(tag);
    }
Enter fullscreen mode Exit fullscreen mode

Stage 7: We've set a dynamic routing as /${tags}. The function chooseTag will set the active tag for this route.

Updating the return method:

return (
        <div>
            {isLoading ? (
                <h2 className="loading_el">Loading.. ⌛</h2>
            ) : (
                <div>
                    <div className="nav_tags">
                        {allTags.map((tag) => {
                            return (
                                <div
                                    className="tags_el"
                                    onClick={() => 
                                    chooseTag(tag)}
                                >
                                    <p>{tag}</p>
                                </div>
                            );
                        })}
                    </div>
                    <div>
                        {blogs.map((blog) => {
                            return (
                                <div>
                                    <BlogCard
                                        key={blog.id}
                                        title={blog.title}
                                  description={blog.description}
                                        icon={blog.icon}
                                  twitter_url={blog.twitter_url}
                                        blog_url={blog.blog_url}
                                        tags={blog.tags}
                                    />
                                </div>
                            );
                        })}
                    </div>
                </div>
            )}
        </div>
    );
Enter fullscreen mode Exit fullscreen mode

Great! We can now view blogs by selecting categories too:

Image description

That's it. You've used HarperDB Custom Functions successfully in your app.

Conclusion

Now that you have learned how to build a collection of blogs, you can take this further and use HarpedBD and React to create a blog of your own. The best way to learn from tutorials is taking what you have learned and using it to build a project of your own.

Building a project of your own will help you to take advantage of the HarperDB’s Custom Functions. HarperDB Studio is beginner friendly and their tutorials are direct to the point. Moreover, HarperDB is a better fit for projects where you need SQL and NoSQL, rapid application development, hybrid cloud, integration, edge computing and distributed computing.

Access the full code here: tech-blogs-github
Visit Tech Blogs here: tech-blogs.vercel.app

Top comments (1)

Collapse
 
ksound22 profile image
Kolade Chris

Awesome article man