DEV Community

Cover image for Adding a GitHub Contribution Calendar to your Svelte App
Patrick Chiu
Patrick Chiu

Posted on

Adding a GitHub Contribution Calendar to your Svelte App

Showcasing your GitHub activities in the personal site is a great way to demonstrate one's enthusiasm and determination to your works. This short article aims at introducing activity-calendar-widget that can be embedded in your Svelte App! In fact, activity-calendar-widget also provides native components in framework e.g. React, Vue, Solid and Qwik as well, but we will focus on the usage in a Svelte App here.

Installation

npm i activity-calendar-widget

Basic Example

<script>
  import ActivityCalendarWidget from 'activity-calendar-widget/svelte'
</script>

<div>
  <ActivityCalendarWidget daysToRender={150} />
</div>

<style>
  img { width: 82px }
</style>
Enter fullscreen mode Exit fullscreen mode

Since we are working on a Svelte codebase, we import ActivityCalendarWidget from 'activity-calendar-widget/svelte' (notice the subdirectory /svelte at the end). After that, we can embed the <ActivityCalendarWidget /> into our Svelte App. And duh! We have an (empty) GitHub Contribution Calendar!

In the basic example, we also pass daysToRender={150} to the component. If we remove the props, by default it will at least render 365 days and try to fill out all the empty day box in the leftmost (oldest) column.

It's a shame to see an empty GitHub Contribution Calendar! Let's walkthrough 2 options in our hands - getting the public activity data using the official GitHub events API, or getting the exact data in your profile's contributions with GitHub contributions API created by @grubersjoe. It is a handy API which scrapes the data from your profile.

Usage with the official GitHub events API

<script>
  import ActivityCalendarWidget from 'activity-calendar-widget/svelte'

  let data = []

  const loadGithubActivity = async () => {
    // 1. Call Github events API
    const githubId = 'patrick-kw-chiu';
    const githubApi = `https://api.github.com/users/${githubId}/events`;
    const response = await fetch(githubApi);
    const payload = await response.json();

    // 2. Report error if there's
    if (payload?.message) {
      return;
    }

    // 3. Construct the data array which expects obj with 2 keys
    // date: 'yyyy-MM-dd'
    // activities: array of anything
    let eventObj = {};
    payload.forEach((event) => {
      const date = event.created_at.slice(0, 10);
      if (!eventObj[date]) {
        eventObj[date] = [event];
      } else {
        eventObj[date] = [...eventObj[date], event];
      }
    });
    const newData = Object.entries(eventObj).map((entry) => {
      return {
        date: entry[0],
        activities: entry[1],
      };
    });
    data = newData
  }
  loadGithubActivity()
</script>

<div>
  <ActivityCalendarWidget
    daysToRender={150}
    data={data}
    levelColorMode={'dark'}
  />
</div>

<style>
  img { width: 82px }
</style>
Enter fullscreen mode Exit fullscreen mode

To do so, first we GET the activities data from https://api.github.com/users/${githubId}/events where githubId is your GitHub ID.

Next, we construct a data array with 2 keys - date and activities, while date is having the yyyy-MM-dd format and activities is an array of anything. Note that the length of the activities array will be the count. Also, we can pass an optional clickHandler to retrieve the detail of the activities. We will demo it in the last section.

Lastly, we pass the data array to the widget like <ActivityCalendarWidget data={data} />. We should see something like:

Svelte-ActivityCalendarWidget-dark-mode

Usage with the GitHub contributions API from @grubersjoe

<script>
  import ActivityCalendarWidget from 'activity-calendar-widget/svelte'

  let data = []

  const loadGithubActivity = async () => {
    // 1. Call Github events API
    const githubId = 'patrick-kw-chiu';
    const githubApi = `https://github-contributions-api.jogruber.de/v4/${githubId}`;
    const response = await fetch(githubApi);
    const payload = await response.json();

    // 2. Report error if there's
    if (!payload?.contributions) {
      return;
    }

    // 3. Construct the data array which expects obj with 2 keys
    // date: 'yyyy-MM-dd'
    // activities: array of anything
    const newData = payload.contributions.map((contribution) => {
      return {
        date: contribution.date,
        activities: new Array(contribution.count).fill(0),
      }
    });
    data = newData
  }
  loadGithubActivity()
</script>

<div>
  <ActivityCalendarWidget
    daysToRender={150}
    data={data}
    levelColorMode={'dark'}
  />
</div>

<style>
  img { width: 82px }
</style>
Enter fullscreen mode Exit fullscreen mode

It is basically very similar to the official GitHub events API. The difference are that

  1. GitHub contributions API reflects the exact contributions view from your profile, which is good

  2. GitHub contributions API returns the contributions / activities like below, which might not include the full detail of the activity (if you need it)

{
  "contributions": [
    {
      "date": "2020-01-01",
      "count": 0,
      "level": 0
    },
    ...
  ]
}
Enter fullscreen mode Exit fullscreen mode

Customize the activities calendar with other options and try out clickHandler

<script>
  const clickHandler = (dt) => console.log(dt)
</script>

<ActivityCalendarWidget
  daysToRender={150}
  data={data}
  levelColorMode={'dark'}
  levelColors={[
    '#021f1f', '#055e5e', '#068f8f', '#06d1d1', '#07ffff'
  ]}
  weekdayLabel={{
    1: '月曜日',
    3: '水曜日',
    5: '金曜日'
  }}
  clickHandler={clickHandler}
/>
Enter fullscreen mode Exit fullscreen mode

Customized Activity Calendar Widget

We can customize the activities calendar widget by passing various props. In the sample above, we pass the levelColors array to change it to a teal-ish color and customize the weekdayLabel to some Japanese characters. Visit the API doc for all the supported options!

Lastly, if we click the teal-ish date box, we should see the log as below, since we pass a clickHandler to the widget. It includes the activities detail of the clicked date, as well as other info e.g. year, month and day.

Activity Calendar Widget click handler


Behind the scene

Activity Calendar Widget is built with Mitosis (with a little modifications), which aims to "Write components once, compile to every framework". That's why there are also native React components, Vue, Solid and Qwik as well. Interested to learn more? Here is a walkthrough of building a "simplied" Activity Calendar Widget with Mitosis.js.

Credits: The API of Activity Calendar Widget is highly influenced by React Activity Calendar. React Activity Calendar is a great component library, which provides more granular options in certain areas.


Thanks for reading! Want to Connect?

Visit me at LinkedIn | GitHub | Twitter

Top comments (0)