Skip to content

Repository files navigation

haliphax.dev

The source code for https://haliphax.dev and its accompanying processes; proudly built with 🎈 Eleventy!

🌳 Directory structure

The directory structure used by this site may be considered "nonstandard" when compared to the Eleventy documentation and various starter site templates, but I personally find it much easier to reason with.

  • .github Definitions for GitHub actions
  • 11ty Eleventy code and data
    • data Global data
      • external Data from external sources
    • events Eleventy engine event handlers
    • functions Global functions (filters)
    • layouts Template layouts
    • libraries Libraries used by the engine
    • plugins Plugins used by the engine
    • transforms Transforms for content manipulation
  • content Renderable site content
    • pages Content pages
    • posts Blog posts
  • static Static files, copied verbatim
    • css Stylesheets
    • img Images
  • tasks Node scripts for out-of-band tasks

🛠️ Configuration structure

In addition to a nonstandard directory structure, I have built my own configuration structure in an effort to wrangle the many pieces' responsibilities.

The various pieces Eleventy needs to consume during its configuration phase are all divided into their own categorical folders beneath the 11ty directory. Each of these folders contains a _config.ts file (with the exception of the data folder, which is automatically parsed by Eleventy).

The _config.ts file is used to collate all of that category's members together and to expose a single function to the main Eleventy configuration function. In this way, the complexity of the category's setup is abstracted from the main configuration and it makes for less clutter.

Modular configuration example

Example: All of your layout templates are under layouts, and a single function in layouts/_config.ts is used by the main Eleventy configuration function to assign each of them an alias. They are loaded in the main .eleventy.ts entrypoint. Here is a (simplified) example:

export=(cfg: UserConfig)=>{require("./11ty/layouts/_config")(cfg);// ...};

When you need to make modifications to your layout setup, you will be working strictly with the files contained in this directory. Similar mechanisms exist for each of the other categories, though their configuration functions' content may differ slightly.

🎉 Features

🖼️ Layouts

🔍 Source folder: 11ty/layouts

All layout templates are built using the 11ty.js (JavaScript) template language.

KeyParentDescription
basenoneThe base layout, which includes the outer document shell and site navigation
withHeaderbaseReads data.header for use in an <h1> element
pagewithHeaderUsed for Markdown pages; includes reading time, edit link, etc.
postwithHeaderLike page, but includes posted timestamp

🔖 Special tags

Some tags may confer special behavior to the post they are attached to.

KeyDescription
archivedRemoves the post from tag lists and displays a notice explaining to the viewer that the page has been archived

🗒 Data

🔍 Source folder: 11ty/data

css

🔍 Source: 11ty/data/css.ts

CSS combine/minify configuration

FieldDescription
externalStylesheetsList of external stylesheet files to pull during build
fontDestinationDestination folder (relative to output folder) for font resources
fontSourcesList of folders that should be copied to fontDestination during build
localStylesheetsList of CSS files from the local filesystem to incoroporate

ignoreTags

🔍 Source: 11ty/data/ignoreTags.ts

List of post tags that should be ignored when building tag pages or displaying a post's associated tags

links

🔍 Source: 11ty/data/links.ts

List of objects for use in the Site navigation menu. Their format is as follows:

FieldDescription
nameName to display in the menu
urlURL for the generated link tag
iconCSS classes for the link's FontAwesome icon

metaDefaults

🔍 Source: 11ty/data/metaDefaults.ts

Default values for page metadata

FieldDescription
authorAuthor of the post/page
descriptionMeta description
generatorEleventy package name and version
openGraphImageUrlURL to use for og:image OpenGraph tag
openGraphTypeType of page for og:type tag

misc

🔍 Source: 11ty/data/misc.ts

Miscellaneous values that don't belong elsewhere

FieldDescription
blurbLengthMaximum length allowed for post blurbs
githubRootGitHub project root for "Suggest an edit" post links
jumboBlurbLengthMaximum length allowed for primary post's blurb
readingTimeWpmWords-per-minute for calculating reading time
siteRootRoot URL of the site
ytPlaylistIdYouTube playlist ID for retrieving latest video

socials

🔍 Source: 11ty/data/socials.ts

List of links for populating the Social navigation menu. Object format is the same as that of links.

strings

🔍 Source: 11ty/data/strings.ts

List of string values used throughout the site and its templates

FieldDescription
aboutMeHTML for the "About me" section
headerText for site header
siteMenuHeaderText for Site navigation menu header
siteNameText for site name (used in <title>)
socialMenuHeaderText for Social navigation menu header

⚡ Functions

🔍 Source folder: 11ty/functions

These are equivalent to filters in other templating languages (e.g. nunjucks).

FunctionDescription
getDescription(content, limit)Produce a trimmed blurb for the given content
getHashRef()Get the hash ref of the latest commit in the repository
getMetaDescription(content, limit)Same as getDescription, but encoded for <meta /> usage
htmlEntities(text)Replace certain character combinations with HTML entity equivalents
inlineScript(...paths)Return an auto-executing anonymous method for the given Javascript file for inline use
metaEncode(text)Replace illegal characters to produce usable text for meta tags
renderArchivedNotice(tags)Used by the post layout to display an archived notice (if applicable)
renderCollection(items, limit, jumboFirst)Render a collection of pages
renderGitHubLink(data)Render link to GitHub for editing the current page
renderIcon(icon)Render the provided Feather Icons sprite
renderLazyImage(html)Render a lazy loaded image of the provided <img> element
renderReadingTime(data)Render the reading time information for a page/post
renderTags(tags)Render a collection of tags

⏰ Event handlers

🔍 Source folder: 11ty/events

HandlerEventDescription
cssTidyeleventy.afterPurges unused rules with purgecss, minifies and combines stylesheets with clean-css
iconPurgeeleventy.afterRemoves unused SVG icons from feather-icons.svg sprite sheet

🤖 Transforms

🔍 Source folder: 11ty/transforms

NameDescription
htmlMinifyMinifies HTML output using html-minifier and esbuild

📚 Libraries

🔍 Source folder: 11ty/libraries

IDDescription
markdown-itUsed for generating HTML content from Markdown files

🔌 Plugins

🔍 Source folder: 11ty/plugins

IDDescription
@11ty/eleventy-plugin-syntaxhighlightSyntax highlighting for code blocks in blog posts

🌐 Environment variables

There are several environment variables required for the site to operate. These may be exposed as GitHub environment secrets, standard environment variables, or by creating a .env file in the root of the project.

NameDescription
TWITCH_USERNAMEYour Twitch username
TWITCH_CLIENT_IDTwitch API client ID
TWITCH_CLIENT_SECRETTwitch API client secret
YT_API_KEYYouTube Data API key

⏯️ Tasks

🔍 Source folder: tasks

There are tasks which are run directly with node, outside of the scope of the the Eleventy system. These will each output a JSON file in the 11ty/data/external directory corresponding to the external data source they represent.

The scripts compare their external data against the file's previous contents (if any). If the file is identical to the external data, they will end with an exit code of 0. If there are differences, they will end with an exit code of 1. This is used to chain them together with an early exit in the GitHub workflow responsible for polling external data sources so that a publish action does not take place if there is nothing to update.

Note: Because they will end with an exit code of 1 when there are differences, this must be accounted for when running them individually in a workflow. See examples below.

Task execution examples
# this could fail and end your workflow early
npm run check:twitch
# this will always proceed to the next step
npm run check:twitch ||true
# this will set the shell variable DIFF to 1 if there are differences while# also proceeding to the next step
npm run check:twitch || DIFF=1
# this will run *all* checks; return code behavior is the same
npm run check
TaskDescription
checkRuns all check:* tasks
check:twitchRetrieves Twitch live stream and VOD information
check:youtubeRetrieves YouTube latest video information

🏭 Workflows

🔍 Source folder: .github/workflows

This site is hosted entirely on GitHub Pages. Both its main publishing and periodic update methods make use of GitHub Actions workflows to update the live site automatically when new content or data is available.

Automatic publish on merge

🔍 Source: .github/workflows/publish-site.yml

When the main branch of this repository is updated, a GitHub workflow regenerates the site and delivers the artifact to a GitHub Pages publishing action, which will update the live site with any new content. External data is also refreshed as part of this process.

Periodic updates

🔍 Source: .github/workflows/check-externals.yml

This site is periodically updated by way of a hosted cronjob and a GitHub workflow. Every 5 minutes, the cronjob runs the workflow responsible for polling external data sources by using a workflow dispatch event. If any of the external sources have updated data since the last execution of the workflow, the site will be re-published (along with the new data).

Used by

Contributors

Languages