Github's Special Profile Repos
Github has a special feature where, the README.md
from a repository with the
same name as your Github username is displayed on your Github profile. My Github
handle and profile is @rickcogley, and you're
looking at a page served via Github Pages from that very repository. In my case,
it's rickcogley / rickcogley.
The Automation Concept
Lately I'm using possibly the world's coolest Static Site Generator
«Lume ルメ», and its companion
Vento templates, both coded by
Óscar Otero. I had a thought that if I could use a
Vento template to generate a markdown file in my rickcogley
repository, I
could somehow automatically copy the markdown file into the repository root, so
that it appears on my Github profile.
It turns out, per Oscar, that all you need to do is set the Vento template's url
to the name of your desired markdown file: url: my-readme.md
. When Lume
generates your site, it will just populate the readme with the content of the
template. However with Vento, you can do SSG-template-y things like loop through
lists, or pull in data from rss feeds or json sources, such as REST APIs.
Getting it done with Lume
Of course if you search, there are plenty of ways to make a dynamic profile readme, but how do we do it with Lume? Here's the overview:
- If you want to test locally, your environment needs Deno, and after cloning
this repo, you can do
deno task lume --serve
to run it onhttp://localhost:3000
. You can also go to this repo and use "use this template" to get your own copy, then clone that to local. - This repo creates a single web page based on the linktree-like
Theme Simple Me template for
Lume, and hosts it on Github pages. But you can change
url: /
tourl: false
insrc/index.md
to disable the site. - Edit the
repo-readme.vto
Vento template, using markdown format, to create the precursor readme. Notice theurl:
in the file's frontmatter is set to output a markdown file. - On build via
deno task lume --serve
(builds and serves on localhost) ordeno task lume
(just builds), Lume will generate the site files in_site
, and also run a script to copy the generated readme into place. - See the script in Lume's config file
_config.ts
in the repo root, in thesite.script
line near the bottom. After the site is built, the readme generated by Vento is copied to the repo root as the typicalREADME.md
here. - Take a look at the Vento template codes (
{{ something }}
) in therepo-readme.vto
Vento template. You can see that it is pulling in the date, checking for a holiday name, and pulling in rss feeds.
Setting up the Data
First take a look at the "Today is" line in the repo-readme.vto
Vento
template.
**Today is:** {{ todaysDateENUS }}{{ set today = todaysDateYYYYMMDD }}{{ if holidays[today] }} ({{ holidays[today] }}){{ /if }}
It's referencing the constants todaysDateENUS
and todaysDateYYYYMMDD
, and
checking a dataset "holidays" if there is any data that matches "today". The
constants and data are set up in the file _data.ts
. For example:
export const todaysDateYYYYMMDD = `${new Date().toISOString().split("T")[0]}`;
This sets up a date in YYYY-MM-DD format, because that's what the holiday dataset has to match on.
As for the holidays, they are fetched into an object holidays
which the Vento
template is parsing.
const response = await fetch('https://holidays-jp.github.io/api/v1/date.json', {
method: 'GET',
...
If you needed to access a protected API, you could put its access token in a repository variable, and access it as a bearer token in the header of your get.
Regarding RSS, I used "parse feed" from a library on denoland/x. This part:
import { parseFeed } from "https://deno.land/x/rss/mod.ts";
async function fetchAndConvertRSS(url: string, limit: number) {
// Fetch the RSS feed
const response = await fetch(url);
...
Then the feed can be fetched into a const to use in the Vento template. The
Vento template just uses a for loop to parse the feed's json and put it into
markdown li
elements.
## Latest Statuses:
{{ for item of statuses.entries }}* [{{ item.description.value }}]({{ item.id }})
{{ /for }}
Automate Generation
To automate the generation, we just use a github actions template,
.github/workflows/update-profile-readme.yml
which triggers Lume to build the
site which copies the README.md
into place, commits the new file, publishes to
GH Pages. The actions template is triggered on push or PR, "workflow dispatch"
which means you can also manually trigger, and on a cron schedule.
on:
push:
# Run on main branch pushes or PRs
branches: [main]
pull_request:
branches: [ "main" ]
# Allow to manually trigger the workflow
workflow_dispatch:
schedule:
# Rebuild every day at 9:06 PM UTC
- cron: "6 21 * * *"
How to get yours?
Go to my profile repo, and click
"use this template" to make your own copy. If you don't have a profile repo
already, save the repo as your username. Then tweak it how you like including
updating the RSS feeds. Or, setup Deno and Lume, and copy in the files manually.
Just Edit the repo-readme.vto
Vento template in markdown format, save, commit
and push. If the GH action is working right, Lume will generate the readme file
and copy it into place, after which you can see it on your personal repo.
You can see a more simple version without any website creation tooling, in my org eSolia's profile repo.
Is it good?
Yes.