Hydra/JAMStack

Modules

Projects based on this architecture will have at most three main modules:

  • cms (backend)

  • etl (data processing module)

  • frontend

Set up as a monorepo using the npm workspaces setting in package.json:

"workspaces": [
  "cms",
  "etl",
  "frontend"
]

Directory structure

  • .envs/ environment files for each of the modules, .example files should be under version control to help setting up new instances

    • .cms.example

    • .etl.example

    • .frontend.example

  • .github/workflows CI/CD pipelines

  • cms/ the cms module

  • docker/ files for setting up Docker provisioning, as needed

    • local/module_name/*

    • production/module_name/*

  • etl/ the data processing module

  • frontend/ the frontend module

  • .eslintrc.json to specify the linting rules

  • .nvmrc to specify the node version used to run the project

  • .prettierignore to specify which files should not be automatically formatted

  • CHANGELOG.md to record project changes

  • LICENSE

  • README.md

  • docker-compose.override.yaml.example Docker compose file for local overrides, should be copied and renamed without .example

  • docker-compose.yaml Docker compose file

  • package.json

Note

Docker is only needed if using the cms, and potentially etl modules. If the project only has the frontend module Docker should not be needed.

The highlevel directory structure for each module/workspace, by default, follows the standard for JavaScript packages:

  • public/

  • src/

  • tests/

  • package.json

Note

This directory structure may not apply to all the workspaces, for example, if using Directus for the cms module the directory structure should follow the structure of the Directus project, which by default doesn’t need a src directory.

Tooling

These are used to guarantee consistency across projects and should be set up at the root of the project:

  • eslint to find issues in the code set up with the recommended settings and using prettier for formatting.

{
  "env": {
    "es6": true,
    "node": true,
    "jest": true
  },
  "extends": [
    "eslint:recommended",
    "prettier"
  ],
  "parser": "@babel/eslint-parser",
  "parserOptions": {
    "requireConfigFile": false
  }
}
  • .nvmrc to specify a node version

  • prettier for code formatting

Dependencies

"devDependencies": {
  "@babel/eslint-parser": "^7.18.2",
  "@babel/eslint-plugin": "^7.17.7",
  "eslint": "^8.17.0",
  "eslint-config-prettier": "^8.5.0",
  "prettier": "^2.6.2",
  "prettier-plugin-sort-imports": "^1.7.0",
  "simple-git-hooks": "^2.8.0",
  "vscode-langservers-extracted": "^4.2.1"
}

Automation

Both linting and formatting should be run as a pre-commit hook set up in package.json, by using the simple-git-hooks package.

"simple-git-hooks": {
  "pre-commit": "npx lint-staged"
},
"lint-staged": {
  "*.{js}": "npm run format",
  "*.{json,md,yaml}": "npm run prettier:fix"
}

Scripts

The top seven sample scripts are mostly useful for when one of the modules in the project uses Docker, they provide a shortcut to interact with the containers.

"scripts": {
  "compose": "trap 'echo Stopped; exit 0' SIGINT; docker-compose",
  "up": "npm run compose up -- --build",
  "down": "npm run compose down",
  "exec": "npm run compose exec ${npm_config_service}",
  "pkg": "npm run exec npm",
  "cms:snapshot": "npm run pkg --service=cms run snapshot:create",
  "cms:snapshot:apply": "npm run pkg --service=cms run snapshot:apply ./snapshots/${npm_config_snapshot}.yaml",
  "lint": "eslint **/src **/tests",
  "lint:fix": "npm run lint -- --fix",
  "prettier": "prettier . --check",
  "prettier:fix": "npm run prettier -- --write",
  "format": "npm run prettier:fix && npm run lint:fix",
  "test": "npm run test --workspaces --if-present"
}

Frontend module

By default the frontend module should be built using 11ty.

Directory structure

  • ../.github/workflows/frontend.yaml GitHub pipeline file to build GitHub pages

  • .eleventy.js 11ty configuration file

  • .env environment file with settings to build the frontend

  • _site/ output directory for the built site (not under version control)

  • package.json

  • public/ contains files that are not used by the build process

    • assets/* images, pdfs, etc.

    • robots.txt

  • src/ input/src directory for the build process

    • _data/ global data/collections for the project

      • eleventyComputed.js computed fields available to every layout

      • config.json settings for the seo plugin and other site metadata

    • _includes/ contains layouts, include files, extends files, partials, or macros

      • layouts/ contains layout templages

      • macros/ contains reusable chunks, similar to a function does in programming languages

      • partials/ contains layouts partials/fragments

    • assets/

      • stylesheets/ SCSS files that will be built by 11ty

Templates

Component-based development for template reuse, one possibility is to use Nunjucks macros:

Warning

11ty supports multiple template languages, ~10! I have settled on Nunjucks because it seemed that was the language mostly used in 11ty projects. The other reason I have not used liquid is because the JavaScript implementation is different from the Ruby one used with Jekyll. One issue I have with it is that both the empty string and 0 are truthy in liquid.

Scripts

Execute them with npm run.

"scripts": {
  "build": "eleventy",
  "dev": "eleventy --serve",
  "debug": "DEBUG=Eleventy* npm run dev",
  "index": "npx pagefind --source _site"
}

Metadata

Post

---
title: Title of the post
# the subtitle field is optional and depends on the project
subtitle: A fancy subtitle
# posts can have multiple tags
tags:
# post is a default tag
  - post
# one tag per line
  - one
# spaces are allowed in tag names
  - multiple words
# posts can have multiple authors
authors:
# id possible use user ids
  - auser
# otherwise full names, don't mix both approaches in the same project
  - Aa User
# if the post filename starts with the date 2022-11-01_post-title.md, then the date is
# optional; the date in the frontmatter has higher precendence
date: 2022-09-07
# an execerpt, optional depending on the project
excerpt: Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum
  sint consectetur cupidatat.
# featured image
feature:
# image URL
  image: images/IDH_banner.original.jpg
# image description
  description: Indigenous Digital Humanities Banner
---

Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint
consectetur cupidatat.

Plugins

The 11ty website has a list of both core and community plugins.

Currently used

  • eleventy-navigation plugin for creating hierarchical navigation and breadcrumbs

  • seo plugin to generate meta tags for improved SEO

  • toc plugin to generate table of contents from page headers