Source code for my Jekyll-based portfolio at, which uses the Freelancer Jekyll Theme with my own additions and modifications.


Requires no servers or hosting, and runs straight from your GitHub repo on GitHub Pages.

Quick Setup

  1. Fork this repo to your own Github, with name:
  2. Open your new repo's settings, and enable Github Pages
  3. Go to

Localhost Setup

Localhost setup uses VS Code Dev Containers.

Note If you don't want to use Docker or VS Code, an older version of this README has manual ruby & gem installation instructions.


  • Docker (For Windows, also install: WSL, Ubuntu, and Docker Desktop)
  • VS Code
  • VS Code extensions:
    • Dev Containers
    • Markdown All in One (recommended)
    • GitHub Markdown Preview (recommended)
    • markdownlint (recommended)


  1. Clone the above repo, which you forked, to your localhost
  2. Open the repo in VS Code and click the "Reopen in Container" button that pops up

Note: Or run Dev Containers: Open Folder in Container... in the command palette (Ctrl+Shift+P)

  1. When the container is done provisioning, hit any key to continue
  2. Start the web server:
bundle exec jekyll serve
  1. Go to http://localhost:4000 and verify it runs locally.

The localhost site will show changes in real-time.

If you modify _config.yml though, you'll need to ctrl+c and restart the web server.


Pipe any variable into debug from any template to see its contents on-screen.

Example: Printing entire _config.yml structure:

{{ site | debug }}

Example: Printing blog post attribute from inside a for loop in blog_grid.html:

{{ post | debug }}


Once up and running locally, configure and personalize your portfolio.


  1. Overwrite profile picture in img/profile.jpg (used on home page) and img/profile32x32.png (used on blog posts)
  2. Fill out everything in _config.yml
  3. Create new posts to display your projects & blog posts. See existing examples in _posts/blog/ and _posts/portfolio/

Contact Form Setup

Formspree will receive POST requests from your contact form and forward them to your email. Without requiring server-side code.

  1. Replace [email protected] in _includes/contact_static.html with your email address
  2. Setup a formspree account for your email address

Comments Setup

Disqus will receive POST requests from your blog post's comment forms, display comments dynamically, and also deal with spam. Without requiring server-side code.

  1. Setup a Disqus account
  2. Add your disqus_shortname in _config.yml


  1. Push the above code changes on master branch to remote
  2. Go to


These are some recommended steps for final polishing.

Google Analytics Setup

  1. Create a Google Analytics site/property
  2. Enter your google_analytics_tracker_id in _config.yml

Google Tag Manager

  1. Create a Google Tag Manager]( container
  2. Enter your gtm_id in _config.yml

If you go this route, you can setup a GA4 tag through GTM, and forego the above "Google Analytics Setup" route.

Custom Domains

Instead of using the default Github Pages URL, you can instead use a custom domain name that you already own.

You can alias a custom domain name to your Github Pages URL. See Github's documentation on this.

However, you will usually have to manage and pay for SSL certificates through your domain registrar.

You can instead use Netlify for all of this, for free.

Using Netlify (Free)

Netlify is a free service that provides CDN, SSL certs, deployment pipelines, and even dynamic serverless functions.

  1. Create a Netlify account
  2. Setup your custom domain to route through Netlify, and from Netlify to your repo
  3. Setup a Netlify SSL cert