ByEnrique Kessler Martínez|
April 12, 2021
1060 words
4 minutes

My personal web is officially out and running!

The enriquekesslerm.com project started as a placeholder for learning Gatsby, entangled in the 100 Days Of Gatsby experience. Built with Gatsby —easily industry-accepted the best framework for lightning fast websites—, the site has quickly become the place where I try to bring all of my ideas to be sure that I keep myself learning, while creating a personal space.

Before starting with the breakdown, I find that it is important to give credit where credit is due. I took a lot of inspiration on the following blogs when designing the website, thank you so much!

Why Gatsby?

Gatsby is a React framework, so you will have to live with that it is built in JavaScript. On the other side, Gatsby compensates by pre-fetching data and caching all your website at build time. This means that the website will feel as crisp as a mobile app while having all the advantages that the web still offers, considering how young the mobile world is.

Gatsby provides extensive docs, and has a joyful community behind, trying to make the web better one step at a time. Without reinventing the wheel, you are able to access starters, plugins and more.

Considering the previous web-building experience that I had, drawing from some of the Django knowledge was plenty to build the website/blog that I had been dreaming of.

Where is the content coming from?

Gatsby by default —i.e. using the default starter— provides several CMS that you can connect to, namely Contentful, Ghost and more. I decided to go the more “emacsy” route, because

By experimenting with voluntary discomfort, we learn to appreciate far more of our life, and can be content with a much simpler and more wholesome one.

Instead of going for Markdown files, being the hardcore Emacs user I am, I needed to find something to merge my love for Emacs and org-mode. The solution rested in the Xiaoxing's orgajs starter, which uses the orgajs package —also authored by him— parsing our org-mode files into beautiful and configurable websites, What could be better?

Just to drive the point home, this is the magic of orgajs in play. The following is the heading of this post.

,* PUBLISHED enriquekesslerm.com                       :web:software:personal:
:DATE: <2021-04-12 lun>
:CATEGORY: Projects
:SUMMARY: Personal web used to showcase myself and collect my writings and ideas in one spot.
:IMAGE: ./images/danielle-macinnes-IuLgi9PWETU-unsplash.jpg

The enriquekesslerm.com project started as a placeholder for learning Gatsby,
entangled in the [[/100daysofgatsby-log][100 Days Of Gatsby]] experience. Built with Gatsby —easily
industry-accepted the best framework for lightning fast websites—, the site has


You can access the source code of this project —like any other of my projects— here, feel free to commit any changes or typos to help the cause.

enriquekesslerm.com follows the following structure

├── assets
│   ├── images
│   └── svg
├── content
│   ├── 100daysofgatsby-log.org
│   ├── advanced.org
│   ├── emacs-for-writers.org
│   ├── getting-started.org
│   ├── images
│   ├── projects.org
│   └── standalong.org
├── gatsby-config.js
├── package.json
├── png2svg_black.sh
├── README.md
├── src
│   ├── components
│   ├── constants
│   ├── gastby-plugin-theme-ui
│   ├── gatsby-theme-blorg
│   ├── hooks
│   ├── pages
│   └── utils
└── yarn.lock

As I'm using the yarn package manager, the yarn.lock file keeps all the versions of the packages that my page requires. Under the /content directory, I store all the org-mode files that compose my posts. Under /src, there are self developed components, but Gatsby's known concept as "Shadowing" is common. I shadow some of the configuration files for the plugins gatsby-plugin-theme-ui and gatsby-theme-blorg.


Search blog posts🔍

Using elasticlunr, which is an amazing light-weight self-hosted search engine, I'm able to implement the search engine for my blog posts. The package has configuration that needed to be done, as always on the gatsby-config.js file.

  resolve: `@gatsby-contrib/gatsby-plugin-elasticlunr-search`,
  options: {
    fields: [`title`, `tags`, `category`],
    // How to resolve each field`s value for a supported node type
    resolvers: {
      OrgPost: {
        title: (node) => node.title,
        tags: (node) => node.tags,
        excerpt: (node) => node.summary,
        slug: (node) => node.slug,
        date: (node) => {
          const date = node.date
          const moment = require("moment")
          return moment(date).format(`MMMM DD, YYYY`)
        category: (node) => node.category,

If you are using Markdown (a.k.a the MarkdownRemark package) for your content, no additional configuration is needed, but I needed to configure the OrgPost graphql type.

Elasticlunr uses the old component system based on state classes, but I imagine it could be implemented using the new useState React Hook. Elasticlunr indexes the blog posts for the user when the /blog page starts, and it does so using the getOrCreateIndex function:

getOrCreateIndex = () =>
  ? this.index
  : // Create an elastic lunr index and hydrate with graphql query results

When the user's input changes, the search function is called, which queries the created index for the results according to the input, mapping the reference to the OrgPost Object.

search = (evt) => {
   const query = evt.target.value
   this.index = this.getOrCreateIndex()
       // Query the index with search string to get an [] of IDs
       results: this.index
          .search(query, { expand: true })
          // Map over each ID and return the full document
          .map(({ ref }) => this.index.documentStore.getDoc(ref)),

The end result is pretty cool! I can search by 'title', 'tags' and 'category'.

Categories and tags📁

Each of the blog posts has additional metadata that can be added using either the headline of the org-file, or in the :PROPERTIES: drawer if the post is headline-based. Here are all the available options:

metadata field headline based file based
title headline content #+TITLE
date DATE #+DATE
"CLOSED" planning timestamp
file name
tags tags of headline #+TAGS
headline content (sanitised) file name

The category and tags are the one that I'm talking about as custom pages are created for each of them (dynamically when they are defined in the blog posts)

Projects category
Software tag

Travel map

One of the ideas that I took from Lee's blog is to add a travel-map. I didn't really find that his using google-map was that interesting, so I searched for other ways, stumbling on react-leaflet.

Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need. Leaflet is designed with simplicity, performance and usability in mind. It works efficiently across all major desktop and mobile platforms, can be extended with lots of plugins, has a beautiful, easy to use and well-documented API and a simple, readable source code that is a joy to contribute to.


React-leaflet is the React package that uses the leaflet library to create custom components, pretty cool, huh?

if (typeof window !== "undefined") {
  return (
      style={{ width: "100%", height: "400px" }}
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      {markers !== null &&
        markers.map((m, index) => (
          <Marker key={index} position={m.position}>
return null

Using that simple code I'm able to use a series of markers (which are stored in their own /constants file) and add them to the map, with their descriptions and custom CSS popups.

Moving rainbow text

As part of the initial look that I wanted to infuse the website, one of the initial TODO's was adding a moving gradient text for my name on the index page.

I adapted Josh Comeau's moving gradient button to work as the background for some text. The end result has pretty clean code and it works for most of the browsers (CSS Houdini is still not fully supported).


As I'm a big advocate of RSS, I found that it needed to be included as one of the key features of the web-page. Using the gatsby-plugin-feed, the configuration was easy and quick.

⚠ As a warning, the output file is only created on build, I had several hours of searching for problems to finally end up finding that it no longer builds the file on gatsby develop.

  resolve: `gatsby-plugin-feed`,
  options: {
    query: `
        site {
          siteMetadata {
            site_url: siteUrl
    feeds: [
        serialize: ({ query: { site, allOrgPost } }) => {
          return allOrgPost.nodes.map(post => {
            return Object.assign({}, post, {
              title: post.title,
              date: post.date,
              url: site.siteMetadata.siteUrl + post.slug,
              guid: site.siteMetadata.siteUrl + post.slug,
              custom_elements: [{ "content:encoded": post.html }],
        query: `
            allOrgPost(sort: {fields: date, order: DESC}) {
               nodes {
                  date(formatString: "MMMM DD, YYYY")
        output: "/rss.xml",
        title: "Enrique Kessler Martínez's posts",

As always, if you are using MarkdownRemark the configuration is even easier, with org-mode you require to add little configuration. An important part is the content-encoded html for my posts, without it there would be problems with the resulting rss.xml file.

You can find the RSS file here.