diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000000000000000000000000000000000000..57a139924ebd4fdfaef5fcf9f0e5fd0b687dfa71
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,4 @@
+{
+  "presets": ["next/babel"],
+  "plugins": ["babel-plugin-optimize-clsx"]
+}
diff --git a/.eslintrc.json b/.eslintrc.json
index 30d39f5719964b09bdaf9793bf294b10b24292cd..7fc1d1c0c233f77799b717121ed67d72c06dee44 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,6 +1,8 @@
 {
   "root": true,
   "extends": [
+    "airbnb/hooks",
+    "airbnb-typescript",
     "eslint:recommended",
     "plugin:@typescript-eslint/eslint-recommended",
     "plugin:@typescript-eslint/recommended",
@@ -9,9 +11,6 @@
     "plugin:import/typescript",
     "plugin:react/recommended",
     "plugin:react-hooks/recommended",
-    "airbnb",
-    "airbnb/hooks",
-    "airbnb-typescript",
     "plugin:prettier/recommended",
     "prettier",
     "prettier/react",
@@ -31,6 +30,7 @@
     "import/order": "off",
     "import/no-unresolved": "error",
     "jsx-a11y/href-no-hash": ["off"],
+    "jsx-a11y/anchor-is-valid": "warn",
     "@typescript-eslint/no-unused-vars": "warn",
     "react/jsx-filename-extension": [
       "off",
@@ -65,5 +65,11 @@
         "project": "./" // use <root>/path/to/folder/tsconfig.json
       }
     }
-  }
+  },
+  "overrides": [
+    {
+      "files": ["*.js"],
+      "rules": { "@typescript-eslint/no-var-requires": "off" }
+    }
+  ]
 }
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 28f136447d52bd8cb99cd8159d7f582e7c887f40..05b21b778e5da4c714ac1219d0e26e9f677f2f9c 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -15,5 +15,7 @@
   ],
 
   // Use workspace version of TypeScript instead of the one built-in
-  "typescript.tsdk": "node_modules/typescript/lib"
+  "typescript.tsdk": "node_modules/typescript/lib",
+
+  "css.validate": false
 }
diff --git a/next-env.d.ts b/next-env.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/package-lock.json b/package-lock.json
index a2606c8a8850b24e050bfaf19ffc7ed381f33cea..8a13494cfe93195b3e231a28b6a33b3d43d885f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1151,6 +1151,11 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@csstools/convert-colors": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
+      "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw=="
+    },
     "@eslint/eslintrc": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@@ -1993,6 +1998,19 @@
         "object.assign": "^4.1.0"
       }
     },
+    "babel-plugin-optimize-clsx": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-optimize-clsx/-/babel-plugin-optimize-clsx-2.6.1.tgz",
+      "integrity": "sha512-uPatuZ4FhqsQ23IhoZNOVoVLCFYBvIwVgWJ4WdUbwaZvsooitwbbwwtQxQHljUiCpMEZGkVln/OLMIdwrlCs1g==",
+      "requires": {
+        "@babel/generator": "^7.6.2",
+        "@babel/template": "^7.6.0",
+        "@babel/types": "^7.6.1",
+        "find-cache-dir": "^3.2.0",
+        "lodash": "^4.17.15",
+        "object-hash": "^2.0.3"
+      }
+    },
     "babel-plugin-syntax-jsx": {
       "version": "6.18.0",
       "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
@@ -2544,6 +2562,11 @@
         "shallow-clone": "^3.0.0"
       }
     },
+    "clsx": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
+      "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
+    },
     "collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -2825,6 +2848,45 @@
         "urix": "^0.1.0"
       }
     },
+    "css-blank-pseudo": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
+      "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==",
+      "requires": {
+        "postcss": "^7.0.5"
+      }
+    },
+    "css-has-pseudo": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz",
+      "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==",
+      "requires": {
+        "postcss": "^7.0.6",
+        "postcss-selector-parser": "^5.0.0-rc.4"
+      },
+      "dependencies": {
+        "cssesc": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+          "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+        },
+        "postcss-selector-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+          "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+          "requires": {
+            "cssesc": "^2.0.0",
+            "indexes-of": "^1.0.1",
+            "uniq": "^1.0.1"
+          }
+        }
+      }
+    },
+    "css-homogenizer": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/css-homogenizer/-/css-homogenizer-1.1.0.tgz",
+      "integrity": "sha512-pN/b4qXys7OPFWzV+arC9lheKUUZWdVLmD08619Uc9UvtwgKROo9YyOuLeLunI9zNylIYQ8qa6FAIw0A/v3NeA=="
+    },
     "css-loader": {
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
@@ -2870,6 +2932,14 @@
         }
       }
     },
+    "css-prefers-color-scheme": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz",
+      "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==",
+      "requires": {
+        "postcss": "^7.0.5"
+      }
+    },
     "css-unit-converter": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
@@ -2880,6 +2950,11 @@
       "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
       "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s="
     },
+    "cssdb": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
+      "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ=="
+    },
     "cssesc": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -4235,6 +4310,11 @@
       "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
       "dev": true
     },
+    "flatten": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
+      "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
+    },
     "flush-write-stream": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@@ -5288,11 +5368,33 @@
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
       "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
     },
+    "lodash._reinterpolate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+      "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
+    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
       "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
     },
+    "lodash.template": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
+      "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0",
+        "lodash.templatesettings": "^4.0.0"
+      }
+    },
+    "lodash.templatesettings": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
+      "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0"
+      }
+    },
     "lodash.toarray": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
@@ -5636,6 +5738,11 @@
         "minimist": "^1.2.5"
       }
     },
+    "modern-normalize": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.0.0.tgz",
+      "integrity": "sha512-1lM+BMLGuDfsdwf3rsgBSrxJwAZHFIrQ8YR61xIqdHo0uNKI9M52wNpHSrliZATJp51On6JD0AfRxd4YGSU0lw=="
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -6257,6 +6364,173 @@
         "supports-color": "^6.1.0"
       }
     },
+    "postcss-attribute-case-insensitive": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz",
+      "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-selector-parser": "^6.0.2"
+      }
+    },
+    "postcss-color-functional-notation": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz",
+      "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-color-gray": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz",
+      "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==",
+      "requires": {
+        "@csstools/convert-colors": "^1.4.0",
+        "postcss": "^7.0.5",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-color-hex-alpha": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz",
+      "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==",
+      "requires": {
+        "postcss": "^7.0.14",
+        "postcss-values-parser": "^2.0.1"
+      }
+    },
+    "postcss-color-mod-function": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz",
+      "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==",
+      "requires": {
+        "@csstools/convert-colors": "^1.4.0",
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-color-rebeccapurple": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz",
+      "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-custom-media": {
+      "version": "7.0.8",
+      "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz",
+      "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==",
+      "requires": {
+        "postcss": "^7.0.14"
+      }
+    },
+    "postcss-custom-properties": {
+      "version": "8.0.11",
+      "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz",
+      "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==",
+      "requires": {
+        "postcss": "^7.0.17",
+        "postcss-values-parser": "^2.0.1"
+      }
+    },
+    "postcss-custom-selectors": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz",
+      "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-selector-parser": "^5.0.0-rc.3"
+      },
+      "dependencies": {
+        "cssesc": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+          "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+        },
+        "postcss-selector-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+          "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+          "requires": {
+            "cssesc": "^2.0.0",
+            "indexes-of": "^1.0.1",
+            "uniq": "^1.0.1"
+          }
+        }
+      }
+    },
+    "postcss-dir-pseudo-class": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz",
+      "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-selector-parser": "^5.0.0-rc.3"
+      },
+      "dependencies": {
+        "cssesc": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+          "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+        },
+        "postcss-selector-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+          "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+          "requires": {
+            "cssesc": "^2.0.0",
+            "indexes-of": "^1.0.1",
+            "uniq": "^1.0.1"
+          }
+        }
+      }
+    },
+    "postcss-double-position-gradients": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz",
+      "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==",
+      "requires": {
+        "postcss": "^7.0.5",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-env-function": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz",
+      "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-focus-visible": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz",
+      "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-focus-within": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz",
+      "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-font-variant": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz",
+      "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
     "postcss-functions": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/postcss-functions/-/postcss-functions-3.0.0.tgz",
@@ -6293,6 +6567,23 @@
         }
       }
     },
+    "postcss-gap-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz",
+      "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-image-set-function": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz",
+      "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
     "postcss-import": {
       "version": "12.0.1",
       "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
@@ -6311,6 +6602,15 @@
         }
       }
     },
+    "postcss-initial": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz",
+      "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==",
+      "requires": {
+        "lodash.template": "^4.5.0",
+        "postcss": "^7.0.2"
+      }
+    },
     "postcss-js": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.3.tgz",
@@ -6320,6 +6620,32 @@
         "postcss": "^7.0.18"
       }
     },
+    "postcss-lab-function": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz",
+      "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==",
+      "requires": {
+        "@csstools/convert-colors": "^1.4.0",
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-logical": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz",
+      "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-media-minmax": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz",
+      "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
     "postcss-modules-extract-imports": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
@@ -6366,6 +6692,117 @@
         "postcss-selector-parser": "^6.0.2"
       }
     },
+    "postcss-nesting": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz",
+      "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-overflow-shorthand": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz",
+      "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-page-break": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz",
+      "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-place": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz",
+      "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-values-parser": "^2.0.0"
+      }
+    },
+    "postcss-preset-env": {
+      "version": "6.7.0",
+      "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz",
+      "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==",
+      "requires": {
+        "autoprefixer": "^9.6.1",
+        "browserslist": "^4.6.4",
+        "caniuse-lite": "^1.0.30000981",
+        "css-blank-pseudo": "^0.1.4",
+        "css-has-pseudo": "^0.10.0",
+        "css-prefers-color-scheme": "^3.1.1",
+        "cssdb": "^4.4.0",
+        "postcss": "^7.0.17",
+        "postcss-attribute-case-insensitive": "^4.0.1",
+        "postcss-color-functional-notation": "^2.0.1",
+        "postcss-color-gray": "^5.0.0",
+        "postcss-color-hex-alpha": "^5.0.3",
+        "postcss-color-mod-function": "^3.0.3",
+        "postcss-color-rebeccapurple": "^4.0.1",
+        "postcss-custom-media": "^7.0.8",
+        "postcss-custom-properties": "^8.0.11",
+        "postcss-custom-selectors": "^5.1.2",
+        "postcss-dir-pseudo-class": "^5.0.0",
+        "postcss-double-position-gradients": "^1.0.0",
+        "postcss-env-function": "^2.0.2",
+        "postcss-focus-visible": "^4.0.0",
+        "postcss-focus-within": "^3.0.0",
+        "postcss-font-variant": "^4.0.0",
+        "postcss-gap-properties": "^2.0.0",
+        "postcss-image-set-function": "^3.0.1",
+        "postcss-initial": "^3.0.0",
+        "postcss-lab-function": "^2.0.1",
+        "postcss-logical": "^3.0.0",
+        "postcss-media-minmax": "^4.0.0",
+        "postcss-nesting": "^7.0.0",
+        "postcss-overflow-shorthand": "^2.0.0",
+        "postcss-page-break": "^2.0.0",
+        "postcss-place": "^4.0.1",
+        "postcss-pseudo-class-any-link": "^6.0.0",
+        "postcss-replace-overflow-wrap": "^3.0.0",
+        "postcss-selector-matches": "^4.0.0",
+        "postcss-selector-not": "^4.0.0"
+      }
+    },
+    "postcss-pseudo-class-any-link": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz",
+      "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==",
+      "requires": {
+        "postcss": "^7.0.2",
+        "postcss-selector-parser": "^5.0.0-rc.3"
+      },
+      "dependencies": {
+        "cssesc": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+          "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+        },
+        "postcss-selector-parser": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+          "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+          "requires": {
+            "cssesc": "^2.0.0",
+            "indexes-of": "^1.0.1",
+            "uniq": "^1.0.1"
+          }
+        }
+      }
+    },
+    "postcss-replace-overflow-wrap": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz",
+      "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==",
+      "requires": {
+        "postcss": "^7.0.2"
+      }
+    },
     "postcss-safe-parser": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz",
@@ -6374,6 +6811,24 @@
         "postcss": "^7.0.26"
       }
     },
+    "postcss-selector-matches": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz",
+      "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "postcss": "^7.0.2"
+      }
+    },
+    "postcss-selector-not": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz",
+      "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "postcss": "^7.0.2"
+      }
+    },
     "postcss-selector-parser": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
@@ -6389,6 +6844,16 @@
       "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
       "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
     },
+    "postcss-values-parser": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+      "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+      "requires": {
+        "flatten": "^1.0.2",
+        "indexes-of": "^1.0.1",
+        "uniq": "^1.0.1"
+      }
+    },
     "prelude-ls": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -6410,6 +6875,15 @@
         "fast-diff": "^1.1.2"
       }
     },
+    "prettier-plugin-tailwind-css": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/prettier-plugin-tailwind-css/-/prettier-plugin-tailwind-css-1.4.0.tgz",
+      "integrity": "sha512-VnS+V7gAJ7LeO3nVEiFLk8359EsYF7jIZMU43PNiw4IQjKUHFd7tazfCG3hKF5/bw5D5c28b8SzuIN2Rczy7uA==",
+      "dev": true,
+      "requires": {
+        "prettier": "^2.0.5"
+      }
+    },
     "pretty-hrtime": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
diff --git a/package.json b/package.json
index 2f17eac4e9451ca00513aee41ade7d8699358f78..004c0d359a8f88a7eab42701cf26d39270e589ac 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,11 @@
   "name": "schdesign-web",
   "version": "1.0.0",
   "description": "Website of schdesign",
+  "scripts": {
+    "dev": "next dev",
+    "build": "next build",
+    "start": "next start"
+  },
   "repository": {
     "type": "git",
     "url": "git+https://github.com/simonyiszk/schdesign-web.git"
@@ -13,9 +18,13 @@
   "homepage": "https://schdesign.hu",
   "dependencies": {
     "@types/react": "^16.9.49",
-    "autoprefixer": "^9.8.6",
+    "babel-plugin-optimize-clsx": "^2.6.1",
+    "clsx": "^1.1.1",
+    "css-homogenizer": "^1.1.0",
+    "modern-normalize": "^1.0.0",
     "next": "^9.5.3",
     "postcss-import": "^12.0.1",
+    "postcss-preset-env": "^6.7.0",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
     "tailwindcss": "^1.8.6",
@@ -26,7 +35,6 @@
     "@typescript-eslint/eslint-plugin": "^4.1.0",
     "@typescript-eslint/parser": "^4.1.0",
     "eslint": "^7.8.1",
-    "eslint-config-airbnb": "^18.2.0",
     "eslint-config-airbnb-typescript": "^10.0.0",
     "eslint-config-prettier": "^6.11.0",
     "eslint-import-resolver-typescript": "^2.3.0",
@@ -38,6 +46,7 @@
     "eslint-plugin-simple-import-sort": "^5.0.3",
     "husky": "^4.3.0",
     "lint-staged": "^10.3.0",
-    "prettier": "^2.1.1"
+    "prettier": "^2.1.1",
+    "prettier-plugin-tailwind-css": "^1.4.0"
   }
 }
diff --git a/postcss.config.js b/postcss.config.js
index b44a9652c7bf9a31b2aca940254f001329327382..753a9c2c049ffee1d25420dd59b67412870ade4a 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,3 +1,7 @@
 module.exports = {
-  plugins: ['postcss-import', 'tailwindcss', 'autoprefixer'],
+  plugins: {
+    'postcss-import': {},
+    tailwindcss: {},
+    'postcss-preset-env': {},
+  },
 };
diff --git a/src/components/placeholder/PlaceholderNav.tsx b/src/components/placeholder/PlaceholderNav.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..8d13f7be0d6dd8814c607b911de0d02e299038b6
--- /dev/null
+++ b/src/components/placeholder/PlaceholderNav.tsx
@@ -0,0 +1,30 @@
+import Link from 'next/link';
+import React from 'react';
+
+const links = [
+  { href: 'https://github.com/vercel/next.js', label: 'GitHub' },
+  { href: 'https://nextjs.org/docs', label: 'Docs' },
+];
+
+export default function Nav(): JSX.Element {
+  return (
+    <nav>
+      <ul className="flex items-center justify-between p-8">
+        <li>
+          <Link href="/" passHref>
+            <a className="text-blue-500 no-underline">Home</a>
+          </Link>
+        </li>
+        <ul className="flex items-center justify-between space-x-4">
+          {links.map(({ href, label }) => (
+            <li key={`${href}${label}`}>
+              <a href={href} className="btn-blue no-underline">
+                {label}
+              </a>
+            </li>
+          ))}
+        </ul>
+      </ul>
+    </nav>
+  );
+}
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..04a3305f19b95d4666d7b7e056ea257b450465bb
--- /dev/null
+++ b/src/pages/_app.tsx
@@ -0,0 +1,10 @@
+import 'style/globalStyles.css';
+
+import type { AppProps } from 'next/app';
+import React from 'react';
+
+function MyApp({ Component, pageProps }: AppProps): JSX.Element {
+  return <Component {...pageProps} />;
+}
+
+export default MyApp;
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f92a78d8d0a258835df248933647549dff02d725
--- /dev/null
+++ b/src/pages/index.tsx
@@ -0,0 +1,13 @@
+import Nav from 'components/placeholder/PlaceholderNav';
+import React from 'react';
+
+export default function IndexPage(): JSX.Element {
+  return (
+    <div>
+      <Nav />
+      <div className="py-20">
+        <h1 className="text-5xl text-center">Next.js + Tailwind CSS</h1>
+      </div>
+    </div>
+  );
+}
diff --git a/src/style/globalStyles.css b/src/style/globalStyles.css
new file mode 100644
index 0000000000000000000000000000000000000000..725f65e339a4908899180870e16b81d23bfdeb16
--- /dev/null
+++ b/src/style/globalStyles.css
@@ -0,0 +1,10 @@
+@import 'modern-normalize/modern-normalize.css';
+@import 'css-homogenizer/reset.css';
+@import 'css-homogenizer/opinionated-base.css';
+@import 'tailwindcss/base.css';
+@import 'tailwindcss/components.css';
+@import 'tailwindcss/utilities.css';
+
+.btn-blue {
+  @apply bg-blue-500 text-white font-bold py-2 px-4 rounded;
+}
diff --git a/stylelintrc.json b/stylelintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..08ae32d0bbc0a965e39a4ea11f3786b0ae8e9b11
--- /dev/null
+++ b/stylelintrc.json
@@ -0,0 +1,18 @@
+{
+  "rules": {
+    "at-rule-no-unknown": [
+      true,
+      {
+        "ignoreAtRules": [
+          "tailwind",
+          "apply",
+          "variants",
+          "responsive",
+          "screen"
+        ]
+      }
+    ],
+    "declaration-block-trailing-semicolon": null,
+    "no-descending-specificity": null
+  }
+}
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..85343219c33ecf189951a61d24744b5c7c30e7e8
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,51 @@
+const plugin = require('tailwindcss/plugin');
+
+function half(value) {
+  return value.replace(/\d+(.\d+)?/, (number) => number / 2);
+}
+
+module.exports = {
+  future: {
+    removeDeprecatedGapUtilities: true,
+    purgeLayersByDefault: true,
+  },
+  purge: ['./src/**/*.{js,ts,tsx}'],
+  corePlugins: {
+    animation: false,
+    preflight: false,
+  },
+  plugins: [
+    plugin(({ addUtilities, e, theme, variants }) => {
+      /* TODO: Remove 'flex-gap' polyfills once supported natively with 'gap' */
+      Object.entries(theme('gap')).forEach(([key, value]) => {
+        addUtilities(
+          {
+            [`.flex-gap-${e(key)}`]: {
+              margin: `-${half(value)}`,
+              '& > *': {
+                margin: half(value),
+              },
+            },
+            [`.flex-gap-x-${e(key)}`]: {
+              marginRight: `-${half(value)}`,
+              marginLeft: `-${half(value)}`,
+              '& > *': {
+                marginRight: half(value),
+                marginLeft: half(value),
+              },
+            },
+            [`.flex-gap-y-${e(key)}`]: {
+              marginTop: `-${half(value)}`,
+              marginBottom: `-${half(value)}`,
+              '& > *': {
+                marginTop: half(value),
+                marginBottom: half(value),
+              },
+            },
+          },
+          variants('gap'),
+        );
+      });
+    }),
+  ],
+};
diff --git a/tsconfig.json b/tsconfig.json
index 8f1046acbfb98d6d4c404a1518d9c7abd70cf1a1..ee9abfa06128fc5adbb0fac52b1584554a0256f1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,15 +1,21 @@
 {
-  // Reference: https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/
   "compilerOptions": {
+    "target": "es5",
+    "lib": ["dom", "dom.iterable", "esnext"],
+    "allowJs": true,
+    "skipLibCheck": true,
     "strict": true,
+    "forceConsistentCasingInFileNames": true,
     "noEmit": true,
-    "target": "ESNext",
+    "esModuleInterop": true,
+    "module": "esnext",
     "moduleResolution": "node",
-    "jsx": "react",
-    "allowJs": true,
-    "allowSyntheticDefaultImports": true,
-    "isolatedModules": true
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "jsx": "preserve",
+    "baseUrl": "./src/",
+    "importsNotUsedAsValues": "error"
   },
-  "include": ["src/**/*", "./postcss.config.js"],
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "*.config.js"],
   "exclude": ["node_modules"]
 }