I use Linux Mint as my daily OS at home. I use Windows as my daily OS at work. And I use both for web development. I don’t own a Mac, so I can’t say for sure that this guide will work for those, but it shouldn’t be too far off - if at all.

Whatever operating system you use, I trust that you know your way around it well enough that I don’t have to tell you how to install and configure software. With that in mind, I’ll give you a high-level rundown of how I have my development environment setup.

For all practical purposes, it’s probably easier if you install Node, Git, and VS Code first, and then use your Bash (Git Bash) terminal to find your config files, and VS Code to edit them.

You can easily find the config files listed below by opening a bash terminal and typing:

cd
ls -al

and look for the files (.bashrc, .gitconfig, .npmrc).

If VS Code is installed, you should be able to open each file with the code command.

code ~/.bashrc

code ~/.gitconfig

code ~/.npmrc

Nodejs

There are many download options for NodeJS.

If you’re using Linux you will need to choose the link to Install via Package Manager.

If you’re running a Debian or Ubuntu based distro, then you can find the install instructions here: https://github.com/nodesource/distributions

.npmrc

If you have authTokens for npm or github or anywhere else, you can add them here too. Any proxy configs you might have to use would also go in here.

.npmrc

”~/.npmrc”

prefix=/home/username/npm
init-author-name=Your Name
init-version=0.0.1
init-license=MIT
 
save-exact=true
package-lock=false
ignore-scripts=false
save-prefix=
fund=false
Link to original

Git

Downloading and installing git is pretty straight forward. Grab the installer you need from the downloads page and follow the prompts when you run it.

Make sure to install Bash if given the option.

.gitconfig

You will want to add your email and name so that you don’t get prompted every time you commit.

Add the core.editor = code setting to use VS Code as your editor whenever git prompts you for input on anything.

I added some aliases as an example. You would type git adog to show the oneline graph log.

And you can change the name of your default branch if you don’t want it to be “master.”

.gitconfig

~/.gitconfig

[user]
  email = your@email.com
  name = Your Name
[push]
  default = simple
  followTags = true
[core]
  editor = code
[pull]
  rebase = false
[alias]
  adog = log --all --decorate --oneline --graph
  logn = log  --abbrev-commit --all --decorate --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'
[init]
  defaultBranch = master
Link to original

Bash

If you’re running Linux or Mac, then you probably already have bash (or something like it - zsh) installed. If you’re on Windows, then you will have installed Bash when you installed Git For Windows.

If you have zsh or csh or something else, then you will need to edit your .zshrc, or whatever respective rc file your terminal uses.

Here I’m showing you how to export tab-completeable shortcuts that you can use instead of having to type out the full path every time you cd to a folder, or run a command.

I make full use of the aliases so that I don’t have to type out repetitive commands, and some of them I don’t use often enough to memorize them so I just type something and hit tab a couple times to see what my options are, which is a quick way to get a reminder of things I’ve aliased.

.bashrc

.bashrc

”~/.bashrc”

export PATH="$HOME/npm/bin:$HOME/bin:$HOME/.local/bin:$PATH"
export PROJECTS="$HOME/dev/projects"
export UTILS="$PROJECTS/utils"
export NGCOMMON="$PROJECTS/ng-common"
export NGSCHEMATICS="$PROJECTS/ng-schematics"
 
alias ls="ls -a --color"
alias editbashrc="code ~/.bashrc"
alias editnpmrc="code ~/.npmrc"
alias editgitconfig="code ~/.gitconfig"
alias refreshbashrc=". ~/.bashrc"
 
alias updatenpm="npm i -g npm"
alias updatenpmcheckupdates="npm i -g npm-check-updates"
alias updateangularcli="npm i -g @angular/cli@latest"
 
alias nbuild="npm run build"
alias nstart="npm start"
alias ntest="npm test"
alias ntestcov="npm run test:cov"
alias ntestfile="npm run test:file"
alias nlint="npm run lint"
alias ncypress="npm run cypress"
alias npushpatch="npm run push:patch"
alias npushminor="npm run push:minor"
alias npushmajor="npm run push:major"
alias npmi="npm install --ignore-scripts"
alias niutils="npm i -S @bjanderson/utils@latest"
alias niclitool="npm i -g @bjanderson/cli-tool@latest"
alias nimoneytoolshared="npm i -S @bjanderson/moneytool-shared@latest"
alias ningcommon="npm i -S @bjanderson/ng-common@latest"
alias ningschematics="npm i -D @bjanderson/ng-schematics@latest"
 
alias ngcomponent="ng g @bjanderson/ng-schematics:component -n"
alias ngdialog="ng g @bjanderson/ng-schematics:dialog -n"
alias ngmodel="ng g @bjanderson/ng-schematics:model -n"
alias ngservice="ng g @bjanderson/ng-schematics:service -n"
alias ngstore="ng g @bjanderson/ng-schematics:store -n"
alias ngtable="ng g @bjanderson/ng-schematics:table -n"
alias ngtablewithdatasource="ng g @bjanderson/ng-schematics:table-with-data-source -n"
alias ngtablewithserversidedatasource="ng g @bjanderson/ng-schematics:table-with-server-side-data-source -n"
alias ngjest="ng g @bjanderson/ng-schematics:setup-jest"
 
alias gs="git status"
alias ga="git add -A"
alias gc="git commit -m"
alias gcamend="git commit --amend --no-edit"
alias gcmaster="git checkout master"
alias gcdev="git checkout dev"
alias gcedits="git checkout edits"
alias gmedits="git merge edits"
alias gbdedits="git branch -d edits"
alias gcbedits="git checkout -b edits"
alias gnewedits="git branch -d edits && git checkout -b edits"
 
function parse_git_branch () {
 git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
 
BLUE="\[\033[01;34m\]"
GREEN="\[\033[0;32m\]"
RED="\[\033[0;31m\]"
WHITE="\[\033[0m\]"
YELLOW="\[\033[0;33m\]"
PS1="$BLUE\W$YELLOW\$(parse_git_branch)$BLUE\$$WHITE "
Link to original

Visual Studio Code

The installer for VS Code is pretty straight forward too. Just grab the installer from the home page and follow the prompts when you run it. Make sure to select the option to include code in your PATH and to allow it to open files and folders from the right-click menu.

Extensions

VS Code Extensions

  • Angular Language Service: angular.ng-template
  • EditorConfig for VS Code: editorconfig.editorconfig
  • JavaScript (ES6) code snippets: xabikos.JavaScriptSnippets
  • Prettier - Code formatter: esbenp.prettier-vscode
  • Prettier ESLint: rvest.vs-code-prettier-eslint
  • ESLint: dbaeumer.vscode-eslint
  • REST Client: humao.rest-client
  • SQLite: alexcvzz.vscode-sqlite
  • IntelliCode: visualstudioexptteam.vscodeintellicode
  • IntelliCode API Usage Examples: visualstudioexptteam.intellicode-api-usage-examples
Link to original

Settings

VS Code Settings

{
  "angular.enable-strict-mode-prompt": false,
 
  "breadcrumbs.enabled": true,
 
  "css.lint.unknownProperties": "ignore",
  "css.lint.unknownVendorSpecificProperties": "ignore",
 
  "diffEditor.ignoreTrimWhitespace": true,
 
  "editor.autoClosingQuotes": "beforeWhitespace",
  "editor.autoIndent": "brackets",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll": true
  },
  "editor.cursorSurroundingLines": 5,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,
  "editor.insertSpaces": true,
  "editor.minimap.enabled": true,
  "editor.minimap.showSlider": "always",
  "editor.multiCursorModifier": "ctrlCmd",
  "editor.scrollBeyondLastLine": false,
  "editor.snippetSuggestions": "top",
  "editor.suggestSelection": "first",
  "editor.suggest.preview": true,
  "editor.suggest.showDeprecated": false,
  "editor.tabCompletion": "on",
  "editor.tabSize": 2,
  "editor.trimAutoWhitespace": true,
 
  "eslint.alwaysShowStatus": true,
  "eslint.codeActionsOnSave.mode": "problems",
  "eslint.format.enable": true,
  "eslint.options": {
    "extensions": [".html", ".ts", ".tsx", ".js", ".jsx"]
  },
  "eslint.validate": ["javascript", "typescript"],
 
  "explorer.confirmDelete": true,
  "explorer.confirmDragAndDrop": true,
 
  "extensions.ignoreRecommendations": true,
 
  "files.insertFinalNewline": true,
  "files.trimFinalNewlines": true,
  "files.trimTrailingWhitespace": true,
 
  "html.format.enable": true,
  "html.format.endWithNewline": true,
  "html.format.wrapAttributes": "force-expand-multiline",
  "html.format.wrapLineLength": 50,
 
  "javascript.format.enable": false,
  "javascript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true,
  "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
  "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true,
  "javascript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true,
  "javascript.preferences.quoteStyle": "single",
  "javascript.suggest.completeFunctionCalls": true,
  "javascript.updateImportsOnFileMove.enabled": "never",
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  },
 
  "js/ts.implicitProjectConfig.experimentalDecorators": true,
 
  "less.lint.unknownProperties": "ignore",
  "less.lint.unknownVendorSpecificProperties": "ignore",
 
  "rest-client.enableTelemetry": false,
 
  "scss.lint.unknownProperties": "ignore",
  "scss.lint.unknownVendorSpecificProperties": "ignore",
 
  "security.workspace.trust.untrustedFiles": "open",
 
  "typescript.format.enable": false,
  "typescript.format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": true,
  "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
  "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true,
  "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": true,
  "typescript.preferences.quoteStyle": "single",
  "typescript.suggest.completeFunctionCalls": true,
  "typescript.updateImportsOnFileMove.enabled": "never",
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  },
 
  "telemetry.telemetryLevel": "off",
 
  "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
 
  "window.zoomLevel": 0,
 
  "workbench.editor.enablePreview": false,
  "workbench.startupEditor": "none"
}
Link to original

Keybindings

VS Code Keybindings

[
  {
    "key": "ctrl+shift+s",
    "command": "workbench.action.files.saveAll"
  },
 
  {
    "key": "ctrl+up",
    "command": "editor.action.insertCursorAbove",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+shift+up",
    "command": "-editor.action.insertCursorAbove",
    "when": "editorTextFocus"
  },
 
  {
    "key": "ctrl+down",
    "command": "editor.action.insertCursorBelow",
    "when": "editorTextFocus"
  },
  {
    "key": "ctrl+shift+down",
    "command": "-editor.action.insertCursorBelow",
    "when": "editorTextFocus"
  },
 
  {
    "key": "ctrl+shift+/",
    "command": "editor.action.blockComment",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "ctrl+shift+a",
    "command": "-editor.action.blockComment",
    "when": "editorTextFocus && !editorReadonly"
  },
  {
    "key": "alt+q",
    "command": "sqlite.runSelectedQuery"
  }
]
Link to original

Snippets

html

VS Code HTML Snippets

 
  "ahref": {
    "prefix": "ahref",
    "description": "a:href target blank",
    "body": [
      "<a href=\"$1\" target=\"_blank\"  rel=\"noopener noreferrer\">$2</a>"
    ]
  },
 
  {
	"href target blank": {
		"prefix": "target=",
		"body": [
			"target=\"_blank\"  rel=\"noopener noreferrer\""
		],
		"description": "href target blank"
	},
 
    "mat-icon": {
      "prefix": "mat-icon",
      "body": [
        "<mat-icon class=\"icon\" aria-hidden=\"true\" fontSet=\"fas\" fontIcon=\"fa-$0\"></mat-icon>"
      ],
      "description": "mat-icon"
    },
 
	"language-bash": {
		"prefix": "language-bash",
		"body": [
			"<code class=\"language-bash\">$0</code>"
		],
		"description": "language-bash"
	},
 
	"language-javascript": {
		"prefix": "language-javascript",
		"body": [
			"<code class=\"language-javascript\">$0</code>"
		],
		"description": "language-javascript"
	},
 
	"language-text": {
		"prefix": "language-text",
		"body": [
			"<code class=\"language-text\">$0</code>"
		],
		"description": "language-text"
	}
}
 
Link to original

javascript

VS Code JavaScript Snippets

{
  "Print to console": {
    "prefix": "llog",
    "body": ["console.log('$0');"],
    "description": "Log output to console"
  },
 
  "Print vlaue to console": {
    "prefix": "ccl",
    "body": ["console.log('$0: ', $0);"],
    "description": "Log value to console"
  },
 
  "noop": {
    "prefix": "noop",
    "body": ["() => undefined"],
    "description": "noop"
  },
 
  "import": {
    "prefix": "import",
    "body": ["import { $2 } from '$1';"],
    "description": "import"
  },
 
  "describe test": {
    "prefix": "desc",
    "body": ["describe('$0', () => {", "", "});"],
    "description": "describe test"
  },
 
  "create test": {
    "prefix": "itt",
    "body": [
      "it('$0', () => {",
      "  const expected = '';",
      "  const result = '';",
      "  expect(result).toEqual(expected);",
      "});"
    ],
    "description": "create test"
  },
 
  "create test with spy": {
    "prefix": "ittspy",
    "body": [
      "it('calls $0', () => {",
      "  spyOn(component, '$0').and.returnValue(null);",
      "  component.();",
      "  expect(component.$0).toHaveBeenCalled();",
      "});"
    ],
    "description": "create test with spy"
  },
 
  "filter": {
    "prefix": "filter",
    "body": ["filter((v,i,a) => a.indexOf(v) === i)"],
    "description": "filter unique values in an array"
  }
}
Link to original

typescript

VS Code TypeScript Snippets

{
  "Create Server Model": {
    "prefix": "smodel",
    "body": [
      "import { getObject, getString } from '@bjanderson/utils';",
      "import { IHasPK } from './ihaspk';",
      "",
      "export class $0 implements IHasPK {",
      "  pk: string;",
      "",
      "  constructor(o?: Partial<$0>) {",
      "    const obj: Partial<$0> = getObject(o);",
      "    this.pk = getString(obj.pk);",
      "  }",
      "}"
    ],
    "description": "Create Server Model"
  },
 
  "Print to console": {
    "prefix": "llog",
    "body": ["console.log('$0');"],
    "description": "Log output to console"
  },
 
  "Print vlaue to console": {
    "prefix": "ccl",
    "body": ["console.log('$0: ', $0);"],
    "description": "Log value to console"
  },
 
  "Print error to console": {
    "prefix": "lerror",
    "body": ["console.error(`ERROR : $1 : ${$0}`);"],
    "description": "Log error to console"
  },
 
  "initialize model object": {
    "prefix": "ob",
    "body": ["obj = getObject(obj);"],
    "description": "initialize a model object"
  },
 
  "noop": {
    "prefix": "noop",
    "body": ["() => undefined"],
    "description": "noop"
  },
 
  "import": {
    "prefix": "bimport",
    "body": ["import { $2 } from '$1';$0"],
    "description": "import"
  },
 
  "export": {
    "prefix": "bexport",
    "body": ["export * from '$1';$0"],
    "description": "export"
  },
 
  "describe test": {
    "prefix": "desc",
    "body": [
      "describe('$0()', () => {",
      "  beforeEach(() => {",
      "    init();",
      "  });",
      "",
      "  it('is a function', () => {",
      "    expect(typeof component.$0).toEqual('function');",
      "  });",
      "});"
    ],
    "description": "describe test"
  },
 
  "create test": {
    "prefix": "itt",
    "body": [
      "it('$0', () => {",
      "  const expected = {};",
      "  const result = {};",
      "  expect(result).toEqual(expected);",
      "});"
    ],
    "description": "create test"
  },
 
  "create test with spy": {
    "prefix": "ittspy",
    "body": [
      "it('calls $0()', () => {",
      "  const spy = jest.spyOn(component, '$0');",
      "  component.();",
      "  expect(spy).toHaveBeenCalled();",
      "});"
    ],
    "description": "create test with spy"
  },
 
  "create init function": {
    "prefix": "finit",
    "body": ["function init() {", "  $0", "}"],
    "description": "create init function"
  },
 
  "ngOnDestroy unsubscribe": {
    "prefix": "ngOnDestroy",
    "body": [
      "unsubscribe = new Subject();",
      "ngOnDestroy(): void {",
      "  this.unsubscribe.next();",
      "  this.unsubscribe.complete();",
      "}"
    ],
    "description": "ngOnDestroy unsubscribe"
  },
 
  "new class": {
    "prefix": "exportclass",
    "body": [
      "import { getObject, getString } from '@bartleyanderson/utils';",
      "",
      "export class $0 {",
      "",
      "  value: string;",
      "",
      "  constructor(obj?: Partial<$0>) {",
      "    obj = getObject(obj);",
      "    this.value = getString(obj.value);",
      "  }",
      "}"
    ],
    "description": "new class"
  },
 
  "mockservice": {
    "prefix": "mockservice",
    "body": ["const $0: any = {", "  $0: () => undefined,", "};"],
    "description": "mock test service"
  },
 
  "filter": {
    "prefix": "filter",
    "body": ["filter((v,i,a) => a.indexOf(v) === i)"],
    "description": "filter unique values in an array"
  }
}
Link to original

css

VS Code CSS Snippets

{
  "css-starter": {
    "prefix": "css-starter",
    "body": [
      "html {",
      "  box-sizing: border-box;",
      "}",
      "",
      "*,",
      "*:before,",
      "*:after {",
      "  box-sizing: inherit;",
      "}",
      "",
      "html, body {",
      "  font-family: system-ui;",
      "  font-size: 16px;",
      "  height: 100%;",
      "  width: 100%;",
      "  margin: 0;",
      "  padding: 0;",
      "}"
    ],
    "description": "css-starter"
  }
}
Link to original

scss

VS Code SCSS Snippets

{
  "css-starter": {
    "prefix": "css-starter",
    "body": [
      "html {",
      "  box-sizing: border-box;",
      "}",
      "",
      "*,",
      "*:before,",
      "*:after {",
      "  box-sizing: inherit;",
      "}",
      "",
      "html, body {",
      "  font-family: system-ui;",
      "  font-size: 16px;",
      "  height: 100%;",
      "  width: 100%;",
      "  margin: 0;",
      "  padding: 0;",
      "}"
    ],
    "description": "css-starter"
  }
}
Link to original