I go back and forth on how to refer to this website, if it should be my portfolio site or personal site or something else. Regardless, it's the website you're currently reading this on. The initial goal of the website was to simply generate project pages from markdown description files, but along the way a lot more was added, including a blog that I hope to actually write on one of these days!
The Pipeline
The website is hosted on GitHub pages and regenerated on each commit, primarily using the JavaScript-based templating language Nunjucks. The commit action triggers a NodeJS script that generates different types of pages: home, articles, and tags.
The home page is the simplest, since it's primarily a static page except for listing tags.
Article pages are the most interesting. They are generated for each markdown file under the projects directory or the articles directory and placed in the corresponding locations on the final site. The markdown files have XML metadata at the top that provide information such as their name, description, icon, banner, author, date of writing, and tags. This information is displayed on the project page and saved for later use as well.
The rest of the markdown file is then evaluated in a Nunjucks environment to expand any macros. Next, it's parsed by MarkedJS with the Highlight and KaTeX extensions, to convert the markdown and katex into HTML and do code highlighting. Finally, it's all combined into one page and saved.
You can see the markdown file used for this project here!
The tag pages use the same project/article data to display cards linking to the appropriate pages. The all projects and changelog posts pages are special cases of tag pages.
Neat Features
While working on this, I would frequently get sucked into implementing new features or stylings rather than actually writing about what I worked on, here are some of my favorites! (Check out the file used to generate this article to see how they're used.)
- Heart bullet points!
- Image Galleries:

Padme at christmas time

Fig yawning

Cats in the sun

Cats on the rug

Fig sleeping peacefully

Padme chilling on the bed
- Code highlighting (via marked) with Lovely Night 80s theme
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if(keyCode == GLFW.GLFW_KEY_E){
this.close();
return true;
}
if(keyCode == GLFW.GLFW_KEY_H){
hintMode = !hintMode;
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
- GitHub, Modrinth, CurseForge shields macros:
- Quatalog course links
Principles Of Program Analysis (CSCI-4450)
Background syncing & fun borders
One feature I spent a lot of time on early on was a system to have elements sync their background image positions. This is used for the colorful nav bar button backgrounds, the tag borders, and the card borders with blurred backgrounds.
The syncing is done with JavaScript on the client, so it's not instant, but it works well enough.
For colorful backgrounds (such as on tags or navbar buttons), an SVG is generated with the requested colors during the site generation and then used as a synced background. The blur effect is done externally by blurring the image used for the background and syncing its position. This lets me put another element under to act as a border with a gradient or other pattern.

Website home page with lots of synced backgrounds

Cards with transitionable gradient borders