diff --git a/package-lock.json b/package-lock.json
index e77d704b..6cd532f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -127,6 +127,12 @@
         "normalize-path": "2.1.1"
       }
     },
+    "app-root-path": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz",
+      "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=",
+      "dev": true
+    },
     "argparse": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
@@ -1560,6 +1566,12 @@
         "readdirp": "2.1.0"
       }
     },
+    "ci-info": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz",
+      "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=",
+      "dev": true
+    },
     "cipher-base": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
@@ -1600,6 +1612,38 @@
       "integrity": "sha1-75h+09SDkaw9q5GAtAanQhgNbmo=",
       "dev": true
     },
+    "cli-truncate": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
+      "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
+      "dev": true,
+      "requires": {
+        "slice-ansi": "0.0.4",
+        "string-width": "1.0.2"
+      },
+      "dependencies": {
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "1.0.1"
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
+          }
+        }
+      }
+    },
     "cli-width": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
@@ -2299,6 +2343,12 @@
       "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz",
       "integrity": "sha1-agdBWgHJH69KMuONnfunH2HLIP4="
     },
+    "date-fns": {
+      "version": "1.28.5",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.28.5.tgz",
+      "integrity": "sha1-JXz8RdMi30XvVlhmWWfuhBzXP68=",
+      "dev": true
+    },
     "date-now": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
@@ -2664,6 +2714,12 @@
       "integrity": "sha1-QcE0V8xxZsXBXnZ65h2GqMrN7l0=",
       "dev": true
     },
+    "elegant-spinner": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
+      "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
+      "dev": true
+    },
     "elliptic": {
       "version": "6.4.0",
       "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
@@ -3142,6 +3198,12 @@
         "clone-regexp": "1.0.0"
       }
     },
+    "exit-hook": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+      "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
+      "dev": true
+    },
     "expand-brackets": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
@@ -4697,6 +4759,31 @@
       "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
       "dev": true
     },
+    "husky": {
+      "version": "0.14.3",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
+      "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==",
+      "dev": true,
+      "requires": {
+        "is-ci": "1.0.10",
+        "normalize-path": "1.0.0",
+        "strip-indent": "2.0.0"
+      },
+      "dependencies": {
+        "normalize-path": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
+          "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+          "dev": true
+        },
+        "strip-indent": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+          "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+          "dev": true
+        }
+      }
+    },
     "iconv-lite": {
       "version": "0.4.15",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz",
@@ -4950,6 +5037,15 @@
       "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
       "dev": true
     },
+    "is-ci": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz",
+      "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=",
+      "dev": true,
+      "requires": {
+        "ci-info": "1.0.0"
+      }
+    },
     "is-date-object": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
@@ -5523,6 +5619,230 @@
         "immediate": "3.0.6"
       }
     },
+    "lint-staged": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-4.0.3.tgz",
+      "integrity": "sha1-HOVVkbwsg6eBqQtpoKDIqg/GNws=",
+      "dev": true,
+      "requires": {
+        "app-root-path": "2.0.1",
+        "cosmiconfig": "1.1.0",
+        "execa": "0.8.0",
+        "listr": "0.12.0",
+        "lodash.chunk": "4.2.0",
+        "minimatch": "3.0.4",
+        "npm-which": "3.0.1",
+        "p-map": "1.1.1",
+        "staged-git-files": "0.0.4"
+      },
+      "dependencies": {
+        "cosmiconfig": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-1.1.0.tgz",
+          "integrity": "sha1-DeoPmATv37kp+7GxiOJVU+oFPTc=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "4.1.11",
+            "js-yaml": "3.7.0",
+            "minimist": "1.2.0",
+            "object-assign": "4.1.1",
+            "os-homedir": "1.0.2",
+            "parse-json": "2.2.0",
+            "pinkie-promise": "2.0.1",
+            "require-from-string": "1.2.1"
+          }
+        },
+        "execa": {
+          "version": "0.8.0",
+          "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
+          "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
+          "dev": true,
+          "requires": {
+            "cross-spawn": "5.1.0",
+            "get-stream": "3.0.0",
+            "is-stream": "1.1.0",
+            "npm-run-path": "2.0.2",
+            "p-finally": "1.0.0",
+            "signal-exit": "3.0.2",
+            "strip-eof": "1.0.0"
+          }
+        },
+        "minimist": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+          "dev": true
+        }
+      }
+    },
+    "listr": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",
+      "integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "figures": "1.7.0",
+        "indent-string": "2.1.0",
+        "is-promise": "2.1.0",
+        "is-stream": "1.1.0",
+        "listr-silent-renderer": "1.1.1",
+        "listr-update-renderer": "0.2.0",
+        "listr-verbose-renderer": "0.4.0",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "ora": "0.2.3",
+        "p-map": "1.1.1",
+        "rxjs": "5.4.3",
+        "stream-to-observable": "0.1.0",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "cli-spinners": {
+          "version": "0.1.2",
+          "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
+          "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
+          "dev": true
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "ora": {
+          "version": "0.2.3",
+          "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
+          "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
+          "dev": true,
+          "requires": {
+            "chalk": "1.1.3",
+            "cli-cursor": "1.0.2",
+            "cli-spinners": "0.1.2",
+            "object-assign": "4.1.1"
+          }
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
+    "listr-silent-renderer": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
+      "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=",
+      "dev": true
+    },
+    "listr-update-renderer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz",
+      "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-truncate": "0.2.1",
+        "elegant-spinner": "1.0.1",
+        "figures": "1.7.0",
+        "indent-string": "3.2.0",
+        "log-symbols": "1.0.2",
+        "log-update": "1.0.2",
+        "strip-ansi": "3.0.1"
+      },
+      "dependencies": {
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "indent-string": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+          "dev": true
+        }
+      }
+    },
+    "listr-verbose-renderer": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.0.tgz",
+      "integrity": "sha1-RNwBuww0oDxXIVTU0Izemx3FYg8=",
+      "dev": true,
+      "requires": {
+        "chalk": "1.1.3",
+        "cli-cursor": "1.0.2",
+        "date-fns": "1.28.5",
+        "figures": "1.7.0"
+      },
+      "dependencies": {
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "figures": {
+          "version": "1.7.0",
+          "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+          "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+          "dev": true,
+          "requires": {
+            "escape-string-regexp": "1.0.5",
+            "object-assign": "4.1.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
     "load-json-file": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
@@ -5601,6 +5921,12 @@
       "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
       "dev": true
     },
+    "lodash.chunk": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
+      "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=",
+      "dev": true
+    },
     "lodash.create": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
@@ -5661,6 +5987,49 @@
         "chalk": "1.1.3"
       }
     },
+    "log-update": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
+      "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "1.4.0",
+        "cli-cursor": "1.0.2"
+      },
+      "dependencies": {
+        "ansi-escapes": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+          "dev": true
+        },
+        "cli-cursor": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+          "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+          "dev": true,
+          "requires": {
+            "restore-cursor": "1.0.1"
+          }
+        },
+        "onetime": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+          "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+          "dev": true,
+          "requires": {
+            "exit-hook": "1.1.1",
+            "onetime": "1.1.0"
+          }
+        }
+      }
+    },
     "lolex": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
@@ -6344,6 +6713,15 @@
         "sort-keys": "1.1.2"
       }
     },
+    "npm-path": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.3.tgz",
+      "integrity": "sha1-Fc/04ciaONp39W9gVbJPl137K74=",
+      "dev": true,
+      "requires": {
+        "which": "1.3.0"
+      }
+    },
     "npm-run-all": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.0.2.tgz",
@@ -6368,6 +6746,17 @@
         "path-key": "2.0.1"
       }
     },
+    "npm-which": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz",
+      "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=",
+      "dev": true,
+      "requires": {
+        "commander": "2.9.0",
+        "npm-path": "2.0.3",
+        "which": "1.3.0"
+      }
+    },
     "num2fraction": {
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -6529,6 +6918,12 @@
         "p-limit": "1.1.0"
       }
     },
+    "p-map": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.1.1.tgz",
+      "integrity": "sha1-BfXkrpegaDcbwqXMhr+9vBnErno=",
+      "dev": true
+    },
     "pako": {
       "version": "0.2.9",
       "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
@@ -8812,6 +9207,15 @@
         "rx-lite": "4.0.8"
       }
     },
+    "rxjs": {
+      "version": "5.4.3",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz",
+      "integrity": "sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==",
+      "dev": true,
+      "requires": {
+        "symbol-observable": "1.0.4"
+      }
+    },
     "safe-buffer": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
@@ -9181,6 +9585,12 @@
       "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
       "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
     },
+    "staged-git-files": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz",
+      "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=",
+      "dev": true
+    },
     "statuses": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
@@ -9342,6 +9752,12 @@
         }
       }
     },
+    "stream-to-observable": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz",
+      "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=",
+      "dev": true
+    },
     "streamsearch": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
@@ -9719,6 +10135,12 @@
       "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.3.1.tgz",
       "integrity": "sha1-tvmpANSWpX8CQI8iGYwQndoGMEE="
     },
+    "symbol-observable": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
+      "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=",
+      "dev": true
+    },
     "syntax-error": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz",
diff --git a/package.json b/package.json
index 08ba53bb..5b9cd7e0 100644
--- a/package.json
+++ b/package.json
@@ -32,9 +32,11 @@
     "eslint-plugin-node": "^5.1.1",
     "eslint-plugin-security": "^1.4.0",
     "git-rev-sync": "^1.9.1",
+    "husky": "^0.14.3",
     "jquery": "^3.2.1",
     "jquery-circle-progress": "^1.2.2",
     "l20n": "^5.0.0",
+    "lint-staged": "^4.0.3",
     "mocha": "^3.4.2",
     "npm-run-all": "^4.0.2",
     "postcss-cli": "^4.1.0",
@@ -97,6 +99,7 @@
     "zh-TW"
   ],
   "scripts": {
+    "precommit": "lint-staged",
     "build": "npm-run-all build:*",
     "build:css": "postcss frontend/src/*.css -d public",
     "build:js": "webpack -p",
@@ -118,5 +121,17 @@
     "test:unit": "mocha test/unit",
     "test:server": "mocha test/server",
     "test--browser": "browserify test/frontend/frontend.bundle.js -o test/frontend/bundle.js -d && node test/frontend/driver.js"
+  },
+  "lint-staged": {
+    "*.js": [
+      "prettier --single-quote --write",
+      "eslint",
+      "git add"
+    ],
+    "*.css": [
+      "prettier --single-quote --write",
+      "stylelint",
+      "git add"
+    ]
   }
 }
diff --git a/server/server.js b/server/server.js
index 377a7cda..7ff4e115 100644
--- a/server/server.js
+++ b/server/server.js
@@ -61,7 +61,8 @@ app.engine(
       l10nDev: conf.l10n_dev,
       baseUrl: conf.base_url,
       title: 'Firefox Send',
-      description: 'Encrypt and send files with a link that automatically expires to ensure your important documents don’t stay online forever.'
+      description:
+        'Encrypt and send files with a link that automatically expires to ensure your important documents don’t stay online forever.'
     }
   })
 );