Skip to content
/ extreme-angular Public template

Extreme Angular is a strict & opinionated starter template with pre-configured settings for ESLint, Prettier, Stylelint, CSpell, Git hooks, CI/CD, and VS Code.

License

Notifications You must be signed in to change notification settings

joematthews/extreme-angular

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

229 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Extreme Angular: A Stricter Starter Template

Meme showing Iron Man wearing the Nano Gauntlet before saving Earth. The caption reads, 'WHEN YOU FINALLY GET ALL THE DEV TOOLS TO WORK TOGETHER'

Extreme Angular adds strict development tooling to a standard Angular project. Use it as a starter template or as a reference for configuring these tools in an existing project.

The underlying Angular project was generated with:

ng new --strict --zoneless --style=scss --ssr=false

Why Use Extreme Angular

Starting a new Angular project with ng new gives you a working app, but not the tooling layer that teams typically add over time. Extreme Angular bridges that gap:

  • ESLint with angular-eslint, typescript-eslint (strict + stylistic), accessibility rules, and JSON linting
  • Prettier with plugins for import sorting, CSS property ordering, and shell script formatting
  • Stylelint for CSS and SCSS
  • CSpell for spell checking
  • Husky + lint-staged for pre-commit linting and pre-push validation
  • Commitlint for conventional commit messages
  • GitHub Actions CI for pull request validation
  • Strict TypeScript and Angular compiler settings beyond Angular's default strict mode

These tools are configured to work together without conflicts. Nothing here deviates from standard Angular — the official Angular documentation applies without modification.

Contributing

We welcome contributions! Please see our Contributing Guidelines for details on how to get started.

Found an issue? Check the existing issues first, then create a new one if needed.

Table of Contents

Getting Started

Clone the repository and install dependencies (replace my-project with your project name):

git clone --depth=1 --origin=upstream https://github.com/joematthews/extreme-angular.git my-project
cd my-project
npm install

Using --origin=upstream names the remote upstream instead of origin, making it possible to pull in updates later.

Tip

You can also select "Use this template" on the GitHub page to create a new repository. Note that template repositories don't maintain a connection to the original, so pulling in updates requires additional setup.

Search and replace extreme-angular with your project name across the codebase, then start developing:

npm start

Tip

If you're using VS Code and Chrome, press F5 to start the app in debug mode. For more information check out: TypeScript in Visual Studio Code.

Tip

The "Dev Tools Implemented" section below is project-agnostic — consider adding it to your project's README.md or CONTRIBUTING.md!

Dev Tools Implemented

This section outlines how each tool is configured, and how they can be leveraged to ensure clean and maintainable code.

Use this script to run all checks against all project files:

npm run lint:all

Caution

These tools are not perfect and they are not a substitute for learning and utilizing the best practices outlined in the Angular guides for Style, Security, Accessibility, and Performance.

TypeScript

Beyond Angular's default strict mode, this template enables additional TypeScript strictness in tsconfig.json to catch more potential issues at compile time:

Enhanced compiler options:

  • exactOptionalPropertyTypes — Prevents assigning undefined to optional properties, ensuring type safety when properties are explicitly optional vs. potentially undefined
  • noUnusedLocals — Reports errors for unused local variables, helping keep your code clean and reducing bundle size
  • noUnusedParameters — Reports errors for unused function parameters, encouraging cleaner function signatures and better code maintainability
  • noUncheckedIndexedAccess — Adds undefined to array access and object property access, forcing explicit checks and preventing runtime errors
  • useUnknownInCatchVariables — Changes catch clause variables from any to unknown, requiring explicit type checking for better error handling safety

Type checking commands:

npm run lint:tsc:app  # Check app files (*.ts)
npm run lint:tsc:spec # Check test files (*.spec.ts)
npm run lint:tsc:all  # Check all TypeScript files

Project structure:

The project uses TypeScript project references with separate configs for different contexts:

All extend tsconfig.json to share the same strict settings.

ESLint

ESLint is used for linting JavaScript, TypeScript, HTML, and JSON files in the project. The linting configuration is set in eslint.config.js, with specific overrides for the following file types: *.js, *.ts, *.spec.ts, *.html, and *.json.

To ensure effective linting for all project files, the following ESLint plugins are used:

To lint all relevant files in the project (not just those in src/):

npm run lint

ESLint output is formatted using eslint-formatter-mo. To use default formatting, remove -f mo from the lint script in package.json.

Tip

Suppress the urge to immediately set rules to "off" or "warn". First, look up the rule and the problem it is correcting for and discuss the rule with other developers on the project.

Accessibility (a11y)

This project enables all the accessibility rules provided by angular-eslint by default (denoted by :accessibility: in the @angular-eslint/template rules configuration matrix linked above).

Includes rules for image alt text, form labels, no autofocus, valid ARIA, and more.

These rules are easier to work with if enabled early in the development process and early adoption of these rules is also very helpful for avoiding common accessibility antipatterns.

The Accessibility in Angular guide is a great place to start learning about accessibility in Angular, and it provides resources on the topic of accessibility.

Stylelint

Stylelint is used to lint CSS and SCSS files in the project. It is configured with the stylelint-config-standard and stylelint-config-standard-scss configurations.

Rules for linting are applied separately to .css and .scss files, and they can be customized in .stylelintrc.json.

To lint all CSS and SCSS files:

npm run lint:style

Prettier

Prettier is used to enforce consistent code formatting, reducing diffs by minimizing formatting changes.

The base settings in .prettierrc.json (printWidth: 100, singleQuote: true) match Angular defaults. This template adds the following enhancements:

htmlWhitespaceSensitivity: "ignore" — Trims unnecessary whitespace around and inside HTML elements for cleaner templates. Use   (non-breaking space) when you need to explicitly maintain spacing between inline elements.

Plugins:

To format files within the project:

npm run format

To check if all files are properly formatted:

npm run lint:format

Important

Angular v20 dropped the .component suffix from component templates, so an override has been setup in .prettierrc.json to parse ["src/app/*.html"] using the Angular parser. If you add additional Angular applications to the project, make sure to update the overrides array to include their HTML file paths (e.g., 'src/new-app/*.html') so Prettier can properly parse those template files.

CSpell

CSpell is used for spell checking for all project files.

To add project-specific words, update .cspell.json.

The Code Spell Checker Extension for VS Code allows you to quickly add misspelled words to the configuration by selecting "Add to config: .cspell.json" from the 'Quick Fix' menu.

The following dictionaries have been enabled: bash, companies, cpp, csharp, css, filetypes, fonts, go, html, latex, misc, node, npm, php, powershell, python, softwareTerms, and typescript.

To find misspelled words in all files within the project:

npm run lint:spelling

Testing

Vitest is the default unit test runner for Angular, replacing Karma. Tests run in Node.js using jsdom to simulate the DOM, providing fast test execution without browser overhead.

To run tests in watch mode:

npm test

To run tests once (for CI):

npm run test:ci

Note

Vitest with jsdom is significantly faster than Karma with a real browser. For most unit tests, jsdom provides sufficient DOM simulation. If you need real browser testing, Angular supports running Vitest with Playwright — see the Angular testing documentation.

Tip

For end-to-end testing, see the End to End Testing (e2e) section under Optional Configuration.

Tip

Want VS Code Test Explorer integration? See the experimental workaround. Note: this is unsupported and may break with future Angular updates.

VS Code

The following VS Code extensions will be recommended when opening the project (.vscode/extensions.json):

The following VS Code settings have been set in .vscode/settings.json:

Husky, Commitlint, and Lint-Staged (Git hooks)

Husky is used to manage the pre-commit, pre-push, and commit-msg git hooks.

Commitlint is used to enforce good commit messages according to the @commitlint/config-conventional configuration in the commit-msg git hook. Additional Commitlint configuration is kept in commitlint.config.js.

Lint-staged is used to run Prettier, ESLint, Stylelint, and CSpell in the pre-commit git hook against all staged files. Lint-staged configuration is kept in .lintstagedrc.json

Shove Progress

You can bypass the git hooks using git commit --no-verify and git push --no-verify. Or, use the shove script in emergencies when progress needs to be backed up quickly:

npm run shove

The shove script will stage all files, commit with the commit message wip: shoved, and then push.

Note

The shove script sets git config push.autoSetupRemote true to increase the likelihood that the push will be successful. If you prefer to set the remote branch names manually you may need to set this option back to false.

Warning

The --no-verify flag cannot be disabled. To protect against untested code use a Continuous Integration solution.

Continuous Integration (CI) Using GitHub Actions

The on-pull-request.yml workflow triggers validate-code.yml to check all files and run tests when a pull request is opened or updated.

Pull requests on GitHub cannot be merged until all checks and tests pass. The output of these workflows can be found in the 'Actions' tab on the GitHub repository.

To execute these checks and tests locally:

npm run ci:all

Optional Configuration

Internationalization (i18n)

Angular has powerful Internationalization capabilities.

If you plan to implement internationalization in the future, adding i18n attributes early on can make the process easier to scale naturally.

To enable the i18n ESLint rule, add the following rule to the *.html section of eslint.config.js:

"@angular-eslint/template/i18n": "error",

Note

You may also need to configure the @angular-eslint/template/i18n rule according to your project's needs.

Tip

Using eslint --fix can automatically add i18n tags in many cases.

End to End Testing (e2e)

Angular has schematics available for several end to end testing frameworks. The Angular End to End Testing guide will walk you through the steps to set one up.

The eslint-plugin-playwright package has rules for the popular Playwright framework. To incorporate these rules, import the plugin in the eslint.config.js file and then add a new config object that targets e2e/**/*.spec.ts files:

import { playwright } from 'eslint-plugin-playwright';
  {
    files: ['e2e/**/*.spec.ts'],
    extends: [...playwright.configs['flat/recommended'], prettierConfig],
    rules: { ...playwright.configs['flat/recommended'].rules },
  },

Tips & Tricks

These are tips and tricks that are too opinionated or situational to include in the repository configuration or are not related to Angular project configuration.

Custom Formatting

This project uses Angular's formatting defaults: 2 space indentation, 100 character line width, and single quotes. Here's how to customize if needed:

Indentation — set indent_size in .editorconfig:

[*]
indent_size = 4

Line width — set printWidth in .prettierrc.json:

{
  "printWidth": 80
}

Double quotes — set singleQuote in .prettierrc.json and update .editorconfig for IDE support:

{
  "singleQuote": false
}
[*.ts]
quote_type = double
ij_typescript_use_double_quotes = true

After making changes, run npm run format to re-format all files.

Here are some reasons for sticking with the defaults:

  • Angular's documentation and libraries use 2 space indentation and single quotes.
  • 4 space indentation can look cramped with a 100 character line width.
  • 100 characters balances readability with side-by-side editor layouts on modern displays.

Git Config

To automatically set the remote branch name to match the local branch name on push:

git config push.autoSetupRemote true

You can use VS Code to edit commit messages when using commands like git commit, git rebase, and git commit --amend. This will only work if the code command in the PATH. Follow these instructions to set up the VS Code cli on macOS if it is not already set up. Run this command to set it up:

git config core.editor "code --wait"

If you use GitHub, and you'd prefer to not show your email in public commits, set your email to the one found on your GitHub account settings under the 'Email' tab. This is the same email used by GitHub Desktop, and when edits are made directly on the GitHub site.

git config user.email "14097616+joematthews@users.noreply.github.com"

Tip

You can add the --global flag to these commands to make them the default for all new projects.

Inlay Hints in VS Code

Consider enabling inlay hints in VS Code. They make it easier to rely on TypeScript's type inference without feeling the need to specify types 'for visibility'.

Add the following to the VS Code user settings to enable all inlay hints for JavaScript & TypeScript:

{
  "editor.inlayHints.enabled": "onUnlessPressed",
  "javascript.inlayHints.functionLikeReturnTypes.enabled": true,
  "javascript.inlayHints.parameterNames.enabled": "literals",
  "javascript.inlayHints.parameterTypes.enabled": true,
  "javascript.inlayHints.propertyDeclarationTypes.enabled": true,
  "javascript.inlayHints.variableTypes.enabled": true,
  "typescript.inlayHints.enumMemberValues.enabled": true,
  "typescript.inlayHints.functionLikeReturnTypes.enabled": true,
  "typescript.inlayHints.parameterNames.enabled": "literals",
  "typescript.inlayHints.parameterTypes.enabled": true,
  "typescript.inlayHints.propertyDeclarationTypes.enabled": true,
  "typescript.inlayHints.variableTypes.enabled": true
}

To temporarily disable inlay hints use CTRL + ALT (or CTRL + OPTION on Mac) -- Or, to reverse this behavior use:

{
  "editor.inlayHints.enabled": "offUnlessPressed"
}

Font Ligatures

VS Code is capable of using 'font ligatures' -- they are worth trying if you haven't already.

The two most popular fonts that support font ligatures are Fira Code and Jet Brains Mono. The 'Regular' *.ttf variant of each font is a good starting point.

After downloading and installing the font of choice, add the font to the fontFamily and enable fontLigatures in the VS Code user settings:

{
  "editor.fontFamily": "'Fira Code', Menlo, Monaco, 'Courier New', monospace",
  "editor.fontLigatures": true
}

The Fira Code repository maintains a list of alternative fonts with ligatures.

Shell Configuration Frameworks

  • Oh My Zsh: Popular on macOS, where zsh is now default.
  • Oh My Bash: Popular on Linux, where bash is usually default.
  • Oh My Posh: Cross-platform. Popular on Windows. Works with many shells.
  • Starship: Cross-platform. Written in Rust.

These are great frameworks for managing shell configuration. They include helpful functions, plugins, helpers, and themes.

Shell configuration frameworks are a quick way to add git branch & status information to the shell prompt.

JetBrains IDEs

Webstorm, Rider & RustRover are now free to use for non-commercial use!

Here are some tips for configuring the dev tools for this project in JetBrains IDEs:

  • ESLint, Stylelint, Prettier
    • Search for each name in the settings to easily find all relevant configuration.
    • Double check all three plugins are installed.
    • Set configuration to 'Automatic' for each and match the file extensions that are found in scripts section of package.json.
    • (Optional) Set "Run on save" for each plugin if preferred.
  • Install the "CSpell Check" plugin to reduce conflicts with JetBrains' built-in spell-checking.
  • (Optional) Set keymap to 'VS Code' or 'VS Code (macOS)' for an easier transition
  • (Optional) Search for 'ligatures' in the settings to enable font ligatures. JetBrainsMono is capable of displaying ligatures and is installed with the IDE

Updating

Warning

If the Angular version has changed, follow the Angular update guide before merging. For mature projects with heavy customization, reviewing the release notes and applying changes manually may be safer than merging.

If you don't have an upstream remote (e.g., you used "Use this template"), add one:

git remote add upstream https://github.com/joematthews/extreme-angular.git

Create a branch and merge the latest changes:

git checkout main && git pull
git checkout -b update
git merge upstream/main

Resolve any merge conflicts, then install dependencies and validate:

npm install
npm run ci:all