<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jeffrey Asilo</title>
    <description>The latest articles on Forem by Jeffrey Asilo (@jeffrey125).</description>
    <link>https://forem.com/jeffrey125</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F881413%2F26535bc8-232a-4c54-a9ae-2812fb3f14ac.jpg</url>
      <title>Forem: Jeffrey Asilo</title>
      <link>https://forem.com/jeffrey125</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jeffrey125"/>
    <language>en</language>
    <item>
      <title>Dev.to and GitHub REST API on my Portfolio site.</title>
      <dc:creator>Jeffrey Asilo</dc:creator>
      <pubDate>Thu, 28 Jul 2022 08:36:38 +0000</pubDate>
      <link>https://forem.com/jeffrey125/devto-and-github-rest-api-on-my-portfolio-site-jp3</link>
      <guid>https://forem.com/jeffrey125/devto-and-github-rest-api-on-my-portfolio-site-jp3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi everyone!&lt;/p&gt;

&lt;p&gt;It's me again and today I'm going to talk about how I used GitHub and Dev.to REST API to connect on my Portfolio site. By the way, this blog post is related to my series called Portfolio Site Journey, and if you haven't read my first post regarding this series, kindly check it out then visit my &lt;a href="https://jeffreyasilo.com/" rel="noopener noreferrer"&gt;Portfolio site&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of using GitHub and Dev.to REST API
&lt;/h2&gt;

&lt;p&gt;The following are the benefits that I experienced using the APIs. First, anything you change from your Dev.to and GitHub account will reflect also on your Portfolio site. Second, it teaches you how to properly consume an API and handle its incoming JSON data; and properly render it on your Frontend. Lastly, it also teaches you how to do some backend coding and the list goes on. However, this type of functionality can be beneficial to a beginner who wants to make his/her first portfolio website because it lets you experience the Frontend and Backend of your web-app.&lt;/p&gt;

&lt;p&gt;For this blog post we're going to use Next.js &lt;strong&gt;getStaticProps&lt;/strong&gt; and &lt;strong&gt;getServerSideProps&lt;/strong&gt; function for ISR and SSR capabilities. Also I'm going to use &lt;strong&gt;Axios&lt;/strong&gt; for fetching JSON data. If you want to know more about the technology and tools that I've mentioned here, kindly refer to the last part of this blog post for the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up your Axios Instance and Env variables
&lt;/h2&gt;

&lt;p&gt;There's this unique feature of Axios that lets you create an instance of it; so that you can reuse that base configuration on request that has the same config when getting JSON data. This is helpful because it makes your code DRY and clean to read.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;GitHub Instance&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios';

const getGithub = axios.create({
  baseURL: 'https://api.github.com',
  headers: { Authorization: `Bearer ${process.env.GITHUB_PAT}` },
});

export default getGithub;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dev.to Instance&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios';

const getDev = axios.create({
  baseURL: 'https://dev.to/api',
  headers: {
    'api-key': process.env.DEV_KEY as string,
  },
});

export default getDev;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;baseURL&lt;/strong&gt; is the base URL endpoint of your API and according to GitHub docs its &lt;code&gt;https://api.github.com&lt;/code&gt; and for Dev.to &lt;code&gt;https://dev.to/api&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;headers&lt;/strong&gt; are the HTTP headers that you want to put in, and in my case, I want to put an Authorization headers so that GitHub doesn't limit my request.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Environment Variables in Next.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may see the &lt;code&gt;process.env.NEXT_PUBLIC_GITHUB_PAT&lt;/code&gt; and &lt;code&gt;process.env.DEV_KEY&lt;/code&gt; in there and those are Environment variables, and by definition, these are variables in your system that describe your environment.&lt;/p&gt;

&lt;p&gt;By default Next.js only expose your .env variables on server-side however if you really need to expose a .env variable on your client-side you will need to define your variable with NEXT_PUBLIC_&lt;em&gt;variableNameHere&lt;/em&gt; but never use NEXT_PUBLIC if you are storing a very important API key!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up Env variables and Storing Dev.to and GitHub API key&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting the API keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Github API Key&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;Generate your GitHub PAT API key here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Login and make sure only tick the public_repo permission for the PAT token or any permission you want&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For Dev.to API Key&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/settings/extensions"&gt;Generate your Dev.to API key here&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;After getting the API keys its time to store it in a .env variable&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a .env.local file on the root folder of your project&lt;/li&gt;
&lt;li&gt;Inside the .env.local define your env variables in there
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GITHUB=ApiKeyHere
DEVTO=ApiKeyHere
NEXT_PUBLIC_SOMETHINGPUBLIC=ExampleOnly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To access this env variables make sure you restart your Next.js and access the variables by using &lt;code&gt;process.env.varNameHere&lt;/code&gt; and &lt;code&gt;process.env.NEXT_PUBLIC_varNameHere&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So why use a Environment variable?&lt;/strong&gt;&lt;br&gt;
From my knowledge, it's a good practice to store any api keys on your env variable so that your code makes it more DRY. And if there's a change on your api key, you just need to go to your .env.local file and change the api key in there.&lt;/p&gt;

&lt;p&gt;Also, it doesn't expose your API keys on your codebase as long as you dont use NEXT_PUBLIC_&lt;em&gt;variableNameHere&lt;/em&gt; because this type of env variable will always be exposed on the client side.&lt;/p&gt;

&lt;p&gt;So now we're ready to connect to the API and fetch some data in there!&lt;/p&gt;


&lt;h2&gt;
  
  
  Connecting with the API and Rendering the Data Response
&lt;/h2&gt;

&lt;p&gt;Now, it's time to fetch our data using getStaticProps and getServerSideProps.&lt;/p&gt;

&lt;p&gt;For Dev.To, I'm going to use getStaticProps since the data incoming on my blog post is not always changing, and using SSG is more faster than using SSR. While for Github, I'm going to use SSR since I'm going to utilize the pagination feature of it, however, that specific topic will be on my next post so I hope you'll check it out soon!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dev.To API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose we want to fetch our articles, I'll make a simple component out of it (for simplicity sake, I'm going to apply simple design and ignore some features)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { AxiosError } from 'axios';
import type { NextPage } from 'next';
import { camelCase, isArray, transform, isObject } from 'lodash';

import getDev from '../../src/axios/getDev';

type CamelizeInput = Record&amp;lt;string, unknown&amp;gt; | Array&amp;lt;Record&amp;lt;string, unknown&amp;gt;&amp;gt;;

const camelize = (obj: CamelizeInput) =&amp;gt;
  transform(
    obj,
    (result: Record&amp;lt;string, unknown&amp;gt;, value: unknown, key: string, target) =&amp;gt; {
      const camelKey = isArray(target) ? key : camelCase(key);
      // eslint-disable-next-line no-param-reassign
      result[camelKey] = isObject(value)
        ? camelize(value as Record&amp;lt;string, unknown&amp;gt;)
        : value;
    }
  );

interface DevArticlesParent {
  title: string;
  pageViewsCount: number;
  description: string;
  positiveReactionsCount: number;
  readingTimeMinutes: number;
}

interface DevArticlesType extends Required&amp;lt;DevArticlesParent&amp;gt; {
  id: number;
  tagList: string[];
  commentsCount: number;
  slug: string;
}

interface JSONResDataType {
  articles: DevArticlesType[];
}

interface JSONResArticle {
  data: Record&amp;lt;string, DevArticlesType[]&amp;gt;;
}

const Portfolio: NextPage&amp;lt;JSONResDataType&amp;gt; = ({
  articles,
}: JSONResDataType) =&amp;gt; {
  console.log(articles);
  return (
    &amp;lt;section
      style={{
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        gap: 10,
        width: '100%',
      }}
      aria-label="Article Page Section"
    &amp;gt;
      &amp;lt;h1
        style={{
          fontSize: 24,
          marginBottom: 24,
          fontWeight: 'bold',
          textDecoration: 'underline',
        }}
      &amp;gt;
        My Articles
      &amp;lt;/h1&amp;gt;
      &amp;lt;ul
        style={{
          display: 'flex',
          flexDirection: 'column',
          justifyContent: 'center',
          alignItems: 'center',
          gap: 10,
        }}
      &amp;gt;
        {articles.map((art) =&amp;gt; (
          &amp;lt;li style={{ border: '1px solid black', width: '100%' }} key={art.id}&amp;gt;
            &amp;lt;h1 style={{ fontSize: 24 }}&amp;gt;{art.title}&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;{art.description}&amp;lt;/p&amp;gt;
            &amp;lt;span&amp;gt;{art.pageViewsCount} Views&amp;lt;/span&amp;gt;
            &amp;lt;br /&amp;gt;
            &amp;lt;span&amp;gt;{art.positiveReactionsCount} Reacts&amp;lt;/span&amp;gt;
          &amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/section&amp;gt;
  );
};

export default Portfolio;

export const getStaticProps = async () =&amp;gt; {
  try {
    const resArticles: JSONResArticle = await getDev('/articles/me/published');
    const resArticlesData = resArticles.data;
    const camelizeArticles = camelize(
      resArticlesData
    ) as unknown as DevArticlesType[];

    return {
      props: {
        articles: camelizeArticles,
      },
      // Next.js ISR feature that revalidates the Static page for
      // every 5 seconds
      // Revalidate every 5 seconds
      revalidate: 5,
    };
  } catch (error) {
    const err = error as AxiosError;

    if (err.response) {
      // The request was made and the server responded with a
      // status code that falls out of the range of 2xx

      if (err.response.status === 404) {
        return {
          notFound: true,
        };
      }

      throw new Error(
        `Something went wrong on fetching my blog articles Status 
         code: ${err.response.status}`
      );
    } else if (err.request) {
      // The request was made but no response was received
      // `err.request` is an instance of XMLHttpRequest in the
      // browser and an instance of
      // http.ClientRequest in node.js

      throw new Error('Request was made but no response data received.');
    } else {
      // Something happened in setting up the request that
      // triggered an err

      throw new Error('Something went wrong on fetching my blog articles');
    }
  }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Output:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2443jcwkoo5gifep3r5.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2443jcwkoo5gifep3r5.PNG" alt="ArticlesOutput"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;While for GitHub, let's fetch our GitHub Profile and render it into our Next.js Page (I personally picked this because on my next article, I will share to you how I fetch my GitHub Repository and utilize the Pagination feature of the API)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GITHUB API&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { AxiosError } from 'axios';
import type { GetServerSideProps, NextPage } from 'next';
import { camelCase, isArray, transform, isObject } from 'lodash';
import Image from 'next/image';

import getGithub from '../../src/axios/getGithub';

type CamelizeInput = Record&amp;lt;string, unknown&amp;gt; | Array&amp;lt;Record&amp;lt;string, unknown&amp;gt;&amp;gt;;

const camelize = (obj: CamelizeInput) =&amp;gt;
  transform(
    obj,
    (result: Record&amp;lt;string, unknown&amp;gt;, value: unknown, key: string, target) =&amp;gt; {
      const camelKey = isArray(target) ? key : camelCase(key);
      // eslint-disable-next-line no-param-reassign
      result[camelKey] = isObject(value)
        ? camelize(value as Record&amp;lt;string, unknown&amp;gt;)
        : value;
    }
  );

interface UserDataValues {
  name: string;
  login: string;
  avatarUrl: string;
  location: string;
  hireable: boolean;
  bio: string;
  publicRepos: number;
  ownedPrivateRepos: number;
}

interface PortfolioProps {
  userData: UserDataValues;
}

interface JSONResUser {
  data: UserDataValues;
}

const Portfolio: NextPage&amp;lt;PortfolioProps&amp;gt; = ({ userData }: PortfolioProps) =&amp;gt; {
  const { avatarUrl, name, login, bio, location, hireable, publicRepos } =
    userData;

  return (
    &amp;lt;section
      style={{
        display: 'flex',
        flexDirection: 'column',
        width: '100%',
        justifyContent: 'center',
        alignItems: 'center',
        textAlign: 'left',
      }}
      aria-label="User Profile Card"
    &amp;gt;
      &amp;lt;div style={{ border: '1px solid black', padding: 60 }}&amp;gt;
        &amp;lt;div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
          }}
        &amp;gt;
          &amp;lt;Image
            style={{ borderRadius: 9999 }}
            src={avatarUrl}
            width={300}
            height={300}
            alt="Profile Picture"
          /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;h1 style={{ fontSize: 32, fontWeight: 'bold' }}&amp;gt;{name}&amp;lt;/h1&amp;gt;
        &amp;lt;h2 style={{ fontSize: 24, fontWeight: 'bold' }}&amp;gt;{login}&amp;lt;/h2&amp;gt;
        &amp;lt;h3 style={{ fontSize: 18, fontWeight: 'bold' }}&amp;gt;
          &amp;lt;span&amp;gt;{location}&amp;lt;/span&amp;gt;
        &amp;lt;/h3&amp;gt;
        &amp;lt;p&amp;gt;{bio}&amp;lt;/p&amp;gt;

        &amp;lt;p&amp;gt;
          Looking for job:{' '}
          &amp;lt;span&amp;gt;{hireable ? 'Yes' : 'No, currently busy'}&amp;lt;/span&amp;gt;
        &amp;lt;/p&amp;gt;

        &amp;lt;p&amp;gt;
          Total Repos:
          &amp;lt;span&amp;gt;{publicRepos}&amp;lt;/span&amp;gt;
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/section&amp;gt;
  );
};

export default Portfolio;

export const getServerSideProps: GetServerSideProps = async () =&amp;gt; {
  try {
    // User Data
    const responseUser: JSONResUser = await getGithub('/user');
    const userData = responseUser.data;
    const camelizeUserData = camelize(
      userData as unknown as Record&amp;lt;string, unknown&amp;gt;
    );

    return {
      props: {
        userData: camelizeUserData as unknown as UserDataValues,
      },
    };
  } catch (error) {
    const err = error as AxiosError;
    const errorMessage = new Error('Something went wrong, please try again');

    if (err.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx

      if (err.response.status === 404) {
        return {
          notFound: true,
        };
      }

      if (err.response.status === 403) {
        throw new Error('Forbidden Access!');
      }

      throw errorMessage;
    } else if (err.request) {
      // The request was made but no response was received
      // `err.request` is an instance of XMLHttpRequest in the browser and an instance of
      // http.ClientRequest in node.js

      throw errorMessage;
    } else {
      // Something happened in setting up the request that triggered an err

      throw errorMessage;
    }
  }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhp98uln7ao140d5caa6n.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhp98uln7ao140d5caa6n.PNG" alt="GitHubOutput"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way since we're rendering an image for this component please make sure you add the domain of the image you are rendering on your next.config.js for this example its &lt;code&gt;avatars.githubusercontent.com&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ['avatars.githubusercontent.com'],
  },
};

module.exports = nextConfig;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As per the documentation we need to this is because it protects our app for malicious users.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To protect your application from malicious users, you must define a list of image provider domains that you want to be served from the Next.js Image Optimization API.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;And congratulations! We're now connected to our APIs! The reason why it works? It's because we used getStaticProps and getServerSideProps with the help of our Axios instance.&lt;/p&gt;

&lt;p&gt;getStaticProps runs during build-time, and our Axios instance fetches the data from Dev.to API with getStaticProps it makes a static web page during build-time. It is actually faster than its counterpart getServerSideProps since getServerSideProps always run on run-time(Every Request). However, the only problem of using getStaticProps is, if there's any changes on the data because it will not render on our app as it's only a one-time request. Now, with the revalidate property, everything changes which makes our getStaticProps an Incremental Static Regeneration for the reason our page revalidates for x amount of seconds and renders it while having the performance and optimization of a static webpage.&lt;/p&gt;

&lt;p&gt;Meanwhile, our getServerSideProps runs on run-time(Every Request) so our data is always updated, and we always render an updated data. This is good if you want to render a data that is always changing or implement a SSR pagination.&lt;/p&gt;

&lt;p&gt;Both Next.js data fetching runs on server-side code so don't worry about putting any sensitive data on it, because it will never ship on the client's browser. Also this is the reason why our Next.js is SEO-friendly since it builds the HTML files on the server rather than on the client side.&lt;/p&gt;

&lt;p&gt;Anyway, this is my high-level definition and also from my knowledge on Next.js getStaticProps, ISR and getServerSideProps. If you want to know more about these features, please refer to the last part of this article for the references.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Connecting to Dev.to and GitHub REST API is a fun experience since I've learned a lot during the course of this journey. With this connection to the API, I'm confident enough that everything on my portfolio site is updated, thus making my future recruiters see my updated Projects and Articles. You can also play around with the API and fetch other data, just refer to its documentation which is located on my Reference part.&lt;/p&gt;

&lt;p&gt;Thank you for reading my second post of the series, I would really appreciate any feedback on my codebase. Thanks in advance! 🙂&lt;/p&gt;

&lt;p&gt;I also hope you'll tune in to my next posts!&lt;/p&gt;




&lt;h3&gt;
  
  
  Reference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.forem.com/api/" rel="noopener noreferrer"&gt;Dev.to REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/rest" rel="noopener noreferrer"&gt;GitHub REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/api-reference/data-fetching/get-static-props" rel="noopener noreferrer"&gt;getStaticProps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props" rel="noopener noreferrer"&gt;getServerSideProps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration" rel="noopener noreferrer"&gt;Incremental Static Regeneration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://axios-http.com/docs/intro" rel="noopener noreferrer"&gt;Axios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/basic-features/environment-variables" rel="noopener noreferrer"&gt;Next.js Environment Variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Sharing my portfolio website</title>
      <dc:creator>Jeffrey Asilo</dc:creator>
      <pubDate>Sat, 16 Jul 2022 15:11:58 +0000</pubDate>
      <link>https://forem.com/jeffrey125/my-journey-on-my-portfolio-website-5d8n</link>
      <guid>https://forem.com/jeffrey125/my-journey-on-my-portfolio-website-5d8n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi everyone!&lt;/p&gt;

&lt;p&gt;I want to share to all of you that my portfolio website is now live! It is connected to Github REST API and Dev.to REST API for the JSON data.&lt;/p&gt;

&lt;p&gt;You may check it out &lt;a href="https://jeffreyasilo.com/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason why I use Next.js is because I'm planning to maintain my portfolio website in a long-term basis and start a beginner tutorial for those who are aspiring to shift in this industry. Also, the features of Next.js like SSG, SSR, ISR, Link component, Image optimization and many more, totally fit on my needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  My thoughts on my Portfolio website
&lt;/h2&gt;

&lt;p&gt;Who would've have thought that a graduate of a marketing degree a few years ago can now build web applications and a website from scratch.&lt;/p&gt;

&lt;p&gt;Shifting from a different industry is not an easy task as it takes a lot of time and effort to be considered competent compared to those who already have a background in the IT industry. However, that doesn't hinder me on achieving on my dreams as long as you have the passion and grit on what you are working on, you will surely be competent in no time.&lt;/p&gt;

&lt;p&gt;On a side note, I am grateful that I had the opportunity to learn and acquire the skills and knowledge in marketing. It made me push even more to do the things that I want since it gave me confidence to hone my other talents and soft skills, which I guess an edge whenever I pursue in IT Industry. I see this an upskill on my part and I am definitely happy.&lt;/p&gt;

&lt;p&gt;Seeing my project from scratch to production makes me feel proud and fulfilled because of what I've achieved. As a person who started my self-study journey last year, I am proud to say that this is now the result of my grit and passion for web development. Although I'm comfortable building a web-app or website from scratch, there are still a lot of things to discover and explore. The grind never stops when it comes to upskilling and on learning new technology.&lt;/p&gt;




&lt;h3&gt;
  
  
  Tech and Tools Used in my Portfolio Site
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Next.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TypeScript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tailwindcss&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Framer-motion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SendGrid&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React Hook Form&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vercel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Axiom&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checkly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This post is meant to be a series of articles related on my journey on building my portfolio website. I will share here what I've learned during the process and teach some basic tutorial on the listed tech and tools on building on my portfolio site.&lt;/p&gt;

&lt;p&gt;Thank you for reading and stay tuned for the series! 🙂&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Sharing my To-do-list app.</title>
      <dc:creator>Jeffrey Asilo</dc:creator>
      <pubDate>Thu, 07 Jul 2022 10:30:51 +0000</pubDate>
      <link>https://forem.com/jeffrey125/sharing-my-to-do-list-app-5g49</link>
      <guid>https://forem.com/jeffrey125/sharing-my-to-do-list-app-5g49</guid>
      <description>&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;Hi Everyone! This is going to be my first blog post in dev.to and it's all about a To-do-list web app because on my programming journey it is the first web app that I made from scratch and it's sentimental to me because it made me escape the dreaded tutorial hell problem of a newbie and it made me confident on my programming skills.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So what is a To-do-list web app? a To-do-list web app is a CRUD app that lets you store your To-do in a web app that has a functionality of Create, Read, Update and Delete in short CRUD on how to interact with your data in storage, and most web app has this kind of functionality, that's why making a to-do-list web app is the go-to project to make if you are a beginner or you just want to test a new framework/library and by the way there is a dedicated GitHub repo that has different to-do-list built on a wide variety of framework you can check it here:  &lt;a href="https://github.com/tastejs/todomvc"&gt;tastejs/todomvc&lt;/a&gt; for more information.&lt;/p&gt;




&lt;h2&gt;
  
  
  To-do-list v1
&lt;/h2&gt;

&lt;p&gt;My first version of a To-do-list web app is built on Vanilla JS with an MVC architecture pattern.&lt;/p&gt;

&lt;p&gt;I built this project using Vanilla JS and store my to-do in localStorage because my only goal is just to release an MVP and improve it along the way on my self-study journey.&lt;/p&gt;

&lt;p&gt;Live link: &lt;a href="https://todo-list-webapp-dun.vercel.app/"&gt;Simple To-do-list webapp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/jeffrey125/todo-list-webapp"&gt;todo-list-webapp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've learned a lot on my first version of my To-do-list web app first separation of concerns on MVC and debugging a web app is easy when you use MVC, DOM Event bubbling and propagation, and many more. Although MVC on a To-do-list web app might be an overkill for such a project I only just want to test the new knowledge that I gained when I starting in JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  To-do-list v2
&lt;/h2&gt;

&lt;p&gt;Now I want to share with all of you my version 2 of a To-do-list web app which has improved design and it is a PWA that works without the internet on all browsers that support PWA installation. When you visit my web app after some interactions with the app the browser will show a popup that my web app is installable and after you've installed it's now offline ready it also behaves as a native-app-like experience. This is all possible because of a TS script called service-worker.ts&lt;/p&gt;

&lt;p&gt;Live link: &lt;a href="https://todo-list-webapp-v2.vercel.app/"&gt;todo-list-webapp-v2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/jeffrey125/todo-list-webapp-v2"&gt;todo-list-webapp-v2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Techs and Tools used for my To-do-list version 2 are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;tailwindcss&lt;/li&gt;
&lt;li&gt;Framer-motion&lt;/li&gt;
&lt;li&gt;pwa-assets-generator&lt;/li&gt;
&lt;li&gt;Cypress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've learned a lot of new techs and tools during the development phase of my to-do-list version 2. First is React is a game-changer on my front-end development skills because it's easy to make a front-end UI that is optimized for every modern device. I also want to mention TypeScript a superset of JavaScript which is a strongly typed language that can catch an error before your code runs. For those who are starting to learn in web dev, I highly recommend learning TypeScript after you're comfortable with JavaScript because it's better to have many wtf bugs that TypeScript catches before your app runs.&lt;/p&gt;

&lt;p&gt;I also what to emphasize tailwindcss and framer-motion as a game-changer for designing and animating complex animations on my UI. Tailwindcss is a utility-first CSS framework that helps you design your front-end UI with modern-like design and framer-motion a production-ready animation library that lets you animate complex animation on your react component. I recommend you try those if you haven't tried them, but before you try those that I've mentioned be sure you are comfortable with vanilla CSS, or else you won't appreciate the power of tailwindcss and framer-motion.&lt;/p&gt;

&lt;p&gt;Lastly, along the way, I've also learned Cypress a front-end testing tool that tests your app on a real browser. Cypress was designed as an E2E testing tool at first but recently they released a Component testing in which you can test your components in an isolated environment think of it like a mix of Storybook + React Testing Library + Jest it's cool right? So right now according to their docs cypress can now write all types of tests including E2E, Integration tests, and Unit tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It was a fun ride building this project and It made me appreciate our industry because there are many techs and tools that can solve your problems and it's just up to you what you are going to use in order to solve a problem.&lt;/p&gt;

&lt;p&gt;If you want to know more about my repos here's my Github repo link:&lt;a href="https://github.com/jeffrey125?tab=repositories"&gt;jeffrey125&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading my first blog post and please stay tuned if you want to read more about my blogs, currently, I'm building my portfolio website which is built on next.js&lt;/p&gt;




&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.dev/learn/pwa/"&gt;PWA docs&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npmjs.com/package/pwa-asset-generator"&gt;pwa-assets-generator&lt;/a&gt; A cool package to make a simple PWA assets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://tailwindcss.com/docs/installation"&gt;tailwindcss docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.framer.com/docs/"&gt;framer-motion docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.cypress.io/"&gt;Cypress docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>react</category>
    </item>
  </channel>
</rss>
