Setup a Dynamic GitHub User Profile README
Tags: github, typescript, graphql, actions
Published: 2023-03-18 18:22:17

---
title: Setup a Dynamic GitHub User Profile README
published: true
description: Creating a customized user profile readme page for GitHub to showcase work projects and make navigation to relevant topics easier. This is part 1 of 4.
tags: github,typescript,graphql,actions
series: ["GitHub Profile"]
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
---

Introduced in 2020, the GitHub user profile README allow individuals to give a long-form introduction. This multi-part tutorial explains how I setup my own profile to create dynamic content to aid discovery of my projects:

- **with the Liquid template engine and Shields** (keep reading below)
- [using GitHub's GraphQL API to query dynamic data about all my repos](https://dev.to/j12y/query-github-repo-topics-using-graphql-35ha) (Part 2 of 4)
- [fetching RSS and Social cards from third-party sites](https://dev.to/j12y/fetching-blog-rss-feeds-for-building-a-github-profile-i31) (Part 3 of 4)
- [automating updates with GitHub Actions](https://dev.to/j12y/automating-github-profile-updates-with-github-actions-14i3) (Part 4 of 4)

You can visit [github.com/j12y](https://github.com/j12y) to see the final result of what I came up with for my own profile page.

![My GitHub Profile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hlg6ws0r5hwxel0ii84h.png)

## Getting Started with Profile README

A profile on GitHub consists of standard attributes like profile name, picture, location, bio and status. Also included on a profile page are dynamic elements such as pinned repositories, stars, followers, contribution graph and activity feed. 

The [GitHub profile README](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme) file adds the capability to provide additional flair and free-form content. It is a specific file and repository that will render on your profile by following the proper conventions.

To get your profile to `hello world` you need to follow a few steps:

1. Create a repository named identical to your username. So for example, my repos name is "j12y" because my GitHub login is "j12y". If your login is "octocato" then the repository would be named "octocato".
2. Create a file README.md in the repository.
3. Put any markdown or HTML you'd like such as `# Hello World` in the file and commit it to the `main` branch.

This is the convention for individuals. For organizations, the repo is called **.github** and the file **profile/README.md**.

The result is rendered on your profile page like so:

![Location of Profile README](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pl7beayfsy7sdqg44ml3.png)

Generally, anything that is in the README.md is what will be rendered to your profile much like it would be in the README.md within an individual repository. 

I stumbled upon a list of [awesome GitHub Profile READMEs](https://github.com/abhisheknaiidu/awesome-github-profile-readme) and spent quite some time reviewing them for inspiration. There are some very creative folks out there that have found interesting ways to express themselves and their projects. Those and other resources go into more examples of the things you can do:

- putting in banner images
- collapsible sections for details
- changing fonts
- making tables
- etc.

Check those resources out for some basic formatting tutorials.

## Generating a README from a Template

To support the idea I had in mind for my own profile README I wanted to use a template engine. That is, I wanted to be able to fetch dynamic data and then substitute it into a template that generates the final README.md as the output. 

```
    ┌────────────┐            ┌─────────────┐
    │            │            │             │
    │ template.a ├────────────►  README.md  │
    │            │            │             │
    └───┬────────┘            └─────────────┘
        │
        │  ┌────────────┐
        │  │            │
        ├──┤ template.b │  <----- DATA
        │  │            │
        │  └────────────┘
        │
        │  ┌────────────┐
        │  │            │
        │  │ template.c │
        └──┤            │
           └────────────┘
```

I spent some time researching options:
- handlebars
- mustache
- pug
- smarty
- liquid
- etc.

I had used handlebars and mustache on web projects in the past and evaluated pug which was new to me and had never used before just for the sake of learning more about it. I planned this project to be a `node` script using `TypeScript` *for reasons*. Finding an easy to use example of [Liquid + TypeScript](https://liquidjs.com/) that worked out of the box was the primary deciding factor in choosing it given I only have a few basic requirements.

### Initializing the TypeScript Project 

I initialized my TypeScript project:

```bash
npm init -y
npm install --save-dev typescript
npx tsc --init --rootDir src --outDir build
npm install -D @types/node 
npm install -D ts-node
```
and configured [tsconfig.json](https://github.com/j12y/j12y/blob/main/tsconfig.json) and package.json to run my build with `npm start` by executing:

```bash
ts-node ./src/app.ts
```

### Getting Started with a Simple Liquid Template

The source directory project is minimimalistic boilerplate and structured like this:

```
├── package-lock.json
├── package.json
├── src
│   ├── app.ts
│   └── template
│       ├── README.liquid
│       └── contact.liquid
└── tsconfig.json
```

When **src/app.ts** is executed, it resolves the paths of the templates in order to generate the output **README.md** from the entry point of the **README.liquid** template. 

```typescript
// src/app.js
import path from 'path'
import { Liquid } from 'liquidjs'
import { writeFileSync } from 'fs'

export async function main() {
  let scope = {};

  const engine = new Liquid({
    root: path.resolve(__dirname, 'template/'),
    extname: '.liquid'
  });

  engine.renderFile('README', scope).then((content) => {
    writeFileSync(path.join(__dirname, '../README.md'), content, {flag: 'w'});
  });
}

main();
```

The liquid template contains any markdown or html that should appear in the final README.md that will be generated into the root of the project.
```
<!-- src/template/README.liquid -->
# Hello World
```

## Using Shields for Visual Flair 

If you've spent time on GitHub exploring repositories you've likely encountered shields. These status boxes can be either static or dynamic but provide a nice visual callout to things like build status, code coverage, downloads, follower counts, etc. 

They can also serve as a helpful visualization for social links. The [docs](https://shields.io/) explain that any logo provided in [simple-icons](https://github.com/simple-icons/simple-icons/blob/develop/slugs.md) can be used.

So defining what you want can be used to construct a URL:

* Label: LinkedIn
* Message: none
* Logo: linkedin
* logoColor: #0077B5

Putting this together, the main entry point to the templates is **src/template/README.liquid**:

```liquid
<!-- src/template/README.liquid -->

{% include 'contact' %}
```

This includes a second template to store all of the contact information such as social profiles in **src/template/contact.liquid**:
```liquid
<!-- src/template/contact.liquid -->
# Hello World

<div id="social" align="center">
  <a href="https://www.linkedin.com/in/jaysondelancey/" target="_blank"><img src="https://img.shields.io/badge/LinkedIn-0077B5?style=flat-square&logo=linkedin&logoColor=white" alt="@jaysondelancey on LinkedIn"/></a>
</div>
```

Now we have badges that can be used for a bit more pop than HTML text anchors.

![social shields](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jcndk51f1p1kaoss6jj.png)

## Learn More About GitHub Readme Profiles

As you let this introduction to setup of a GitHub Profile Readme marinate, the next articles will dive into some of the more interesting applications of GitHub features.

- [Creating a topic explorer for repos using GraphQL](https://dev.to/j12y/query-github-repo-topics-using-graphql-35ha) (Part 2 of 4)
- [Fetching RSS and Social Cards for GitHub Profile](https://dev.to/j12y/fetching-blog-rss-feeds-for-building-a-github-profile-i31) (Part 3 of 4)
- [Automating GitHub Profile Updates with Actions](https://dev.to/j12y/automating-github-profile-updates-with-github-actions-14i3) (Part 4 of 4)

Did this help you get your own profile started? Let me know and follow to get notified about updates.