<?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>DEV Community: Ahmed Altaai</title>
    <description>The latest articles on DEV Community by Ahmed Altaai (@ahmedaltaai).</description>
    <link>https://dev.to/ahmedaltaai</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%2F380235%2Fc1d9d5ad-1438-47e3-a652-c6cdf011f301.jpg</url>
      <title>DEV Community: Ahmed Altaai</title>
      <link>https://dev.to/ahmedaltaai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedaltaai"/>
    <language>en</language>
    <item>
      <title>Create subdomains in express.js with vhost in Heroku and Namecheap</title>
      <dc:creator>Ahmed Altaai</dc:creator>
      <pubDate>Fri, 16 Oct 2020 15:35:09 +0000</pubDate>
      <link>https://dev.to/ahmedaltaai/create-subdomains-in-express-js-with-vhost-in-heroku-and-namecheap-1emk</link>
      <guid>https://dev.to/ahmedaltaai/create-subdomains-in-express-js-with-vhost-in-heroku-and-namecheap-1emk</guid>
      <description>&lt;p&gt;Wondering how to replicate the Apache vhost feature in Express.js? Virtual hosting is a method for hosting multiple domain names on a single server. In case you are new to vhost, it allows a web server to listen on a single port and serve different web apps depending on the domain name or the subdomain. Implementing such a feature in Express.js is very easy. &lt;/p&gt;

&lt;p&gt;I will be using Heroku as a cloud hosting provider with Namecheap as a domain registrar and Node.js (Express.js) for the Back-End displaying my portfolio which is made with Vue.js.&lt;/p&gt;

&lt;h1&gt;
  
  
  The goal
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Create and connect subdomain on the services&lt;/li&gt;
&lt;li&gt;Directory structure&lt;/li&gt;
&lt;li&gt;Node.js server setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic node.js/ express.js knowledge&lt;/li&gt;
&lt;li&gt;Payed Dyno (hobby)&lt;/li&gt;
&lt;li&gt;The will to learn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets get started!&lt;/p&gt;

&lt;h1&gt;
  
  
  Create and connect subdomain
&lt;/h1&gt;

&lt;p&gt;Lets start with Heroku where you need to be logged in:&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602841999594%2FWnGvXbuxS.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602841999594%2FWnGvXbuxS.png" alt="heroku login.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After login your dynos will be displayed...&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602840726382%2FH0St-aNov.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602840726382%2FH0St-aNov.png" alt="after login.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick the one you want to use.&lt;/li&gt;
&lt;li&gt;Go to settings&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602841011800%2FQ6zjxtTaX.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602841011800%2FQ6zjxtTaX.png" alt="dyno settings.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scroll down to domains&lt;/li&gt;
&lt;li&gt;Click on "Add domain"&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602843597535%2FFpd5MF0dK.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602843597535%2FFpd5MF0dK.png" alt="add domain.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter wished subdomain&lt;/li&gt;
&lt;li&gt;for the sake of this tutorial it will be test.ahmedaltaai.com &lt;/li&gt;
&lt;li&gt;Click next&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602843810118%2FnoFYD1cFZ.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602843810118%2FnoFYD1cFZ.png" alt="enter subdomain.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy DNS Target&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602844744974%2FLEJEBLDMR.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602844744974%2FLEJEBLDMR.png" alt="after entering subdomain.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will show you "waiting" on heroku until you connect it to a domain with DNS Target&lt;/p&gt;

&lt;h3&gt;
  
  
  Now lets head to namecheap to connect DNS Target
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Login&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842215216%2F-vI0XI72c.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842215216%2F-vI0XI72c.png" alt="namecheap login.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Domain List&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842847365%2FCJBwVoyrK.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842847365%2FCJBwVoyrK.png" alt="namecheap domain list.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;choose your domain and click on "manage"&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842898692%2FACQwyOELc.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602842898692%2FACQwyOELc.png" alt="namecheap manage domain list.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on advanced DNS and scroll down to "host records" &lt;/li&gt;
&lt;li&gt;Click "add new record"&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602845163133%2F4S2eOfhlp.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602845163133%2F4S2eOfhlp.png" alt="namecheap add new record.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select "CNAME" from the dropdown menu in the type column&lt;/li&gt;
&lt;li&gt;Enter your subdomain in the "host" column&lt;/li&gt;
&lt;li&gt;Paste in your "DNS Target" in The "value" column&lt;/li&gt;
&lt;li&gt;Click on the "greenish" check mark to save&lt;/li&gt;
&lt;/ul&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846092256%2FiHH3mLk76.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846092256%2FiHH3mLk76.png" alt="namecheap add subdomain.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  That was it for the registeration of the subdomain
&lt;/h3&gt;

&lt;p&gt;Now on heroku there would be a red flag because of the SSL certificate. It will take some time for it to be activated on the subdomain (5-10 min).&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846650372%2FHuOLM5uJP.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846650372%2FHuOLM5uJP.png" alt="heroku wait for dns and SSL.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some time has passed it will say that everything is OK&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846699133%2FpyaFEJ-YH.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602846699133%2FpyaFEJ-YH.png" alt="heroku subdomain ok.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Directory structure
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Root folder

&lt;ul&gt;
&lt;li&gt;server.js&lt;/li&gt;
&lt;li&gt;public (main website)&lt;/li&gt;
&lt;li&gt;index.html&lt;/li&gt;
&lt;li&gt;style.css&lt;/li&gt;
&lt;li&gt;main.js&lt;/li&gt;
&lt;li&gt;subdomains&lt;/li&gt;
&lt;li&gt;test (project directory)

&lt;ul&gt;
&lt;li&gt;server.js&lt;/li&gt;
&lt;li&gt;public&lt;/li&gt;
&lt;li&gt;index.html&lt;/li&gt;
&lt;li&gt;style.css&lt;/li&gt;
&lt;li&gt;main.js&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In the root directory a creation of an express app is needed&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;npm init&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 then&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;npm install express&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
. Now we create our server.js file which if not changed during the "npm package initialization process" will be named index.js by default. &lt;br&gt;
It can be checked in the package.json file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "scripts": {
    "start": "node server.js"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every website needs its own express app to be rendered by. In the root directory there is the one express app to rule them all. In our case to route the views for the specified URL.&lt;/p&gt;

&lt;p&gt;As seen above every project directory has a server.js file which is the node server (express app) and the public directory where the website is which will be rendered in the browser.&lt;/p&gt;

&lt;p&gt;to serve  are the website files e.g. index.html / style.css / main.js. It is needed to put them all in one directory e.g. public / client / frontend because we will be serving/ rendering the view from server.js.&lt;/p&gt;

&lt;p&gt;The subdomain directory will hold all the other directories of the individual projects which will be rendered when visiting the registered subdomain in our case it will be test.ahmedaltaai.com&lt;/p&gt;

&lt;h1&gt;
  
  
  Nodejs server setup
&lt;/h1&gt;

&lt;h4&gt;
  
  
  Lets take a look at server.js for displaying the main website
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// importing express
const express = require('express')

// The path module provides utilities for working with 
// file and directory paths
const path = require('path')

// app is an instance of express
// why app? I DON'T KNOW it is the law
const app = express()

// serves files from public directory 
// which contains the main website
const website = express.static(path.join(__dirname, '/public')

// Mounts the specified middleware function or functions 
// at the specified path: the middleware function is executed 
// when the base of the requested path matches path.
app.use(website)

// routes an HTTP request, where METHOD is the HTTP 
// method of the request, such as 
// GET, PUT, POST, and so on, in lowercase. 
app.get('/', (req, res) =&amp;gt; {
// The path.join() method joins all given path segments together
// using the platform-specific separator as a delimiter, 
// then normalizes the resulting path.
 res.render(path.join(__dirname, '/public'))
})

// in many environments (e.g. Heroku), and as a convention,
// you can set the environment variable PORT 
// to tell your web server what port to listen on.
const port = process.env.PORT || 8080

// binds and listens for connections on the specified host and port.
app.listen(port)

// just logging out on which port the app is listening
console.log("listening on... " + port)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when visiting yourwebsite.com the index.html inside the public directory will be rendered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now lets use vhost to display the subdomains
&lt;/h3&gt;

&lt;p&gt;To display the subdomains we need to create a module out of the test directory's express app which is named server.js&lt;/p&gt;

&lt;p&gt;It is nearly the same as a normal express app except we won't use&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;app.listen(...)&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 rather we will export it as a module and make it run on the same port and server which is being used for the main website.&lt;/p&gt;
&lt;h4&gt;
  
  
  test subdomains express app
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const path = require('path')
const app = express()

app.use(express.static(path.join(__dirname, './public')))

app.get('/', (req, res) =&amp;gt; {
  res.render(path.join(__dirname, './public'))
})

module.exports = app

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

&lt;/div&gt;

&lt;h4&gt;
  
  
  Now lets configure vhost in the root express app.
&lt;/h4&gt;

&lt;p&gt;vhost needs to be installed through npm in the root directory&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;npm install vhost&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;then import it as we did with express and path with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


#### main express app


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

&lt;/div&gt;

&lt;p&gt;const express = require('express')&lt;br&gt;
const path = require('path')&lt;br&gt;
const vhost = require('vhost')&lt;br&gt;
const app = express()&lt;/p&gt;

&lt;p&gt;const website = express.static(path.join(__dirname, '/public')&lt;/p&gt;

&lt;p&gt;// it is important to have it at the top &lt;br&gt;
// before app.use(website) otherwise it wont work&lt;br&gt;
// the express app which we exported &lt;br&gt;
// is being requires thus it is being executed&lt;br&gt;
// also the code says it should render a view&lt;br&gt;
app.use(vhost('test.ahmedaltaai.com', require('./subdomains/test/public/app')))&lt;/p&gt;

&lt;p&gt;app.use(website)&lt;/p&gt;

&lt;p&gt;app.get('/', (req, res) =&amp;gt; {&lt;br&gt;
 res.render(path.join(__dirname, '/public'))&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;const port = process.env.PORT || 8080&lt;/p&gt;

&lt;p&gt;app.listen(port)&lt;/p&gt;

&lt;p&gt;console.log("listening on... " + port)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


The repository can be found  [here](https://github.com/ahmedaltaai/portfolio-vuejs) 

# I hope you learned something new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>express</category>
      <category>vhost</category>
      <category>node</category>
      <category>heroku</category>
    </item>
    <item>
      <title>How to automate your portfolio website [Part 2]</title>
      <dc:creator>Ahmed Altaai</dc:creator>
      <pubDate>Thu, 15 Oct 2020 11:48:54 +0000</pubDate>
      <link>https://dev.to/ahmedaltaai/how-to-automate-your-portfolio-website-part-2-5b09</link>
      <guid>https://dev.to/ahmedaltaai/how-to-automate-your-portfolio-website-part-2-5b09</guid>
      <description>&lt;p&gt;To have less steps redacting the portfolio every time you publish a blog or push a new project to GitHub, automating it is the right choice.&lt;/p&gt;

&lt;p&gt;In this article, I'd like to share how you can automate publishing your Hashnode blogs to your portfolio website with the help of Hashnodes API, let me show you how I did it.&lt;/p&gt;

&lt;h1&gt;
  
  
  What should be achieved with this project
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Automatically display and link my projects from GitHub&lt;/li&gt;
&lt;li&gt;Automatically display and link my blogs from Hashnode&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Vue.js&lt;/li&gt;
&lt;li&gt;vue-apollo&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The steps I took
&lt;/h3&gt;

&lt;p&gt;After I finished preparing my last post about  &lt;a href="https://ahmeds.tech/how-to-automate-your-portfolio-website-part-1-1" rel="noopener noreferrer"&gt;automating with github api&lt;/a&gt; I started playing with the Hashnode API.&lt;/p&gt;

&lt;h4&gt;
  
  
  Which looks like this
&lt;/h4&gt;

&lt;p&gt;It is a GraphQL playground&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602679236811%2FGgsgGM4pD.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602679236811%2FGgsgGM4pD.png" alt="hashnode_api.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  The documentation tab is next to the scroll bar
&lt;/h4&gt;

&lt;p&gt;I searched for it quite a bit until I found it because it was the first time me seeing this UI&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602679368382%2F4ctgsFKM_.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602679368382%2F4ctgsFKM_.png" alt="hashnode_api_docu_tab.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets start with a step for step explanation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;specify a user
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;username: String!&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 the exclamation mark means it is required to enter what is specified, in this case it is a String.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;age: Int?&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 the question mark means it is not necessary to enter what is specified, in this case it is an Int and it was just an example we only need the one above "username".&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602680921700%2F5jQzWfFI0.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602680921700%2F5jQzWfFI0.png" alt="specify_a_user.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;choose publication&lt;/li&gt;
&lt;li&gt;then posts&lt;/li&gt;
&lt;li&gt;finally pick which data you want retrieve from the API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our case we will need cover image, title, brief(description).&lt;/p&gt;

&lt;p&gt;Also cuid and slug are going to be needed to dynamically link the blog card on your website to direct to the original post. We will discuss it later.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602683127527%2FVYUNhkuz1.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602683127527%2FVYUNhkuz1.png" alt="specify_a_user's_stuff.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm using my username for demonstration, you can use whatever username you like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
    user(username: "ahmedaltaai") {
        publication {
                  posts {
                    coverImage
                    title
                    brief
                    slug
                    cuid
                    }
              }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  This is the result after pressing the play button in the middle of  the screen
&lt;/h3&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602683477511%2FGToBE-k0I.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602683477511%2FGToBE-k0I.png" alt="hashnode_api_data.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Well very nice we did it in the GraphQL playground but how can we do it in our code base?
&lt;/h4&gt;

&lt;p&gt;Because I'm using Vue.js we will be using vue-apollo. There is also a version for React and Angular.&lt;/p&gt;

&lt;p&gt;So we will install the npm package as a dependency with&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i vue-apollo --save&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Afterwards we will find a new js file in our projects src directory "vue-apollo.js"&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602684111236%2FHBYXfdNSZ.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602684111236%2FHBYXfdNSZ.png" alt="vue-apollo-js.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inside the vue-apollo.js file we need to modify two things
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;httpEndpoint&lt;/li&gt;
&lt;li&gt;wsEndpoint (Web Socket)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our API address link goes into the httpEndpoint and the wsEndpoint is going to be set to null.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602684410482%2FjUsKg5Ct_.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602684410482%2FjUsKg5Ct_.png" alt="vue-apollo-js-modifyed.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Now we switch to the component where we will be making the call (I'm not using a state management system such as Vuex)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script&amp;gt;
//we need to import graphql
//gql is the graphql query language

import gql from 'graphql-tag'

export default {
  name: 'blog',

//use the "apollo" object
//to query and retrieve the data

  apollo: {

//add an attribute which has the same name 
//as the field name in the query

    user: gql`
      query {
        user(username: "ahmedaltaai") {
          publication {
            posts {
              coverImage
              title
              brief
              slug
              cuid
            }
          }
        }
      }
    `
  }
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the  &lt;a href="https://apollo.vuejs.org/guide/apollo/queries.html#name-matching" rel="noopener noreferrer"&gt;vue-apollo documentation&lt;/a&gt;  for better understanding about name matchnig &amp;amp; co.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now we can just loop over the apollo object to display the data
&lt;/h3&gt;

&lt;p&gt;We need to loop over the "posts" object which is in "publication" under "user".&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v-for="post in user.publication.posts" :key="post.cuid"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  This is how my component looks like
&lt;/h4&gt;

&lt;p&gt;I will spare you the style section for the sake of the blogs length. You can still see the whole code on my github profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section
        v-for="post in user.publication.posts"
        :key="post.cuid"
        class="card"
      &amp;gt;
        &amp;lt;a :href="`https://ahmeds.tech/${post.slug}`"&amp;gt;
          &amp;lt;div class="cover-image"&amp;gt;
            &amp;lt;img :src="post.coverImage" /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div class="text"&amp;gt;
            &amp;lt;div class="title"&amp;gt;
              &amp;lt;h3&amp;gt;{{ post.title }}&amp;lt;/h3&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div class="description"&amp;gt;
              &amp;lt;p&amp;gt;{{ post.brief }}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/a&amp;gt;
      &amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see I'm using an "a" tag to make my card link to the original post if clicked.&lt;/p&gt;

&lt;p&gt;You have the complete power to do it as you wish!&lt;/p&gt;

&lt;h2&gt;
  
  
  How to modify the URL in the "a" tag
&lt;/h2&gt;

&lt;p&gt;It will depend if you have your own domain or using a subdomain under hashnode.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Own domain&lt;/li&gt;
&lt;li&gt;Subdomain under Hashnode&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Own domain
&lt;/h1&gt;

&lt;p&gt;On  &lt;a href="//api.hashnode.com"&gt;api.hashnode.com&lt;/a&gt; when we queried for the data we requested a "slug"&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A slug is a human-readable, unique identifier, used to identify a resource instead of a less human-readable identifier like an id . You use a slug when you want to refer to an item while preserving the ability to see, at a glance, what the item is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The value of slug will be your post title:&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602688706064%2FyI-fuM9f4.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602688706064%2FyI-fuM9f4.png" alt="own_domain.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So in the "a" tag we want to make the "href" dynamic with a v-bind which I will be shortening to a colon " : " just like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;a :href="`https://ahmeds.tech/${post.slug}`"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;To access the v-for loop "post" element &lt;/p&gt;

&lt;p&gt;I'm putting the link in backticks - which result in template literals (template string) &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Template literals are string literals allowing embedded expressions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I can use "post" attribute from the v-for loop and fetch the slug to append it to the URL which will accumulate to a full link of my individual blog... the blog which is being clicked on.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://ahmeds.tech/how-to-automate-your-portfolio-website-part-1-1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Subdomain under Hashnode
&lt;/h1&gt;

&lt;p&gt;Identical procedure except we now also need the cuid&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Customer user ID (CUID) field is a unique user identifier set by app and website owners.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A blogger's URL without a private domain will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;username&amp;gt;.hashnode.dev/&amp;lt;slug&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;username&amp;gt;.hashnode.dev/&amp;lt;slug&amp;gt;-&amp;lt;cuid&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;I can't tell you why there are those two differences because I don't know. You have to find out which one suites you. If you pay more attention to the URLs when ready on Hashnode then you will notice and understand what I'm talking about here.&lt;/p&gt;

&lt;p&gt;Replace  with your username on Hashnode, hard code it. And take the same procedure with the rest of the URL.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;a :href="`https://&amp;lt;username&amp;gt;.hashnode.dev/${post.slug}`"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;a :href="`https://&amp;lt;username&amp;gt;.hashnode.dev/${post.slug}-${post.cuid}`"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Now the posts should be displaying on your website. Although there is a "long" loading time which I don't like and I think neither do you.
&lt;/h3&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602694011403%2FgsfPSx3X1.gif" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602694011403%2FgsfPSx3X1.gif" alt="withoutLoadingSkeleton.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets make it more professional with a loading skeleton&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading skeleton
&lt;/h3&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602694308770%2Faa2eHx9H_.gif" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602694308770%2Faa2eHx9H_.gif" alt="withLoadingSkeleton.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I won't go into detail on how to create or style a loading skeleton because there are plenty of tutorials which are online. Also it is an opportunity to get your googling skills on fleek :p &lt;/p&gt;

&lt;p&gt;Although I will tell you the challenge I had while setting the skeleton up.&lt;/p&gt;

&lt;h4&gt;
  
  
  Loading state on  &lt;a href="https://apollo.vuejs.org/guide/apollo/queries.html#loading-state" rel="noopener noreferrer"&gt;vue-apollo documentation&lt;/a&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;You can display a loading state thanks to the $apollo.loading prop:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;div v-if="$apollo.loading"&amp;gt;Loading...&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;When I was implementing this function at the beginning it didn't work. It never displayed the skeleton. So I reversed the order of the&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;v-if&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div v-if="!$apollo.loading"&amp;gt;
  &amp;lt;blog-card /&amp;gt;
&amp;lt;/div&amp;gt; 

&amp;lt;div v-else&amp;gt;
  &amp;lt;loading-skeleton /&amp;gt;
&amp;lt;div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case if it is NOT loading, as of NOT fetching any data then show me the blog card with the cover image, title and description else display loading skeleton.&lt;/p&gt;

&lt;h1&gt;
  
  
  Easy Peazy
&lt;/h1&gt;

&lt;p&gt;That was it I hope you learned something new 😃&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>graphql</category>
      <category>vue</category>
      <category>hashnode</category>
    </item>
    <item>
      <title>How to automate your portfolio website [Part 1]</title>
      <dc:creator>Ahmed Altaai</dc:creator>
      <pubDate>Wed, 14 Oct 2020 12:10:19 +0000</pubDate>
      <link>https://dev.to/ahmedaltaai/how-to-automate-your-portfolio-website-part-1-2cg2</link>
      <guid>https://dev.to/ahmedaltaai/how-to-automate-your-portfolio-website-part-1-2cg2</guid>
      <description>&lt;p&gt;To have less steps redacting the portfolio every time you publish a blog or push a new project to GitHub, automating it is the right choice.&lt;/p&gt;

&lt;p&gt;In this article, I'd like to share how you can automate your portfolio website with the help of some APIs, let me show you how I did it.&lt;/p&gt;

&lt;h1&gt;
  
  
  What should be achieved with this project
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Automatically display and link my projects from GitHub&lt;/li&gt;
&lt;li&gt;Automatically display and link my blogs from Hashnode&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Vue.js&lt;/li&gt;
&lt;li&gt;fetch API&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The steps I took
&lt;/h3&gt;

&lt;p&gt;First of all, I was messing around with the github API and have created a user search application with vuejs. Then the idea struck me! If I can search for users and display them this way, there must be a way to automatically display all the repositories on my website.&lt;/p&gt;

&lt;p&gt;So I started looking through the  &lt;a href="https://api.github.com/"&gt;API links&lt;/a&gt; until I found what was needed. Afterwards I looked into the Hashnode API which will be explained in the next article so stay tuned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The GitHub API
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V6d_fUYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601763359943/atz7M0a_O.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V6d_fUYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601763359943/atz7M0a_O.png" alt="api_github.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparing the fetch request
&lt;/h3&gt;

&lt;p&gt;This link will be prepared so we can fetch all the public repositories of the chosen profile.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}"&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;// change {user} with a GitHub username
// remove the curly braces and insert the username
// to retrieve all the public repositories remove everything 
// after repos within the quotation marks

// this is how the link looks like in my case 
"https://api.github.com/users/ahmedaltaai/repos"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  All the work is happening inside a component
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DIazQBtz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601889327728/GSe5L1o7I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DIazQBtz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601889327728/GSe5L1o7I.png" alt="project_component.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requesting the repositories from the GitHub API with the JavaScript fetch API when the the instance is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  created() {
    fetch('https://api.github.com/users/ahmedaltaai/repos')
      .then(res =&amp;gt; res.json())
      .then(data =&amp;gt;
        console.log(data)
      })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The response
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5M0B9XCU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601766714317/MXqaJ9CO0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5M0B9XCU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601766714317/MXqaJ9CO0.png" alt="fetch_response.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Afterwards
&lt;/h3&gt;

&lt;p&gt;Analise the returned data by clicking on the triangle next to the indexed links to display the information within the object which is needed to know which data is being returned and which to use for displaying on the website.&lt;/p&gt;

&lt;p&gt;I placed a red dot next to the information which I want to display:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Language &lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;li&gt;Repository URL&lt;/li&gt;
&lt;li&gt;URL of the project for live preview&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BfNAz3fo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601890409572/m4XOTDZCn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BfNAz3fo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601890409572/m4XOTDZCn.png" alt="fetch_response_data.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets store all the information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing the response into an array
&lt;/h3&gt;

&lt;p&gt;To be able to store the data we first need to create an empty array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data() {
    return {
      // empty array to store the data
      // coming from the api
      repos: []
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then assign the data to the array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Populating the empty array which was created prior
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  created() {
    fetch('https://api.github.com/users/ahmedaltaai/repos')
      .then(res =&amp;gt; res.json())
      .then(data =&amp;gt;
// select the array with this.repos and insert the data into it
        this.repos = data
      })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Looping over the repos
&lt;/h3&gt;

&lt;p&gt;We can use the v-for directive to render a list of items based on an array. The v-for directive requires a special syntax in the form of item in items, where items is the source data array and item is an alias for the array element being iterated on.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v-for="(repo, i) in repos" :key="i"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;To give Vue a hint so that it can track each node’s identity, and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item.&lt;/p&gt;

&lt;h4&gt;
  
  
  This is how my component looks like. I will spare the styling which you can find in my  &lt;a href="https://github.com/ahmedaltaai/portfolio-vuejs"&gt;GitHub repo&lt;/a&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;!-- projects container --&amp;gt;
  &amp;lt;article class="projects__container"&amp;gt;
    &amp;lt;!-- card container --&amp;gt;
    &amp;lt;section class="card" v-for="(repo, i) in repos" :key="i"&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;!-- card header --&amp;gt;
        &amp;lt;header class="header"&amp;gt;
          &amp;lt;div&amp;gt;
            {{ repo.name }}
          &amp;lt;/div&amp;gt;
          &amp;lt;div class="lang"&amp;gt;
            &amp;lt;span class="tag"&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;div&amp;gt;
              {{ repo.language }}
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/header&amp;gt;
        &amp;lt;!-- card body --&amp;gt;
        &amp;lt;div class="description"&amp;gt;
          {{ repo.description }}
        &amp;lt;/div&amp;gt;
        &amp;lt;!-- links / buttons --&amp;gt;
        &amp;lt;footer class="buttons"&amp;gt;
          &amp;lt;a :href="repo.svn_url"&amp;gt;
            &amp;lt;i class="fab fa-github"&amp;gt;&amp;lt;/i&amp;gt;
            CODE
          &amp;lt;/a&amp;gt;
          &amp;lt;a :href="repo.homepage"&amp;gt;
            &amp;lt;i class="fas fa-play-circle"&amp;gt;&amp;lt;/i&amp;gt;
            DEMO
          &amp;lt;/a&amp;gt;
        &amp;lt;/footer&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/section&amp;gt;
  &amp;lt;/article&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  This is how it looks like in the browser
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rkYNa4HR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601892852653/VtAXUo7WC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rkYNa4HR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601892852653/VtAXUo7WC.png" alt="projects.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see it is returning every public repository which I don't want it to; so I will use an if-statement and disclose that it should show only the repos which have a homepage link them.&lt;/p&gt;

&lt;p&gt;This is a common scenario as you can imagine, wanting to conditionally loop through objects. Only actually running the loop on objects that match a given criteria. The question is how do you do it?&lt;/p&gt;

&lt;h4&gt;
  
  
  This is how to do it
&lt;/h4&gt;

&lt;p&gt;Place this if statement after the v-for loop so it has access to the individual item and can figure out if repo.homepage is true or false&lt;/p&gt;

&lt;p&gt;v-if="repo.homepage"&lt;/p&gt;

&lt;p&gt;We want to loop through this repos array using the v-for directive. With each loop iteration we display another repo. But we only want to loop through repos which have a link to a live demo. If a repo doesn't have anything inside the repo.homepage we basically want to skip over it.&lt;/p&gt;

&lt;p&gt;This means if homepage in the individual repo is true then show me the requested details as of name, description and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  The result of the if-statement
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gMkEXI11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601893257317/TQRt_iRcu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gMkEXI11--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601893257317/TQRt_iRcu.png" alt="projects_after_if.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see this would technically work. But we now have empty div elements around each object which can likely interfere with DOM traversal and phantom CSS styling. In addition, it clutters our app and adds unnecessary structure to our HTML markup.&lt;/p&gt;

&lt;p&gt;I should also mention that you are still looping through unwanted repos and running a conditional before breaking and going to the next loop iteration. This might solve the problem visually, but computationally we are still looping through every single repo in the system instead of only the needed ones. Depending on the size of the repos payload, this could lead to performance issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution: computed properties
&lt;/h3&gt;

&lt;p&gt;Instead of looping through all of the repo objects and then checking mid-loop if they meet our criteria, we could just create a subset of our repos, which only represents the wanted repos, with homepage link, and loop only that subset!&lt;/p&gt;

&lt;p&gt;We have the repos as an array so we can use the .filter() method to only return the wanted repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // this function is made to filter every public
    // repo and return only the ones with a homepage in it
    // to overcome empty divs and phantom CSS styling

computed: {
    wantedRepos: function() {
      return this.repos.filter(repo =&amp;gt; {
        return repo.homepage
      })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  And now we update the v-for loop
&lt;/h4&gt;



&lt;p&gt;&lt;code&gt;v-for="(repo, i) in wantedRepos" :key="i"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  The new outcome with computed properties
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZBLaOtol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897021718/YBPSSMkTH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZBLaOtol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897021718/YBPSSMkTH.png" alt="projects_computed.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;90% of the work is done. There is one more thing I want to add to the cards I want to add colored language tags the same as on GitHub.&lt;/p&gt;

&lt;h4&gt;
  
  
  example
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w72WD_cZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897231836/MUptHjFaS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w72WD_cZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897231836/MUptHjFaS.png" alt="langTags.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Hold up
&lt;/h1&gt;

&lt;p&gt;You may be asking: well how can I add a description and a homepage link to my repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Say no more
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to the desired repository&lt;/li&gt;
&lt;li&gt;Click the cog icon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jOfI5TbF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897672482/n9DXqFBf8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jOfI5TbF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897672482/n9DXqFBf8.png" alt="description.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fill the fields out and click save changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2mO3FeUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897694254/NL7qEO2OP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2mO3FeUX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1601897694254/NL7qEO2OP.png" alt="description2.PNG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Now lets go back to the colored language tags
&lt;/h2&gt;

&lt;p&gt;First of all put a class or id on the languages element. I used a class and named it 'lang'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;header class="header"&amp;gt;
    &amp;lt;div&amp;gt;
      {{ repo.name }}
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="lang"&amp;gt;
        &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
      &amp;lt;div&amp;gt;
          {{ repo.language }}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/header&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe everyone is going to have multiple repositories to portray so when you grab the element of the language e.g. class of 'lang' there will be multiple classes with the same value because every repo card has its own language element. So we need to grab them all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;updated() {
    // grab the all element of the language tag
    let lang = document.querySelectorAll('.lang')

    // and cycle through them
    // with a for-of loop then use if and else if statements
    // to decide which language gets which color
    // with 'tag' you can access the individual nodes
    // within the grabed element
    // tag.firstChild is the span element where
    // the colored dot is being displayed

   for (let tag of lang) {
      if (tag.innerText === 'PHP') {
        tag.firstChild.style.backgroundColor = '#4F5D95'
      } else if (tag.innerText === 'HTML') {
        tag.firstChild.style.backgroundColor = '#e34c26'
      } else if (tag.innerText === 'JavaScript') {
        tag.firstChild.style.backgroundColor = '#f1e05a'
      } else if (tag.innerText === 'CSS') {
        tag.firstChild.style.backgroundColor = '#563d7c'
      } else if (tag.innerText === 'C') {
        tag.firstChild.style.backgroundColor = '#f34b7d'
      } else if (tag.innerText === 'C++') {
        tag.firstChild.style.backgroundColor = '#b07219'
      } else if (tag.innerText === 'Java') {
        tag.firstChild.style.backgroundColor = '#b07219'
      } else if (tag.innerText === 'Python') {
        tag.firstChild.style.backgroundColor = '#3572A5'
      } else if (tag.innerText === 'Vue') {
        tag.firstChild.style.backgroundColor = '#2c3e50'
      } else if (tag.innerText === 'TypeScript') {
        tag.firstChild.style.backgroundColor = '#2b7489'
      }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The colored dot is styled in the CSS section and we are only adding the background-color to it.&lt;/p&gt;

&lt;p&gt;I grabbed the colors from GitHub with the help of dev-tools inspector.&lt;/p&gt;

&lt;h3&gt;
  
  
  Congratulations on automating your projects section on your portfolio homepage.
&lt;/h3&gt;

&lt;p&gt;Next: Hashnode API implementation so stay tuned and follow me to not miss it out!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>github</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
