A collection of template repositories for new projects.
Starting a new project repository means to spend a lot of time first for setting up the basic structure and configuration for the used technology stack over and over again. It is a repetitive task since the same tools are often used across many projects, like linters and code formatters, and therefore often just copied over. This has the disadvantage that the configuration or documentation may differ between different projects or common changes and configurations are not synchronize at all. Many tools provide a way to created so called “shared configurations“ that can be used as base and dynamically composed with project-specific configurations, however, this does not apply to all. To prevent such problems a central place, so called “template repository“, for basic configurations and documentations as well as focus on different use cases, project structures and programming languages is a good solution to act as a single-source-of-truth™️.
tmpl, the imaginative abbreviation for “template“, is my solution to enable a smooth project start and ensure that a project stays healthy, stable and up-to-date over time. It is separated into context, layout and/or language specific templates where each lives in its own repository. Please note that tmpl has mainly been created for my personal use in mind. The default configurations of these templates might not fit your needs, but they were designed to be flexible and can be adapted to different use cases and environments.
This repository serves as the base template repository of tmpl that provides essential features for every project.
- GitHub specific features like…
- …definitions for code owners
- …individual issue templates
- …a extensive pull request template
- …basic CI/CD action workflows
- …automated updates and security vulnerability alerts for dependencies through the native Dependabot integration
- Configurations for npm and Yarn
- Basic configurations for Git
- A MIT license
- EditorConfig integration
- Prettier for “auto-magical“ code& text formatting
- remark-lint to lint Markdown
- lint-staged for Automatic pre-commit linting
- husky to manage and run Git Hooks
See the “Features“ section below for more details.
Like mentioned in the introduction above, tmpl is separated into multiple scalable tmpl repositories based on different project layouts, languages and/or context. See the documentations of the specific repository for more details about the use case(s) and how to use it as template:
tmpl
├─ .github
│ ├─ ISSUE_TEMPLATE
│ └─ workflows
└─ assets
└─ images
The current directory structure consists of basic directories mainly targeted for repositories hosted on GitHub, but the contained files can also be simply adjusted for usage with other platforms. Please see the GitHub Features section below for more details about the provided files.
.github
— The base directory for configurations and documentations of GitHub features like action workflows and issue/pull request templates..github/ISSUE_TEMPLATE
— The directory for individual issue template files..github/workflows
— The directory for action workflow files.
.assets
— A common base directory for (binary) projects assets like media or tool specific files that is independent of the repository hosting platform..assets/images
— The sub-directory for project and/or repository specific images like SVG or raster graphics.
This repository serves as the base template repository of tmpl that provides essential features for every project.
The sections below contain more detailed information about each feature, the sane default configurations and their files in the repository as well as ways to customize and adjust them to adapt to other use cases and projects. They provide details about files in this repository and the overall directory structure.
This template repository has partially been designed for repositories hosted on GitHub and makes use of many of its fantastic features.
The .github/CODEOWNERS
file defines individuals or teams that are responsible for code in a repository and automatically requested for review when a contributor opens a pull request that modifies files that they own.
The individual issue template files in the .github/ISSUE_TEMPLATE
directory are automatically used as content when a contributor creates a new issue where each file will be available as template in the issue template chooser.
Note that the .github/ISSUE_TEMPLATE.md
file is still included in this repository, but has been official deprecated by GitHub in favor of these individual issue template files.
The .github/PULL_REQUEST_TEMPLATE.md
file is automatically used as content when a contributor creates a new pull request. It can also be used for automation and as URL query parameter value e.g. do directly link to it in documentations.
The GitHub Actions .github/workflows
directory includes basic CI/CD workflow files that runs for changes in the Git main
branch and v*
tags. There is currently one job called lint-node
that runs all linters that are included in this template repository. See sections like “Automatic Code and Text Formatter“, “Markdown Linting“ and “Automatic Pre-Commit Linting“ below for more details.
To skip a workflow, include a supported keyword like [skip actions]
in a commit message.
To ensure dependencies of various package ecosystems are up-to-date, Dependabot has been natively integrated into GitHub. It creates automated updates and security vulnerability alerts for dependencies.
The basic dependabot.yml
file in this template repository contains the configuration for GitHub Action workflows and Node.js dependencies.
Note that you must manually enable or disable version and security Dependabot updates per repository!
Since most of the tools included in this template repository like…
- Prettier for “auto-magical“ code & text formatting
- remark-lint for linting of Markdown source files
- lint-staged for automatic pre-commit linting
- husky as Git Hook manager & runner
…are (unfortunately) written in JavaScript for Node, npm/Yarn is required to manage these packages.
The package.json
and .npmrc
files declare Node specific configurations like the development dependencies and the package-lock
, save-exact
and save-prefix
version resolution strategy. npm is the main package manager so Yarn‘s yarn.lock
file should not be used and tracked in order to prevent conflicts with the package-lock.json
file.
Note that as of version 0.9.0
the minimum versions for npm is >=7.7.0
, bundled with Node >=15.13.0
, in order to use the run
and exec
commands with workspaces.
The .gitattributes
and .gitignore
configuration files define basic pattern. This includes pattern when using git-crypt to encrypt and store secrets within the repository as well as pattern for the fantastic Jetbrains products like IntelliJ.
There is also the .mailmap
file that…
- …serves as a reference to involved project maintainers and teams and also allows contributors to send mails regarding security issues.
- …prevents unnecessary overhead of updating all documentations when new core team members and contributors are added.
- …fulfills it main purpose and functionality: Mapping commit authors when someone changed their email address or uses a different one.
The tmpl project and its repositories are licensed under the MIT license which is included as LICENSE
file.
The .editorconfig
file allows to define and maintain consistent coding styles between different editors and IDEs. It is a well-known file that can, next to tools that are specialized to specific languages and formats, help to keep the style of source code and documentations healthy.
A code formatter is a essential part of a project setup to ensure a good and consistent code style without requiring relatively time-consuming manual corrections found by a code linter. With code being automatically formatted on actions like saving a file the developer can focus entirely on the code instead of spending time and energy on indenting code line by line.
That‘s where one special project comes in: Prettier, the opinionated code formatter with support for almost any language and integration with almost every popular editor. I‘ve been using it since the first version and I totally forgot about the fact that formatting is even a thing. That could also be because Gophers are already used to gofmt
anyway.
Prettier is a absolute must-have for every project setup and I‘m not aware of any other projects with such advanced parsers and language support. The only negative point is that it is written in JavaScript instead of Go so it always pulls in Node as a development dependency. This is not a problem at all for web-based projects, but for Go or any other non Node.js project it inflates the setup unnecessarily.
Anyway, the fantastic developer experience and project benefits clearly outweigh the negative points. In addition many developers today already have Node installed locally since its large ecosystem has already spread by far further than just the web but already powers many system, desktop and CLI applications.
One of the main features of Prettier is its configuration: It already provides the best and recommended style configurations of-out-the-box™.
The only option that was adjusted for this template repository is the print width. It is set to 80
by default which is not up-to-date for modern screens (might only be relevant when working in TUIs like e.g. vim). It has been changed to 120
like defined in all of my style guides.
The prettier.config.js
configuration file is placed in the project root as well as the .prettierignore
file that defines ignore pattern.
To allow to format all sources a format:pretty
npm package script is available that also runs in the main format
script flow. The lint:pretty
script allows to check if all supported files are formatted correctly and is also included in the main lint
script flow.
Ensuring that documentations and content written in Markdown are of great quality should be a continuous goal of any project. Persisting information is a consistent and extensive way helps tp keep a project healthy, no matter whether for long-time or new users ad well as maintainers and contributors. Linting Markdown results in better rendering with different markdown parsers and makes sure less refactoring is needed afterwards.
The best solution for this task would be a tool written in Go, but the undisputed best tool is still remark-lint which is (unfortunately) written in JavaScript and used via Node. Of course there are fantastic projects written in Go like goldmark that provides a great way to parse content, but linting is (currently) not a feature. remark-lint on the other side is built on top of remark, the powerful Markdown processor powered by plugins (such as remark-lint itself) and part of the unified collective. It comes with a really large set of customizable rule and ways to ensure Markdown will be consistent across any project.
Another decision point for remark-lint was the fact that Prettier (see section “Automatic Code and Text Formatter“) so Node.js is already a development dependency anyway. This also allows to add other awesome projects that are (unfortunately) written in JavaScript and for which there is no comparable alternative.
remark-lint can be used via remark-cli and a rule preset. This preset is remark-preset-lint-arcticicestudio, my custom preset that implements my Markdown Style Guide.
Since the custom preset is still in major version 0
the version range is currently >=0.x.x <1.0.0
to avoid the “SemVer Major Zero Caveat”. When defining package versions with the the carat ^
or tilde ~
range selector it won‘t affect packages with a major version of 0
. npm will resolve these packages to their exact version until the major version is greater or equal to 1
.
To avoid this caveat the more detailed version range >=0.x.x <1.0.0
is used to resolve all versions greater or equal to 0.x.x
but less than 1.0.0
. This will always use the latest 0.x.x
version and removes the need to increment the version manually on each new release.
The .remarkrc.js
configuration file is placed in the project root as well as the .remarkignore
file that defines ignore pattern.
To allow to run the Markdown linting separately the lint:md
npm package script is available and included in the main lint
script flow.
Git Hooks are a fantastic way to customize the development workflow of a project to simplify and automate specific tasks that are required when working on the code base. For example, formatting, linting and running tests before pushing a commit to ensure it conforms to the code style and works as expected. Most Git Hooks are not that complex and fullfil a simple purpose while other solutions like danger can help to manage larger projects and projects that need to scale.
This template repository uses a Git Hook that automatically runs configured linters on all files that have been staged and that match the configured pattern like file extensions or names. Like described in the “Automatic Code and Text Formatter“ section above, Node is already a development dependency anyway so the lint-staged NPM package is used for this goal. I‘ve used this package in almost any project and it is the most stable, production-proven and advanced tool that is currently out there with no comparable alternatives in other languages.
The configuration file lint-staged.config.js
is placed in the project root and includes the command that should be run for matching file extensions. It currently contains entries for the following linters that run in the same order as listed here:
prettier --list-different
- Runs Prettier (see section “Automatic Code and Text Formatter“) to ensure all files are formatted correctly. The--check
flag prints files that are not conform with the Prettier configuration.remark --no-stdout
- Runs remark-lint (see section “Markdown Linting“) against*.md
to ensure all Markdown files are compliant to the style guide. The--no-stdout
flag suppresses the output of the parsed file content.
In section “Automatic Pre-Commit Linting“ the integration of lint-staged, a Git Hook runner that runs linters against staged files, is described and how it is used in this template repository. To automatically run it and other Git Hooks the hook manager and runner husky is used.
Just like other already added tools described in the sections above, husky is (unfortunately) also written in JavaScript. Since Node is therefore already a development dependency it doesn‘t really matter that husky is another Node.js package too. Unlike the other tools there are indeed alternatives written in Go like lefthook or quickhook, but it requires time to test and evaluate them before actually replacing husky. Also a long as there are no comparable alternatives to the already used tools listed above, this template would be more complex by requiring both Node.js and Go as development dependency. Therefore husky took over the part as hook manager & runner for this template repository since it is a stable, production-proven and advanced project that I already use in almost any other project setup.
The .huskyrc.js
configuration file is placed in the project root and includes the command to run for any supported Git Hook. It contains entries for the following hooks:
pre-commit
- Runs lint-staged (see section “Automatic Pre-Commit Linting“) before each commit to ensure all staged files are compliant to all style guides.
There are multiple ways to use this template repository, either by using GitHubs feature to create a repository from a template or simply cloning it. No matter which method is used, there are a few manual steps to adjust some configurations and documentations for the individual target project. Note that these changes are only recommendations, but are common steps anyway.
- Adjust the
.github/CODEOWNERS
and.mailmap
files to use mappings for your project contributors and team members. - Adjust files related to GitHub features like the CI/CD action workflow, issue & pull request templates, code owners and any other file located in the
github
directory to match your project. - Adjust documentations like the README, changelog, code of conduct and contribution guides to match your project.
- Adjust the
package.json
file to match your project. - Adjust the
dependabot.yml
file to match your project. - Adjust all copyright notices to match your project.
tmpl is an open source project and contributions are always welcome!
There are many ways to contribute, from writing- and improving documentation and tutorials, reporting bugs, submitting enhancement suggestions that can be added to tmpl by submitting pull requests.
Please take a moment to read the contributing guide to learn about the development process, the styleguides to which this project adheres as well as the branch organization and versioning model.
The guide also includes information about minimal, complete, and verifiable examples and other ways to contribute to the project like improving existing issues and giving feedback on issues and pull requests.
Copyright © 2020-present Sven Greb