diff --git a/assets/Steam/achievements/pack-for-web.sh b/assets/Steam/achievements/pack-for-web.sh
new file mode 100644
index 000000000..f00431ff2
--- /dev/null
+++ b/assets/Steam/achievements/pack-for-web.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+BASEDIR=$(dirname "$0")
+ROOTDIR=$BASEDIR/../../..
+echo $ROOTDIR
+rm -rf $ROOTDIR/dist/icons/achievements
+mkdir -p $ROOTDIR/dist/icons
+cp -r $BASEDIR/real $ROOTDIR/dist/icons/achievements
+for i in $ROOTDIR/dist/icons/achievements/*.svg; do
+  echo $i
+  # Make background transparent and replace green with black
+  # The icons will be recolored by css filters matching the player's theme
+  sed -i "s/fill:#000000;/fill-opacity: 0%;/g" "$i"
+  sed -i "s/fill:#00ff00;/fill:#000000;/g" "$i"
+done
diff --git a/dist/icons/achievements/$1Q.svg b/dist/icons/achievements/$1Q.svg
new file mode 100644
index 000000000..4b51b63bd
--- /dev/null
+++ b/dist/icons/achievements/$1Q.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="$1Q.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:23.0096px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.308159"
+       x="8.2434549"
+       y="38.355984"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.308159"
+         x="8.2434549"
+         y="38.355984">$1Q</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/-1b.svg b/dist/icons/achievements/-1b.svg
new file mode 100644
index 000000000..d582e1fb2
--- /dev/null
+++ b/dist/icons/achievements/-1b.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="-1b.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:23.4183px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.313633"
+       x="3.2184403"
+       y="41.740555"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.313633"
+         x="3.2184403"
+         y="41.740555">-$1b</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/1H.svg b/dist/icons/achievements/1H.svg
new file mode 100644
index 000000000..8bc9b30df
--- /dev/null
+++ b/dist/icons/achievements/1H.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="1H.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="34.034172"
+       y="37.49543"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="34.034172"
+         y="37.49543"
+         id="tspan17808">1H</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/2DAYS.svg b/dist/icons/achievements/2DAYS.svg
new file mode 100644
index 000000000..34aecf3d0
--- /dev/null
+++ b/dist/icons/achievements/2DAYS.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="2DAYS.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="34.034172"
+       y="37.49543"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="34.034172"
+         y="37.49543"
+         id="tspan17808">2 DAYS</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/4S.svg b/dist/icons/achievements/4S.svg
new file mode 100644
index 000000000..efcca024f
--- /dev/null
+++ b/dist/icons/achievements/4S.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="4S.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="37.743938"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="37.743938"
+         id="tspan16668">4S</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BLADE.svg b/dist/icons/achievements/BLADE.svg
new file mode 100644
index 000000000..1e1a47a43
--- /dev/null
+++ b/dist/icons/achievements/BLADE.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BLADE.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan16415">BLADE</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BLADE100K.svg b/dist/icons/achievements/BLADE100K.svg
new file mode 100644
index 000000000..ed8ca6170
--- /dev/null
+++ b/dist/icons/achievements/BLADE100K.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BLADE100K.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan16415">BLADE</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.40966"
+         y="49.888741"
+         id="tspan16668">100000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BLADEOVERCLOCK.svg b/dist/icons/achievements/BLADEOVERCLOCK.svg
new file mode 100644
index 000000000..a35fc796a
--- /dev/null
+++ b/dist/icons/achievements/BLADEOVERCLOCK.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BLADEOVERCLOCK.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan16415">BLADE</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan16668">OC</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN1+.svg b/dist/icons/achievements/BN1+.svg
new file mode 100644
index 000000000..66eae0b45
--- /dev/null
+++ b/dist/icons/achievements/BN1+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN1+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN1+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN10+.svg b/dist/icons/achievements/BN10+.svg
new file mode 100644
index 000000000..c4d6847cd
--- /dev/null
+++ b/dist/icons/achievements/BN10+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN10+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN10+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN12+.svg b/dist/icons/achievements/BN12+.svg
new file mode 100644
index 000000000..8ec06bf4a
--- /dev/null
+++ b/dist/icons/achievements/BN12+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN12+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN12+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN13+.svg b/dist/icons/achievements/BN13+.svg
new file mode 100644
index 000000000..c5b043cc3
--- /dev/null
+++ b/dist/icons/achievements/BN13+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN13+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="29"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN13+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN2+.svg b/dist/icons/achievements/BN2+.svg
new file mode 100644
index 000000000..80e8fdffc
--- /dev/null
+++ b/dist/icons/achievements/BN2+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN2+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN2+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN3+.svg b/dist/icons/achievements/BN3+.svg
new file mode 100644
index 000000000..3a6598836
--- /dev/null
+++ b/dist/icons/achievements/BN3+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN3+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN3+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN6+.svg b/dist/icons/achievements/BN6+.svg
new file mode 100644
index 000000000..c8ea68153
--- /dev/null
+++ b/dist/icons/achievements/BN6+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN6+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN6+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN7+.svg b/dist/icons/achievements/BN7+.svg
new file mode 100644
index 000000000..93ee9d9c1
--- /dev/null
+++ b/dist/icons/achievements/BN7+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN7+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN7+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN8+.svg b/dist/icons/achievements/BN8+.svg
new file mode 100644
index 000000000..fd1926b8b
--- /dev/null
+++ b/dist/icons/achievements/BN8+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN8+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN8+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/BN9+.svg b/dist/icons/achievements/BN9+.svg
new file mode 100644
index 000000000..ed1273ada
--- /dev/null
+++ b/dist/icons/achievements/BN9+.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="BN9+.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.0737px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+       x="34.276661"
+       y="40.084541"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.215272"
+         x="34.276661"
+         y="40.084541"
+         id="tspan20241">BN9+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CORP.svg b/dist/icons/achievements/CORP.svg
new file mode 100644
index 000000000..d085570b8
--- /dev/null
+++ b/dist/icons/achievements/CORP.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CORP.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan14497">CORP</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CORP1000.svg b/dist/icons/achievements/CORP1000.svg
new file mode 100644
index 000000000..0c6a287da
--- /dev/null
+++ b/dist/icons/achievements/CORP1000.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CORP1000.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan14497">CORP</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan15347">1000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CORPCITY.svg b/dist/icons/achievements/CORPCITY.svg
new file mode 100644
index 000000000..a51577a6f
--- /dev/null
+++ b/dist/icons/achievements/CORPCITY.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CORPCITY.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan14497">CORP</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan15347">3000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CORPLOBBY.svg b/dist/icons/achievements/CORPLOBBY.svg
new file mode 100644
index 000000000..b08e951cf
--- /dev/null
+++ b/dist/icons/achievements/CORPLOBBY.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CORPLOBBY.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan14497">CORP</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan15347">LOBBY</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CORPRE.svg b/dist/icons/achievements/CORPRE.svg
new file mode 100644
index 000000000..945ad9295
--- /dev/null
+++ b/dist/icons/achievements/CORPRE.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CORPRE.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan14497">CORP</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan15347">RE</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/CSEC.svg b/dist/icons/achievements/CSEC.svg
new file mode 100644
index 000000000..493d2e937
--- /dev/null
+++ b/dist/icons/achievements/CSEC.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="CSEC.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:18.9715px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.254082;stroke-opacity:1"
+       x="4.3416786"
+       y="43.981724"
+       id="text2505"
+       transform="scale(1.0801483,0.9257988)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.254082;stroke-opacity:1"
+         x="4.3416786"
+         y="43.981724">CSEC</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/GANG.svg b/dist/icons/achievements/GANG.svg
new file mode 100644
index 000000000..94c1188fb
--- /dev/null
+++ b/dist/icons/achievements/GANG.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="GANG.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan11415">GANG</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/GANG100%.svg b/dist/icons/achievements/GANG100%.svg
new file mode 100644
index 000000000..ecbef464c
--- /dev/null
+++ b/dist/icons/achievements/GANG100%.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="GANG100%.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan11415">GANG</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="57.620747"
+         id="tspan14185">100%</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/GANG10000.svg b/dist/icons/achievements/GANG10000.svg
new file mode 100644
index 000000000..2a149da66
--- /dev/null
+++ b/dist/icons/achievements/GANG10000.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="GANG10000.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan14185">GANG</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="57.620747"
+         id="tspan14497">10000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/GANGMAX.svg b/dist/icons/achievements/GANGMAX.svg
new file mode 100644
index 000000000..f755f92fd
--- /dev/null
+++ b/dist/icons/achievements/GANGMAX.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="GANGMAX.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan11415">GANG</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="57.620747"
+         id="tspan14185">MAX</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/HASHNET.svg b/dist/icons/achievements/HASHNET.svg
new file mode 100644
index 000000000..70abf6eed
--- /dev/null
+++ b/dist/icons/achievements/HASHNET.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="HASHNET.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="33.920467"
+       y="29.422306"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="29.422306"
+         id="tspan16668">HASHNET</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/HASHNETALL.svg b/dist/icons/achievements/HASHNETALL.svg
new file mode 100644
index 000000000..cd2f6be76
--- /dev/null
+++ b/dist/icons/achievements/HASHNETALL.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="HASHNETALL.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="33.920467"
+       y="29.422306"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="29.422306"
+         id="tspan16668">HASHNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="43.710182"
+         id="tspan17808">ALL</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/HASHNETCAP.svg b/dist/icons/achievements/HASHNETCAP.svg
new file mode 100644
index 000000000..648778096
--- /dev/null
+++ b/dist/icons/achievements/HASHNETCAP.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="HASHNETCAP.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="33.920467"
+       y="29.422306"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="29.422306"
+         id="tspan16668">HASHNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="43.710182"
+         id="tspan17808">100%</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/HASHNETMAX.svg b/dist/icons/achievements/HASHNETMAX.svg
new file mode 100644
index 000000000..e7b40e803
--- /dev/null
+++ b/dist/icons/achievements/HASHNETMAX.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="HASHNETMAX.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="33.920467"
+       y="29.422306"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="29.422306"
+         id="tspan16668">HASHNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="43.710182"
+         id="tspan17808">MAX</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/HASHNETMONEY.svg b/dist/icons/achievements/HASHNETMONEY.svg
new file mode 100644
index 000000000..2ed64dfc2
--- /dev/null
+++ b/dist/icons/achievements/HASHNETMONEY.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="HASHNETMONEY.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="33.920467"
+       y="29.422306"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="29.422306"
+         id="tspan16668">HASHNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="33.920467"
+         y="43.710182"
+         id="tspan17808">$1B</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/INT255.svg b/dist/icons/achievements/INT255.svg
new file mode 100644
index 000000000..e578553cf
--- /dev/null
+++ b/dist/icons/achievements/INT255.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="INT255.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.409664"
+       y="31.148991"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="31.148991"
+         id="tspan15347">INT</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.409664"
+         y="49.888741"
+         id="tspan16415">255</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/NiteSec.svg b/dist/icons/achievements/NiteSec.svg
new file mode 100644
index 000000000..60168f42f
--- /dev/null
+++ b/dist/icons/achievements/NiteSec.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="NiteSec.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:13.3201px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+       x="4.4427061"
+       y="39.151321"
+       id="text2505"
+       transform="scale(1.0332295,0.96783917)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+         x="4.4427061"
+         y="39.151321">NiteSec</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/OUCH.svg b/dist/icons/achievements/OUCH.svg
new file mode 100644
index 000000000..3ae7e7223
--- /dev/null
+++ b/dist/icons/achievements/OUCH.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="OUCH.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan11415">OUCH!</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF-1.svg b/dist/icons/achievements/SF-1.svg
new file mode 100644
index 000000000..01bc07937
--- /dev/null
+++ b/dist/icons/achievements/SF-1.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF-1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:18.9715px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.254082;stroke-opacity:1"
+       x="4.3416786"
+       y="43.981724"
+       id="text2505"
+       transform="scale(1.0801483,0.9257988)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.254082;stroke-opacity:1"
+         x="4.3416786"
+         y="43.981724">SF -1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF1.1.svg b/dist/icons/achievements/SF1.1.svg
new file mode 100644
index 000000000..5ae7bf73c
--- /dev/null
+++ b/dist/icons/achievements/SF1.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF1.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.69091"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="335"
+     inkscape:window-y="29"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF1.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF10.1.svg b/dist/icons/achievements/SF10.1.svg
new file mode 100644
index 000000000..b387d1c22
--- /dev/null
+++ b/dist/icons/achievements/SF10.1.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF10.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.2573px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+       x="2.3807058"
+       y="43.837727"
+       id="text2505"
+       transform="scale(1.0801483,0.9257988)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+         x="2.3807058"
+         y="43.837727">SF10.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF11.1.svg b/dist/icons/achievements/SF11.1.svg
new file mode 100644
index 000000000..fbf5a5653
--- /dev/null
+++ b/dist/icons/achievements/SF11.1.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF11.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.2573px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+       x="2.3807058"
+       y="43.837727"
+       id="text2505"
+       transform="scale(1.0801483,0.9257988)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+         x="2.3807058"
+         y="43.837727">SF11.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF12.1.svg b/dist/icons/achievements/SF12.1.svg
new file mode 100644
index 000000000..c8a72d4b5
--- /dev/null
+++ b/dist/icons/achievements/SF12.1.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF12.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.2573px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+       x="2.3807058"
+       y="43.837727"
+       id="text2505"
+       transform="scale(1.0801483,0.9257988)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.204338;stroke-opacity:1"
+         x="2.3807058"
+         y="43.837727">SF12.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF2.1.svg b/dist/icons/achievements/SF2.1.svg
new file mode 100644
index 000000000..c7edf44cd
--- /dev/null
+++ b/dist/icons/achievements/SF2.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF2.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF2.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF3.1.svg b/dist/icons/achievements/SF3.1.svg
new file mode 100644
index 000000000..58c635a52
--- /dev/null
+++ b/dist/icons/achievements/SF3.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF3.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF3.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF4.1.svg b/dist/icons/achievements/SF4.1.svg
new file mode 100644
index 000000000..58fc523a3
--- /dev/null
+++ b/dist/icons/achievements/SF4.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF4.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF4.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF5.1.svg b/dist/icons/achievements/SF5.1.svg
new file mode 100644
index 000000000..6033895de
--- /dev/null
+++ b/dist/icons/achievements/SF5.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF5.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF5.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF6.1.svg b/dist/icons/achievements/SF6.1.svg
new file mode 100644
index 000000000..ecbfdfcd0
--- /dev/null
+++ b/dist/icons/achievements/SF6.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF6.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF6.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF7.1.svg b/dist/icons/achievements/SF7.1.svg
new file mode 100644
index 000000000..44c8b6430
--- /dev/null
+++ b/dist/icons/achievements/SF7.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF7.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="270"
+     inkscape:window-y="58"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF7.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF8.1.svg b/dist/icons/achievements/SF8.1.svg
new file mode 100644
index 000000000..4c44d9354
--- /dev/null
+++ b/dist/icons/achievements/SF8.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF8.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF8.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SF9.1.svg b/dist/icons/achievements/SF9.1.svg
new file mode 100644
index 000000000..21f1c4344
--- /dev/null
+++ b/dist/icons/achievements/SF9.1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SF9.1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:19.7556px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+       x="3.4424145"
+       y="42.027332"
+       id="text2505"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;stroke-opacity:1"
+         x="3.4424145"
+         y="42.027332">SF9.1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/SLEEVE8.svg b/dist/icons/achievements/SLEEVE8.svg
new file mode 100644
index 000000000..0db368e18
--- /dev/null
+++ b/dist/icons/achievements/SLEEVE8.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="SLEEVE8.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.4303px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+       x="34.034172"
+       y="37.49543"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.153084"
+         x="34.034172"
+         y="37.49543"
+         id="tspan17808">8 SLEEVE</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/TBH.svg b/dist/icons/achievements/TBH.svg
new file mode 100644
index 000000000..2153ac84e
--- /dev/null
+++ b/dist/icons/achievements/TBH.svg
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="TBH.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="3.2907448"
+     inkscape:cx="116.99479"
+     inkscape:cy="121.09721"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:13.3201px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+       x="32.751316"
+       y="22.204227"
+       id="text2505"
+       transform="scale(1.0332295,0.96783918)"><tspan
+         sodipodi:role="line"
+         id="tspan2503"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+         x="32.751316"
+         y="22.204227">The</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+         x="32.751316"
+         y="38.854351"
+         id="tspan5436">black</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.178394;stroke-opacity:1"
+         x="32.751316"
+         y="55.504475"
+         id="tspan5438">hand</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/TOR.svg b/dist/icons/achievements/TOR.svg
new file mode 100644
index 000000000..430090bb5
--- /dev/null
+++ b/dist/icons/achievements/TOR.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="TOR.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.9918px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+       x="34.523369"
+       y="38.880997"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.200782"
+         x="34.523369"
+         y="38.880997"
+         id="tspan11415">TOR</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/TRAVEL.svg b/dist/icons/achievements/TRAVEL.svg
new file mode 100644
index 000000000..ef059574b
--- /dev/null
+++ b/dist/icons/achievements/TRAVEL.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="TRAVEL.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="33.916092"
+       y="33.325958"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.916092"
+         y="33.325958"
+         id="tspan11415">WORLD</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/WORKOUT.svg b/dist/icons/achievements/WORKOUT.svg
new file mode 100644
index 000000000..62befc520
--- /dev/null
+++ b/dist/icons/achievements/WORKOUT.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="WORKOUT.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="33.916092"
+       y="33.325958"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.916092"
+         y="33.325958"
+         id="tspan11415">WORKOUT</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/bigcost.svg b/dist/icons/achievements/bigcost.svg
new file mode 100644
index 000000000..e6596813e
--- /dev/null
+++ b/dist/icons/achievements/bigcost.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="bigcost.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:13.3483px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.17877"
+       x="34.172409"
+       y="39.818333"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.17877"
+         x="34.172409"
+         y="39.818333"
+         id="tspan5330">32GB+</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/bitrunners.svg b/dist/icons/achievements/bitrunners.svg
new file mode 100644
index 000000000..a03ba8ece
--- /dev/null
+++ b/dist/icons/achievements/bitrunners.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="bitrunners.svg.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.86318px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.132095"
+       x="2.8813558"
+       y="37.776012"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.132095"
+         x="2.8813558"
+         y="37.776012">BitRunners</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/broker.svg b/dist/icons/achievements/broker.svg
new file mode 100644
index 000000000..a1a2e2d01
--- /dev/null
+++ b/dist/icons/achievements/broker.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="broker.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:20.708px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.277337"
+       x="34.164398"
+       y="40.048054"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.277337"
+         x="34.164398"
+         y="40.048054"
+         id="tspan5330">$1q</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/combat3000.svg b/dist/icons/achievements/combat3000.svg
new file mode 100644
index 000000000..683a90947
--- /dev/null
+++ b/dist/icons/achievements/combat3000.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="combat3000.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.662px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+       x="33.197567"
+       y="30.194496"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.197567"
+         y="30.194496"
+         id="tspan2495">combat</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.197567"
+         y="48.521996"
+         id="tspan3127">3000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/daedalus.svg b/dist/icons/achievements/daedalus.svg
new file mode 100644
index 000000000..dcf7a640d
--- /dev/null
+++ b/dist/icons/achievements/daedalus.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="daedalus.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="101"
+     inkscape:window-y="106"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.9663px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.160262"
+       x="2.6862416"
+       y="39.373894"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.160262"
+         x="2.6862416"
+         y="39.373894">Daedalus</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/discount.svg b/dist/icons/achievements/discount.svg
new file mode 100644
index 000000000..f7ef0c238
--- /dev/null
+++ b/dist/icons/achievements/discount.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="discount.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:16.3511px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.218986"
+       x="35.443775"
+       y="39.886589"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.218986"
+         x="35.443775"
+         y="39.886589"
+         id="tspan5330">-10%</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/donation.svg b/dist/icons/achievements/donation.svg
new file mode 100644
index 000000000..da3c651a8
--- /dev/null
+++ b/dist/icons/achievements/donation.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="donation.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="33.916092"
+       y="33.325958"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.916092"
+         y="33.325958"
+         id="tspan11415">DONATION</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/drain.svg b/dist/icons/achievements/drain.svg
new file mode 100644
index 000000000..1b5a4b005
--- /dev/null
+++ b/dist/icons/achievements/drain.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="drain.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:30.1035px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.403166"
+       x="34.864677"
+       y="41.09906"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.403166"
+         x="34.864677"
+         y="41.09906"
+         id="tspan5330">$0</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/folders.svg b/dist/icons/achievements/folders.svg
new file mode 100644
index 000000000..080057bfd
--- /dev/null
+++ b/dist/icons/achievements/folders.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="folders.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:10.6208px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.142242"
+       x="34.928535"
+       y="37.743538"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.142242"
+         x="34.928535"
+         y="37.743538"
+         id="tspan5330">/scripts/</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/formulas.svg b/dist/icons/achievements/formulas.svg
new file mode 100644
index 000000000..6c5be3e90
--- /dev/null
+++ b/dist/icons/achievements/formulas.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="formulas.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:27.3155px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.365827"
+       x="5.2327757"
+       y="39.963947"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.365827"
+         x="5.2327757"
+         y="39.963947">f(x)</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/forze.svg b/dist/icons/achievements/forze.svg
new file mode 100644
index 000000000..a8b57f44e
--- /dev/null
+++ b/dist/icons/achievements/forze.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="forze.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:13.0104px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.174244"
+       x="34.064476"
+       y="38.520031"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.174244"
+         x="34.064476"
+         y="38.520031"
+         id="tspan3127">FROZEN</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/hack100000.svg b/dist/icons/achievements/hack100000.svg
new file mode 100644
index 000000000..698e8e518
--- /dev/null
+++ b/dist/icons/achievements/hack100000.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="hack100000.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.662px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+       x="33.197567"
+       y="30.194496"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.197567"
+         y="30.194496"
+         id="tspan2003">hack</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.197567"
+         y="48.521996"
+         id="tspan2495">100000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/hacknet-10m.svg b/dist/icons/achievements/hacknet-10m.svg
new file mode 100644
index 000000000..4b3c9e419
--- /dev/null
+++ b/dist/icons/achievements/hacknet-10m.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="hacknet-10m.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="34.445259"
+       y="33.325958"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.445259"
+         y="33.325958"
+         id="tspan10677">HACKNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.445259"
+         y="45.773895"
+         id="tspan11099">$10m</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/hacknet-all.svg b/dist/icons/achievements/hacknet-all.svg
new file mode 100644
index 000000000..dcd469710
--- /dev/null
+++ b/dist/icons/achievements/hacknet-all.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="hacknet-all.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="34.217846"
+       y="34.463017"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.217846"
+         y="34.463017"
+         id="tspan5330">HACKNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.217846"
+         y="46.910954"
+         id="tspan10677">ALL</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/hacknet-max.svg b/dist/icons/achievements/hacknet-max.svg
new file mode 100644
index 000000000..8fe597241
--- /dev/null
+++ b/dist/icons/achievements/hacknet-max.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="hacknet-max.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="34.217846"
+       y="34.463017"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.217846"
+         y="34.463017"
+         id="tspan5330">HACKNET</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="34.217846"
+         y="46.910954"
+         id="tspan10677">MAX</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/illuminati.svg b/dist/icons/achievements/illuminati.svg
new file mode 100644
index 000000000..526367451
--- /dev/null
+++ b/dist/icons/achievements/illuminati.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="illuminati.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:11.3623px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.152171"
+       x="2.7185695"
+       y="38.914951"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.152171"
+         x="2.7185695"
+         y="38.914951">Illuminati</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/install.svg b/dist/icons/achievements/install.svg
new file mode 100644
index 000000000..d26b20615
--- /dev/null
+++ b/dist/icons/achievements/install.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="install.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.6728px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.2099"
+       x="6.1825614"
+       y="39.945213"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.2099"
+         x="6.1825614"
+         y="39.945213">Install</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/install_100.svg b/dist/icons/achievements/install_100.svg
new file mode 100644
index 000000000..644038aab
--- /dev/null
+++ b/dist/icons/achievements/install_100.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="install_100.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.6728px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+       x="34.312416"
+       y="31.189854"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+         x="34.312416"
+         y="31.189854">Install</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+         x="34.312416"
+         y="50.780853"
+         id="tspan1231">100</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/karma.svg b/dist/icons/achievements/karma.svg
new file mode 100644
index 000000000..e0afb441b
--- /dev/null
+++ b/dist/icons/achievements/karma.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="karma.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:10.6208px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.142242"
+       x="34.928535"
+       y="37.743538"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.142242"
+         x="34.928535"
+         y="37.743538"
+         id="tspan5330">KARMA</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/maxcores.svg b/dist/icons/achievements/maxcores.svg
new file mode 100644
index 000000000..4ad449eb2
--- /dev/null
+++ b/dist/icons/achievements/maxcores.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="maxcores.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:12.8371px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.171924"
+       x="34.01947"
+       y="38.517769"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.171924"
+         x="34.01947"
+         y="38.517769"
+         id="tspan5330">8 Cores</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/maxram.svg b/dist/icons/achievements/maxram.svg
new file mode 100644
index 000000000..effc927a4
--- /dev/null
+++ b/dist/icons/achievements/maxram.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="maxram.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:12.8371px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.171924"
+       x="32.996117"
+       y="37.60812"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.171924"
+         x="32.996117"
+         y="37.60812"
+         id="tspan5330">2^30GB</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/nf255.svg b/dist/icons/achievements/nf255.svg
new file mode 100644
index 000000000..a23672bc9
--- /dev/null
+++ b/dist/icons/achievements/nf255.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="nf255.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.662px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+       x="33.538685"
+       y="39.290974"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.538685"
+         y="39.290974"
+         id="tspan3127">NF 255</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/node.svg b/dist/icons/achievements/node.svg
new file mode 100644
index 000000000..576020448
--- /dev/null
+++ b/dist/icons/achievements/node.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="node.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="33.763023"
+       y="38.329018"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.763023"
+         y="38.329018"
+         id="tspan5330">HACKNET</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/ns2.svg b/dist/icons/achievements/ns2.svg
new file mode 100644
index 000000000..2a75482ed
--- /dev/null
+++ b/dist/icons/achievements/ns2.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="ns2.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:14.662px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+       x="33.538685"
+       y="39.290974"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.196363"
+         x="33.538685"
+         y="39.290974"
+         id="tspan3127">NS2</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/p0.svg b/dist/icons/achievements/p0.svg
new file mode 100644
index 000000000..9a4f9e6f5
--- /dev/null
+++ b/dist/icons/achievements/p0.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="p0.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:41.3704px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.554058"
+       x="4.0280304"
+       y="48.20945"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.554058"
+         x="4.0280304"
+         y="48.20945">P0</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/p1.svg b/dist/icons/achievements/p1.svg
new file mode 100644
index 000000000..7bb2cf6cb
--- /dev/null
+++ b/dist/icons/achievements/p1.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="p1.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:41.3704px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.554058"
+       x="4.0280304"
+       y="48.20945"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.554058"
+         x="4.0280304"
+         y="48.20945">P1</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/p2.svg b/dist/icons/achievements/p2.svg
new file mode 100644
index 000000000..48d861052
--- /dev/null
+++ b/dist/icons/achievements/p2.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="p2.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:41.3704px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.554058"
+       x="4.0280304"
+       y="48.20945"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.554058"
+         x="4.0280304"
+         y="48.20945">P2</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/p3.svg b/dist/icons/achievements/p3.svg
new file mode 100644
index 000000000..cd82ca1ff
--- /dev/null
+++ b/dist/icons/achievements/p3.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="p3.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:41.3704px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.554058"
+       x="4.0280304"
+       y="48.20945"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.554058"
+         x="4.0280304"
+         y="48.20945">P3</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/p4.svg b/dist/icons/achievements/p4.svg
new file mode 100644
index 000000000..4a4ed8b48
--- /dev/null
+++ b/dist/icons/achievements/p4.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="p4.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:41.3704px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.554058"
+       x="4.0280304"
+       y="48.20945"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.554058"
+         x="4.0280304"
+         y="48.20945">P4</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/queue40.svg b/dist/icons/achievements/queue40.svg
new file mode 100644
index 000000000..6227323c7
--- /dev/null
+++ b/dist/icons/achievements/queue40.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="queue40.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:15.6728px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+       x="34.312416"
+       y="30.507618"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+         x="34.312416"
+         y="30.507618"
+         id="tspan1231">queue</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.2099"
+         x="34.312416"
+         y="50.098618"
+         id="tspan2003">40</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/reputation.svg b/dist/icons/achievements/reputation.svg
new file mode 100644
index 000000000..67e50d7f8
--- /dev/null
+++ b/dist/icons/achievements/reputation.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="reputation.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:9.95835px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+       x="33.916092"
+       y="33.325958"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.916092"
+         y="33.325958"
+         id="tspan11099">Reputation</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.13337"
+         x="33.916092"
+         y="45.773895"
+         id="tspan11415">10m</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/run1000.svg b/dist/icons/achievements/run1000.svg
new file mode 100644
index 000000000..a6d1ba6f3
--- /dev/null
+++ b/dist/icons/achievements/run1000.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="run1000.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.81048"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="146"
+     inkscape:window-y="51"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:13.0104px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.174244"
+       x="34.291889"
+       y="30.105789"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.174244"
+         x="34.291889"
+         y="30.105789"
+         id="tspan3127">RUN</tspan><tspan
+         sodipodi:role="line"
+         style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.174244"
+         x="34.291889"
+         y="46.36879"
+         id="tspan5330">1000</tspan></text>
+  </g>
+</svg>
diff --git a/dist/icons/achievements/thecovenant.svg b/dist/icons/achievements/thecovenant.svg
new file mode 100644
index 000000000..5dded05a7
--- /dev/null
+++ b/dist/icons/achievements/thecovenant.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="256"
+   height="256"
+   viewBox="0 0 67.733332 67.733335"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (c3084ef, 2021-09-22)"
+   sodipodi:docname="thecovenant.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="true"
+     units="px"
+     inkscape:zoom="2.326908"
+     inkscape:cx="86.380726"
+     inkscape:cy="111.09163"
+     inkscape:window-width="2423"
+     inkscape:window-height="1341"
+     inkscape:window-x="96"
+     inkscape:window-y="79"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid824" />
+  </sodipodi:namedview>
+  <defs
+     id="defs2" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background">
+    <rect
+       style="fill-opacity: 0%;stroke:none;stroke-width:7.02745"
+       id="rect849"
+       width="67.73333"
+       height="67.73333"
+       x="0"
+       y="0" />
+  </g>
+  <g
+     inkscape:label="main"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:8.0461px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1;stroke-width:0.107759"
+       x="2.917733"
+       y="36.395454"
+       id="text8876"><tspan
+         sodipodi:role="line"
+         id="tspan8874"
+         style="fill:#000000;fill-opacity:1;stroke-width:0.107759"
+         x="2.917733"
+         y="36.395454">The Covenant</tspan></text>
+  </g>
+</svg>
diff --git a/package.sh b/package.sh
index 94dbb9306..866be1700 100755
--- a/package.sh
+++ b/package.sh
@@ -7,6 +7,7 @@ mkdir -p .package/node_modules || true
 cp index.html .package
 cp -r electron/* .package
 cp -r dist/ext .package/dist
+cp -r dist/icons .package/dist
 
 # The css files
 cp dist/vendor.css .package/dist
diff --git a/src/Achievements/AchievementData.json b/src/Achievements/AchievementData.json
new file mode 100644
index 000000000..7228ea889
--- /dev/null
+++ b/src/Achievements/AchievementData.json
@@ -0,0 +1,486 @@
+{
+  "note": "***** Generated from a script, overwritten by steam achievements data *****",
+  "fetchedOn": 1641517584274,
+  "achievements": {
+    "CYBERSEC": {
+      "ID": "CYBERSEC",
+      "Name": "CyberSec",
+      "Description": "Join CyberSec."
+    },
+    "NITESEC": {
+      "ID": "NITESEC",
+      "Name": "avmnite-02h",
+      "Description": "Join NiteSec."
+    },
+    "THE_BLACK_HAND": {
+      "ID": "THE_BLACK_HAND",
+      "Name": "I.I.I.I",
+      "Description": "Join The Black Hand."
+    },
+    "BITRUNNERS": {
+      "ID": "BITRUNNERS",
+      "Name": "run4theh111z",
+      "Description": "Join the BitRunners."
+    },
+    "DAEDALUS": {
+      "ID": "DAEDALUS",
+      "Name": "fl1ght.exe",
+      "Description": "Join Daedalus."
+    },
+    "THE_COVENANT": {
+      "ID": "THE_COVENANT",
+      "Name": "The Covenant",
+      "Description": "Join The Covenant."
+    },
+    "ILLUMINATI": {
+      "ID": "ILLUMINATI",
+      "Name": "Illuminati",
+      "Description": "Join the Illuminati."
+    },
+    "BRUTESSH.EXE": {
+      "ID": "BRUTESSH.EXE",
+      "Name": "BruteSSH.exe",
+      "Description": "Acquire BruteSSH.exe"
+    },
+    "FTPCRACK.EXE": {
+      "ID": "FTPCRACK.EXE",
+      "Name": "FTPCrack.exe",
+      "Description": "Acquire FTPCrack.exe"
+    },
+    "RELAYSMTP.EXE": {
+      "ID": "RELAYSMTP.EXE",
+      "Name": "relaySMTP.exe",
+      "Description": "Acquire relaySMTP.exe"
+    },
+    "HTTPWORM.EXE": {
+      "ID": "HTTPWORM.EXE",
+      "Name": "HTTPWorm.exe",
+      "Description": "Acquire HTTPWorm.exe"
+    },
+    "SQLINJECT.EXE": {
+      "ID": "SQLINJECT.EXE",
+      "Name": "SQLInject.exe",
+      "Description": "Acquire SQLInject.exe"
+    },
+    "FORMULAS.EXE": {
+      "ID": "FORMULAS.EXE",
+      "Name": "Formulas.exe",
+      "Description": "Acquire Formulas.exe"
+    },
+    "SF1.1": {
+      "ID": "SF1.1",
+      "Name": "Source Genesis",
+      "Description": "Acquire SF1.1"
+    },
+    "SF2.1": {
+      "ID": "SF2.1",
+      "Name": "Rise of the Underworld",
+      "Description": "Acquire SF2.1"
+    },
+    "SF3.1": {
+      "ID": "SF3.1",
+      "Name": "Corporatocracy",
+      "Description": "Acquire SF3.1"
+    },
+    "SF4.1": {
+      "ID": "SF4.1",
+      "Name": "The Singularity",
+      "Description": "Acquire SF4.1"
+    },
+    "SF5.1": {
+      "ID": "SF5.1",
+      "Name": "Artificial Intelligence",
+      "Description": "Acquire SF5.1"
+    },
+    "SF6.1": {
+      "ID": "SF6.1",
+      "Name": "Bladeburners",
+      "Description": "Acquire SF6.1"
+    },
+    "SF7.1": {
+      "ID": "SF7.1",
+      "Name": "Bladeburners 2079",
+      "Description": "Acquire SF7.1"
+    },
+    "SF8.1": {
+      "ID": "SF8.1",
+      "Name": "Ghost of Wall Street",
+      "Description": "Acquire SF8.1"
+    },
+    "SF9.1": {
+      "ID": "SF9.1",
+      "Name": "Hacktocracy",
+      "Description": "Acquire SF9.1"
+    },
+    "SF10.1": {
+      "ID": "SF10.1",
+      "Name": "Digital Carbon",
+      "Description": "Acquire SF10.1"
+    },
+    "SF11.1": {
+      "ID": "SF11.1",
+      "Name": "The Big Crash",
+      "Description": "Acquire SF11.1"
+    },
+    "SF12.1": {
+      "ID": "SF12.1",
+      "Name": "The Recursion",
+      "Description": "Acquire SF12.1"
+    },
+    "MONEY_1Q": {
+      "ID": "MONEY_1Q",
+      "Name": "Here comes the money!",
+      "Description": "Have $1Q on your home computer."
+    },
+    "MONEY_M1B": {
+      "ID": "MONEY_M1B",
+      "Name": "Massive debt",
+      "Description": "Be $1b in debt."
+    },
+    "INSTALL_1": {
+      "ID": "INSTALL_1",
+      "Name": "I never asked for this.",
+      "Description": "Install your first augmentation."
+    },
+    "INSTALL_100": {
+      "ID": "INSTALL_100",
+      "Name": "I asked for this.",
+      "Description": "Have 100 augmentation installed at once."
+    },
+    "QUEUE_40": {
+      "ID": "QUEUE_40",
+      "Name": "It's time to install",
+      "Description": "Have 40 augmentation queued at once."
+    },
+    "HACKING_100000": {
+      "ID": "HACKING_100000",
+      "Name": "Power Overwhelming",
+      "Description": "Achieve 100 000 hacking skill."
+    },
+    "COMBAT_3000": {
+      "ID": "COMBAT_3000",
+      "Name": "One punch man",
+      "Description": "Achieve 3000 in all combat stats."
+    },
+    "NEUROFLUX_255": {
+      "ID": "NEUROFLUX_255",
+      "Name": "Neuroflux is love, Neuroflux is live",
+      "Description": "Install Neuroflux Governor level 255"
+    },
+    "NS2": {
+      "ID": "NS2",
+      "Name": "Maximum speed!",
+      "Description": "Write an ns2 script."
+    },
+    "FROZE": {
+      "ID": "FROZE",
+      "Name": "while(true);",
+      "Description": "Restart the game using the reload & kill all option because you froze it with an infinite loop."
+    },
+    "RUNNING_SCRIPTS_1000": {
+      "ID": "RUNNING_SCRIPTS_1000",
+      "Name": "Need more real life ram",
+      "Description": "Run 1000 scripts simultaneously."
+    },
+    "DRAIN_SERVER": {
+      "ID": "DRAIN_SERVER",
+      "Name": "Big trouble",
+      "Description": "Drain a server of all its money."
+    },
+    "MAX_RAM": {
+      "ID": "MAX_RAM",
+      "Name": "Download more ram",
+      "Description": "Maximize your home computer ram."
+    },
+    "MAX_CORES": {
+      "ID": "MAX_CORES",
+      "Name": "Download more cores?",
+      "Description": "Maximize your home computer cores."
+    },
+    "SCRIPTS_30": {
+      "ID": "SCRIPTS_30",
+      "Name": "Thank you folders!",
+      "Description": "Have 30 scripts on your home computer."
+    },
+    "KARMA_1000000": {
+      "ID": "KARMA_1000000",
+      "Name": "Wretched hive of scum and vilany",
+      "Description": "Reach -1m karma."
+    },
+    "STOCK_1q": {
+      "ID": "STOCK_1q",
+      "Name": "Wolf of wall stree.",
+      "Description": "Make 1q on the stock market."
+    },
+    "DISCOUNT": {
+      "ID": "DISCOUNT",
+      "Name": "Discount!",
+      "Description": "Get a discount at Powerhouse Gym by backdooring their server."
+    },
+    "SCRIPT_32GB": {
+      "ID": "SCRIPT_32GB",
+      "Name": "You'll need upgrade for this one.",
+      "Description": "Write a script that costs 32GB per thread."
+    },
+    "FIRST_HACKNET_NODE": {
+      "ID": "FIRST_HACKNET_NODE",
+      "Name": "Free money!",
+      "Description": "Purchase your first hacknet node."
+    },
+    "30_HACKNET_NODE": {
+      "ID": "30_HACKNET_NODE",
+      "Name": "Big network",
+      "Description": "Have 30 hacknet nodes."
+    },
+    "MAX_HACKNET_NODE": {
+      "ID": "MAX_HACKNET_NODE",
+      "Name": "That's the limit",
+      "Description": "Maximize a hacknet node."
+    },
+    "HACKNET_NODE_10M": {
+      "ID": "HACKNET_NODE_10M",
+      "Name": "The original hacker",
+      "Description": "Make 10m from hacknet nodes."
+    },
+    "REPUTATION_10M": {
+      "ID": "REPUTATION_10M",
+      "Name": "Well liked",
+      "Description": "Reach 10m reputation with a faction."
+    },
+    "DONATION": {
+      "ID": "DONATION",
+      "Name": "Donate!",
+      "Description": "Unlock donations with a faction."
+    },
+    "TRAVEL": {
+      "ID": "TRAVEL",
+      "Name": "World explorer",
+      "Description": "Travel anywhere."
+    },
+    "WORKOUT": {
+      "ID": "WORKOUT",
+      "Name": "Gains!",
+      "Description": "Workout at a gym."
+    },
+    "TOR": {
+      "ID": "TOR",
+      "Name": "The Onion Network",
+      "Description": "Purchase the TOR router."
+    },
+    "HOSPITALIZED": {
+      "ID": "HOSPITALIZED",
+      "Name": "Ouch!",
+      "Description": "Go to the hospital."
+    },
+    "GANG": {
+      "ID": "GANG",
+      "Name": "Gangster",
+      "Description": "Form a gang."
+    },
+    "FULL_GANG": {
+      "ID": "FULL_GANG",
+      "Name": "Don",
+      "Description": "Recruit all gang members."
+    },
+    "GANG_TERRITORY": {
+      "ID": "GANG_TERRITORY",
+      "Name": "Stay out of my territory",
+      "Description": "Have 100% of the territory."
+    },
+    "GANG_MEMBER_POWER": {
+      "ID": "GANG_MEMBER_POWER",
+      "Name": "One punch guy",
+      "Description": "Have a gang member with 10 000 in 1 skill."
+    },
+    "CORPORATION": {
+      "ID": "CORPORATION",
+      "Name": "A small 150b loan.",
+      "Description": "Create a corporation."
+    },
+    "CORPORATION_BRIBE": {
+      "ID": "CORPORATION_BRIBE",
+      "Name": "Lobbying is great!",
+      "Description": "Lower your taxes through lobbying."
+    },
+    "CORPORATION_PROD_1000": {
+      "ID": "CORPORATION_PROD_1000",
+      "Name": "Streamlined manufacturing",
+      "Description": "Have a division with a production multiplier of 1000."
+    },
+    "CORPORATION_EMPLOYEE_3000": {
+      "ID": "CORPORATION_EMPLOYEE_3000",
+      "Name": "Small town",
+      "Description": "Have a division with 3000 employee."
+    },
+    "CORPORATION_REAL_ESTATE": {
+      "ID": "CORPORATION_REAL_ESTATE",
+      "Name": "Own the land",
+      "Description": "Expand to the Real Estate division."
+    },
+    "INTELLIGENCE_255": {
+      "ID": "INTELLIGENCE_255",
+      "Name": "Smart!",
+      "Description": "Reach intelligence 255"
+    },
+    "BLADEBURNER_DIVISION": {
+      "ID": "BLADEBURNER_DIVISION",
+      "Name": "Bladeburners",
+      "Description": "Join the Bladeburner division."
+    },
+    "BLADEBURNER_OVERCLOCK": {
+      "ID": "BLADEBURNER_OVERCLOCK",
+      "Name": "Overclock!",
+      "Description": "Reach maximum level of Overclock"
+    },
+    "BLADEBURNER_UNSPENT_100000": {
+      "ID": "BLADEBURNER_UNSPENT_100000",
+      "Name": "You should really spent those.",
+      "Description": "Have 100 000 unspent bladeburner skill points."
+    },
+    "4S": {
+      "ID": "4S",
+      "Name": "4S",
+      "Description": "Purchase the 4S market data."
+    },
+    "FIRST_HACKNET_SERVER": {
+      "ID": "FIRST_HACKNET_SERVER",
+      "Name": "The improved hacker.",
+      "Description": "Purchase your first hacknet server."
+    },
+    "ALL_HACKNET_SERVER": {
+      "ID": "ALL_HACKNET_SERVER",
+      "Name": "Full network",
+      "Description": "Buy all hacknet servers."
+    },
+    "MAX_HACKNET_SERVER": {
+      "ID": "MAX_HACKNET_SERVER",
+      "Name": "That's the new limit.",
+      "Description": "Maximize a hacknet server."
+    },
+    "HACKNET_SERVER_1B": {
+      "ID": "HACKNET_SERVER_1B",
+      "Name": "Not passive anymore",
+      "Description": "Make $1b with hacknet servers."
+    },
+    "MAX_CACHE": {
+      "ID": "MAX_CACHE",
+      "Name": "What a waste.",
+      "Description": "Cap your hashes."
+    },
+    "SLEEVE_8": {
+      "ID": "SLEEVE_8",
+      "Name": "You and what army?",
+      "Description": "Purchase all duplicate sleeves from The Covenant."
+    },
+    "INDECISIVE": {
+      "ID": "INDECISIVE",
+      "Name": "Too many options.",
+      "Description": "Spend 1h straight on the bitverse."
+    },
+    "FAST_BN": {
+      "ID": "FAST_BN",
+      "Name": "Speed demon.",
+      "Description": "Destroy a bitnode in under 2 days."
+    },
+    "CHALLENGE_BN1": {
+      "ID": "CHALLENGE_BN1",
+      "Name": "BN1: Challenge",
+      "Description": "Destroy BN1 with at most 128GB and 1 core."
+    },
+    "CHALLENGE_BN2": {
+      "ID": "CHALLENGE_BN2",
+      "Name": "BN2: Challenge",
+      "Description": "Destroy BN2 without forming a gang."
+    },
+    "CHALLENGE_BN3": {
+      "ID": "CHALLENGE_BN3",
+      "Name": "BN3: Challenge",
+      "Description": "Destroy BN3 without creating corporation."
+    },
+    "CHALLENGE_BN6": {
+      "ID": "CHALLENGE_BN6",
+      "Name": "BN6: Challenge",
+      "Description": "Destroy BN6 without joining the bladeburner division."
+    },
+    "CHALLENGE_BN7": {
+      "ID": "CHALLENGE_BN7",
+      "Name": "BN7: Challenge",
+      "Description": "Destroy BN7 without joining the bladeburner division."
+    },
+    "CHALLENGE_BN8": {
+      "ID": "CHALLENGE_BN8",
+      "Name": "BN8: Challenge",
+      "Description": "Destroy BN8 without purchasing the 4s market data."
+    },
+    "CHALLENGE_BN9": {
+      "ID": "CHALLENGE_BN9",
+      "Name": "BN9: Challenge",
+      "Description": "Destroy BN9 without using hacknet servers."
+    },
+    "CHALLENGE_BN10": {
+      "ID": "CHALLENGE_BN10",
+      "Name": "BN10: Challenge",
+      "Description": "Destroy BN10 without using sleeves."
+    },
+    "CHALLENGE_BN12": {
+      "ID": "CHALLENGE_BN12",
+      "Name": "BN12: Challenge",
+      "Description": "Destroy BN12 50 times."
+    },
+    "BYPASS": {
+      "ID": "BYPASS",
+      "Name": "Exploit: bypass",
+      "Description": "Circumventing the ram cost of document."
+    },
+    "PROTOTYPETAMPERING": {
+      "ID": "PROTOTYPETAMPERING",
+      "Name": "Exploit: prototype tampering",
+      "Description": "Tamper with the Numbers prototype."
+    },
+    "UNCLICKABLE": {
+      "ID": "UNCLICKABLE",
+      "Name": "Exploit: unclickable",
+      "Description": "Click the unclickable."
+    },
+    "UNDOCUMENTEDFUNCTIONCALL": {
+      "ID": "UNDOCUMENTEDFUNCTIONCALL",
+      "Name": "Exploit: undocumented",
+      "Description": "Call the undocumented function."
+    },
+    "TIMECOMPRESSION": {
+      "ID": "TIMECOMPRESSION",
+      "Name": "Exploit: time compression",
+      "Description": "Compress time."
+    },
+    "REALITYALTERATION": {
+      "ID": "REALITYALTERATION",
+      "Name": "Exploit: reality alteration",
+      "Description": "Alter reality."
+    },
+    "N00DLES": {
+      "ID": "N00DLES",
+      "Name": "Exploit: noodles",
+      "Description": "Harness the power of the noodles."
+    },
+    "EDITSAVEFILE": {
+      "ID": "EDITSAVEFILE",
+      "Name": "Exploit: edit",
+      "Description": "Acquire the EditSaveFile Source-File -1"
+    },
+    "UNACHIEVABLE": {
+      "ID": "UNACHIEVABLE",
+      "Name": "UNACHIEVABLE",
+      "Description": "This achievement cannot be unlocked."
+    },
+    "CHALLENGE_BN13": {
+      "ID": "CHALLENGE_BN13",
+      "Name": "BN13: Challenge",
+      "Description": "Complete BN13 without Stanek's Gift."
+    },
+    "DEVMENU": {
+      "ID": "DEVMENU",
+      "Name": "Exploit: edit",
+      "Description": "Open the dev menu."
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/Achievements/AchievementEntry.tsx b/src/Achievements/AchievementEntry.tsx
new file mode 100644
index 000000000..0d3131a7a
--- /dev/null
+++ b/src/Achievements/AchievementEntry.tsx
@@ -0,0 +1,60 @@
+import React from "react";
+
+import { Box, Typography } from "@mui/material";
+
+import { Achievement } from "./Achievements";
+import { Settings } from "../Settings/Settings"
+import { AchievementIcon } from "./AchievementIcon";
+
+interface IProps {
+  achievement: Achievement;
+  unlockedOn?: number;
+  cssFiltersUnlocked: string;
+  cssFiltersLocked: string;
+}
+
+export function AchievementEntry({ achievement, unlockedOn, cssFiltersUnlocked, cssFiltersLocked }: IProps): JSX.Element {
+  if (!achievement) return <></>;
+  const isUnlocked = !!unlockedOn;
+
+  const mainColor = isUnlocked ? Settings.theme.primary : Settings.theme.secondarylight;
+
+  let achievedOn = '';
+  if (unlockedOn) {
+    achievedOn = new Date(unlockedOn).toLocaleString();
+  }
+
+  return (
+    <Box sx={{
+      border: `1px solid ${Settings.theme.well}`, mb: 2
+    }}>
+      <Box sx={{
+        display: 'flex',
+        flexDirection: 'row',
+        flexWrap: 'wrap',
+      }}>
+        <AchievementIcon
+          achievement={achievement} unlocked={isUnlocked} size="72px"
+          colorFilters={isUnlocked ? cssFiltersUnlocked: cssFiltersLocked} />
+        <Box sx={{
+          display: 'flex',
+          flexDirection: 'column',
+          justifyContent: 'center',
+          px: 1
+        }}>
+          <Typography variant="h6" sx={{ color: mainColor}}>
+            {achievement.Name}
+          </Typography>
+          <Typography variant="body2" sx={{ maxWidth: '500px', color: mainColor}}>
+            {achievement.Description}
+          </Typography>
+          {isUnlocked && (
+            <Typography variant="caption" sx={{ fontSize: '12px', color: Settings.theme.primarydark }}>
+              Acquired on {achievedOn}
+            </Typography>
+          )}
+        </Box>
+      </Box>
+    </Box>
+  );
+}
diff --git a/src/Achievements/AchievementIcon.tsx b/src/Achievements/AchievementIcon.tsx
new file mode 100644
index 000000000..7bf576b9b
--- /dev/null
+++ b/src/Achievements/AchievementIcon.tsx
@@ -0,0 +1,35 @@
+import React, { useState } from "react";
+
+import { Box } from "@mui/material";
+
+import { Achievement } from "./Achievements";
+import { Settings } from "../Settings/Settings"
+
+interface IProps {
+  achievement: Achievement;
+  unlocked: boolean;
+  colorFilters: string;
+  size: string;
+}
+
+export function AchievementIcon({ achievement, unlocked, colorFilters, size }: IProps): JSX.Element {
+  const [imgLoaded, setImgLoaded] = useState(false);
+  const mainColor = unlocked ? Settings.theme.primarydark : Settings.theme.secondarydark;
+
+  if (!achievement.Icon) return (<></>);
+  return (
+    <Box
+      sx={{
+        border: `1px solid ${mainColor}`,
+        width: size, height: size,
+        m: 1,
+        visibility: imgLoaded ? 'visible' : 'hidden'
+      }}
+    >
+      <img src={`dist/icons/achievements/${encodeURI(achievement.Icon)}.svg`}
+        style={{ filter: colorFilters, width: size, height: size }}
+        onLoad={() => setImgLoaded(true)}
+        alt={achievement.Name} />
+    </Box>
+  );
+}
diff --git a/src/Achievements/AchievementList.tsx b/src/Achievements/AchievementList.tsx
new file mode 100644
index 000000000..b590cf38c
--- /dev/null
+++ b/src/Achievements/AchievementList.tsx
@@ -0,0 +1,121 @@
+import React from "react";
+
+import { Accordion, AccordionSummary, AccordionDetails, Box, Typography } from "@mui/material";
+
+import { AchievementEntry } from "./AchievementEntry";
+import { Achievement,  PlayerAchievement} from "./Achievements";
+import { Settings } from "../Settings/Settings"
+import { getFiltersFromHex } from "../ThirdParty/colorUtils";
+import { CorruptableText } from "../ui/React/CorruptableText";
+
+interface IProps {
+  achievements: Achievement[];
+  playerAchievements: PlayerAchievement[];
+}
+
+export function AchievementList({ achievements, playerAchievements }: IProps): JSX.Element {
+  // Need to transform the primary color into css filters to change the color of the SVG.
+  const cssPrimary = getFiltersFromHex(Settings.theme.primary);
+  const cssSecondary = getFiltersFromHex(Settings.theme.secondary);
+
+  const data = achievements.map(achievement => ({
+    achievement,
+    unlockedOn: playerAchievements.find(playerAchievement => playerAchievement.ID === achievement.ID)?.unlockedOn,
+  })).sort((a, b) => (b.unlockedOn ?? 0) - (a.unlockedOn ?? 0));
+
+  const unlocked = data.filter(entry => entry.unlockedOn);
+
+  // Hidden achievements
+  const secret = data.filter(entry => !entry.unlockedOn && entry.achievement.Secret)
+
+  // Locked behind locked content (bitnode x)
+  const unavailable = data.filter(entry => !entry.unlockedOn && !entry.achievement.Secret && entry.achievement.Visible && entry.achievement.Visible());
+
+  // Remaining achievements
+  const locked = data
+    .filter(entry => !unlocked.map(u => u.achievement.ID).includes(entry.achievement.ID))
+    .filter(entry => !secret.map(u => u.achievement.ID).includes(entry.achievement.ID))
+    .filter(entry => !unavailable.map(u => u.achievement.ID).includes(entry.achievement.ID));
+
+  return (
+    <Box sx={{ pr: 18, my: 2 }}>
+      <Box sx={{
+        display: 'flex',
+        flexDirection: 'column',
+        flexWrap: 'wrap',
+      }}>
+        {unlocked.length > 0 && (
+          <Accordion defaultExpanded disableGutters square>
+            <AccordionSummary>
+              <Typography variant="h5" sx={{ my: 1 }}>
+                Acquired ({unlocked.length}/{data.length})
+              </Typography>
+            </AccordionSummary>
+            <AccordionDetails sx={{ pt: 2 }}>
+              {unlocked.map(item => (
+                <AchievementEntry key={item.achievement.ID}
+                  achievement={item.achievement}
+                  unlockedOn={item.unlockedOn}
+                  cssFiltersUnlocked={cssPrimary}
+                  cssFiltersLocked={cssSecondary} />
+              ))}
+            </AccordionDetails>
+          </Accordion>
+        )}
+
+        {locked.length > 0 && (
+          <Accordion disableGutters square>
+            <AccordionSummary>
+              <Typography variant="h5" color="secondary">
+                Locked ({locked.length} remaining)
+              </Typography>
+            </AccordionSummary>
+            <AccordionDetails sx={{ pt: 2 }}>
+              {locked.map(item => (
+                <AchievementEntry key={item.achievement.ID}
+                  achievement={item.achievement}
+                  cssFiltersUnlocked={cssPrimary}
+                  cssFiltersLocked={cssSecondary} />
+              ))}
+            </AccordionDetails>
+          </Accordion>
+        )}
+
+        {unavailable.length > 0 && (
+          <Accordion disableGutters square>
+            <AccordionSummary>
+              <Typography variant="h5" color="secondary">
+                Unavailable ({unavailable.length} remaining)
+              </Typography>
+            </AccordionSummary>
+            <AccordionDetails>
+            <Typography sx={{ mt: 1 }}>
+                {unavailable.length} additional achievements hidden behind content you don't have access to.
+              </Typography>
+            </AccordionDetails>
+          </Accordion>
+        )}
+
+        {secret.length > 0 && (
+          <Accordion disableGutters square>
+            <AccordionSummary>
+              <Typography variant="h5" color="secondary">
+                Secret ({secret.length} remaining)
+              </Typography>
+            </AccordionSummary>
+            <AccordionDetails>
+              <Typography color="secondary" sx={{ mt: 1 }}>
+                {secret.map(item => (
+                  <>
+                    <CorruptableText content={item.achievement.ID}></CorruptableText>
+                    <br />
+                  </>
+                ))}
+              </Typography>
+            </AccordionDetails>
+          </Accordion>
+        )}
+      </Box>
+    </Box>
+  );
+}
diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts
new file mode 100644
index 000000000..368c6bb15
--- /dev/null
+++ b/src/Achievements/Achievements.ts
@@ -0,0 +1,768 @@
+import { PlayerObject } from "src/PersonObjects/Player/PlayerObject";
+import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
+import { SkillNames } from "../Bladeburner/data/SkillNames";
+import { Skills } from "../Bladeburner/Skills";
+import { CONSTANTS } from "../Constants";
+import { Industries } from "../Corporation/IndustryData";
+import { Exploit } from "../Exploits/Exploit";
+import { Factions } from "../Faction/Factions";
+import { AllGangs } from "../Gang/AllGangs";
+import { GangConstants } from "../Gang/data/Constants";
+import { HacknetNodeConstants, HacknetServerConstants } from "../Hacknet/data/Constants";
+import { hasHacknetServers } from "../Hacknet/HacknetHelpers";
+import { HacknetNode } from "../Hacknet/HacknetNode";
+import { HacknetServer } from "../Hacknet/HacknetServer";
+import { CityName } from "../Locations/data/CityNames";
+import { Player } from "../Player";
+import { Programs } from "../Programs/Programs";
+import { GetAllServers, GetServer } from "../Server/AllServers";
+import { SpecialServers } from "../Server/data/SpecialServers";
+import { Server } from "../Server/Server";
+import { Router } from "../ui/GameRoot";
+import { Page } from "../ui/Router";
+import { IMap } from '../types';
+import * as data from "./AchievementData.json";
+
+// Unable to correctly cast the JSON data into AchievementDataJson type otherwise...
+const achievementData = (<AchievementDataJson><unknown>data).achievements;
+
+export interface Achievement {
+  ID: string;
+  Icon?: string;
+  Name?: string;
+  Description?: string;
+  Secret?: boolean;
+  Condition: () => boolean;
+  Visible?: () => boolean;
+}
+
+export interface PlayerAchievement {
+  ID: string;
+  unlockedOn?: number;
+}
+
+export interface AchievementDataJson {
+  achievements: IMap<AchievementData>;
+}
+
+export interface AchievementData {
+  ID: string;
+  Name: string;
+  Description: string;
+}
+
+function bitNodeFinishedState(): boolean {
+  const wd = GetServer(SpecialServers.WorldDaemon);
+  if (!(wd instanceof Server)) return false;
+  if (wd.backdoorInstalled) return true;
+  return Player.bladeburner !== null && Player.bladeburner.blackops.hasOwnProperty("Operation Daedalus");
+}
+
+function hasAccessToSF(player: PlayerObject, bn: number): boolean {
+  return player.bitNodeN === bn || player.sourceFiles.some((a) => a.n === bn);
+}
+
+function knowsAboutBitverse(player: PlayerObject): boolean {
+  return player.sourceFiles.some((a) => a.n === 1)
+}
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+function sfAchievement(): Achievement[] {
+  const achs: Achievement[] = [];
+  for (let i = 0; i <= 11; i++) {
+    for (let j = 1; j <= 3; j++) {
+      achs.push({
+        ID: `SF${i}.${j}`,
+        Condition: () => Player.sourceFileLvl(i) >= j,
+      });
+    }
+  }
+  return achs;
+}
+
+export const achievements: IMap<Achievement> = {
+  "CYBERSEC": {
+    ...achievementData['CYBERSEC'],
+    Icon: "CSEC",
+    Condition: () => Player.factions.includes("CyberSec"),
+  },
+  "NITESEC": {
+    ...achievementData['NITESEC'],
+    Icon: "NiteSec",
+    Condition: () => Player.factions.includes("NiteSec"),
+  },
+  "THE_BLACK_HAND": {
+    ...achievementData['THE_BLACK_HAND'],
+    Icon: "TBH",
+    Condition: () => Player.factions.includes("The Black Hand"),
+  },
+  "BITRUNNERS": {
+    ...achievementData['BITRUNNERS'],
+    Icon: 'bitrunners',
+    Condition: () => Player.factions.includes("BitRunners"),
+  },
+  "DAEDALUS": {
+    ...achievementData['DAEDALUS'],
+    Icon: "daedalus",
+    Condition: () => Player.factions.includes("Daedalus"),
+  },
+  "THE_COVENANT": {
+    ...achievementData['THE_COVENANT'],
+    Icon: "thecovenant",
+    Condition: () => Player.factions.includes("The Covenant"),
+  },
+  "ILLUMINATI": {
+    ...achievementData['ILLUMINATI'],
+    Icon: 'illuminati',
+    Condition: () => Player.factions.includes("Illuminati") ,
+  },
+  "BRUTESSH.EXE": {
+    ...achievementData['BRUTESSH.EXE'],
+    Icon: 'p0',
+    Condition: () => Player.getHomeComputer().programs.includes(Programs.BruteSSHProgram.name),
+  },
+  "FTPCRACK.EXE": {
+    ...achievementData['FTPCRACK.EXE'],
+    Icon: 'p1',
+    Condition: () => Player.getHomeComputer().programs.includes(Programs.FTPCrackProgram.name),
+  },
+  //-----------------------------------------------------
+  "RELAYSMTP.EXE": {
+    ...achievementData['RELAYSMTP.EXE'],
+    Icon: 'p2',
+    Condition: () => Player.getHomeComputer().programs.includes(Programs.RelaySMTPProgram.name),
+  },
+  "HTTPWORM.EXE": {
+    ...achievementData['HTTPWORM.EXE'],
+    Icon: 'p3',
+    Condition: () => Player.getHomeComputer().programs.includes(Programs.HTTPWormProgram.name),
+  },
+  "SQLINJECT.EXE": {
+    ...achievementData['SQLINJECT.EXE'],
+    Icon: 'p4',
+    Condition: () => Player.getHomeComputer().programs.includes(Programs.SQLInjectProgram.name),
+  },
+  "FORMULAS.EXE": {
+    ...achievementData['FORMULAS.EXE'],
+    Icon: 'formulas',
+      Condition: () => Player.getHomeComputer().programs.includes(Programs.Formulas.name),
+  },
+  "SF1.1": {
+    ...achievementData['SF1.1'],
+    Icon: 'SF1.1',
+      Visible: () => hasAccessToSF(Player, 1),
+      Condition: () => Player.sourceFileLvl(1) >= 1
+  },
+  "SF2.1": {
+    ...achievementData['SF2.1'],
+    Icon: "SF2.1",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () => Player.sourceFileLvl(2) >= 1,
+  },
+  "SF3.1": {
+    ...achievementData['SF3.1'],
+    Icon: "SF3.1",
+      Visible: () => hasAccessToSF(Player, 3),
+      Condition: () => Player.sourceFileLvl(3) >= 1,
+  },
+  "SF4.1": {
+    ...achievementData['SF4.1'],
+    Icon: "SF4.1",
+    Visible: () => hasAccessToSF(Player, 4),
+    Condition: () => Player.sourceFileLvl(4) >= 1,
+  },
+  "SF5.1": {
+    ...achievementData['SF5.1'],
+    Icon: "SF5.1",
+    Visible: () => hasAccessToSF(Player, 5),
+    Condition: () => Player.sourceFileLvl(5) >= 1,
+  },
+  "SF6.1": {
+    ...achievementData['SF6.1'],
+    Icon: "SF6.1",
+    Visible: () => hasAccessToSF(Player, 6),
+    Condition: () => Player.sourceFileLvl(6) >= 1,
+  },
+  "SF7.1": {
+    ...achievementData['SF7.1'],
+    Icon: "SF7.1",
+    Visible: () => hasAccessToSF(Player, 7),
+    Condition: () => Player.sourceFileLvl(7) >= 1,
+  },
+  "SF8.1": {
+    ...achievementData['SF8.1'],
+    Icon: "SF8.1",
+      Visible: () => hasAccessToSF(Player, 8),
+      Condition: () => Player.sourceFileLvl(8) >= 1,
+  },
+  "SF9.1": {
+    ...achievementData['SF9.1'],
+    Icon: "SF9.1",
+      Visible: () => hasAccessToSF(Player, 9),
+      Condition: () => Player.sourceFileLvl(9) >= 1,
+  },
+  "SF10.1": {
+    ...achievementData['SF10.1'],
+    Icon: "SF10.1",
+      Visible: () => hasAccessToSF(Player, 10),
+       Condition: () => Player.sourceFileLvl(10) >= 1
+  },
+  "SF11.1": {
+    ...achievementData['SF11.1'],
+    Icon: "SF11.1",
+    Visible: () => hasAccessToSF(Player, 11),
+    Condition: () => Player.sourceFileLvl(11) >= 1
+  },
+  "SF12.1": {
+    ...achievementData['SF12.1'],
+    Icon: "SF12.1",
+      Visible: () => hasAccessToSF(Player, 12),
+      Condition: () => Player.sourceFileLvl(12) >= 1
+  },
+  "MONEY_1Q": {
+    ...achievementData['MONEY_1Q'],
+    Icon: "$1Q",
+    Condition: () => Player.money >= 1e18,
+  },
+  "MONEY_M1B": {
+    ...achievementData['MONEY_M1B'],
+    Icon: "-1b",
+      Secret: true,
+      Condition: () => Player.money <= -1e9,
+  },
+  "INSTALL_1": {
+    ...achievementData['INSTALL_1'],
+    Icon: "install",
+    Condition: () => Player.augmentations.length >= 1,
+  },
+  "INSTALL_100": {
+    ...achievementData['INSTALL_100'],
+    Icon: "install_100",
+      Condition: () => Player.augmentations.length >= 100,
+  },
+  "QUEUE_40": {
+    ...achievementData['QUEUE_40'],
+    Icon: "queue40",
+      Condition: () => Player.queuedAugmentations.length >= 40,
+  },
+  "HACKING_100000": {
+    ...achievementData['HACKING_100000'],
+    Icon: "hack100000",
+      Condition: () => Player.hacking >= 100000,
+  },
+  "COMBAT_3000": {
+    ...achievementData['COMBAT_3000'],
+    Icon: "combat3000",
+      Condition: () =>
+        Player.strength >= 3000 && Player.defense >= 3000 && Player.dexterity >= 3000 && Player.agility >= 3000,
+  },
+  "NEUROFLUX_255": {
+    ...achievementData['NEUROFLUX_255'],
+    Icon: "nf255",
+      Condition: () => Player.augmentations.some((a) => a.name === AugmentationNames.NeuroFluxGovernor && a.level >= 255),
+  },
+  "NS2": {
+    ...achievementData['NS2'],
+    Icon: "ns2",
+    Condition: () => Player.getHomeComputer().scripts.some((s) => s.filename.endsWith(".js") || s.filename.endsWith(".ns")),
+  },
+  "FROZE": {
+    ...achievementData['FROZE'],
+    Icon: "forze",
+    Condition: () => location.href.includes("noScripts")
+  },
+  "RUNNING_SCRIPTS_1000": {
+    ...achievementData['RUNNING_SCRIPTS_1000'],
+    Icon: "run1000",
+    Condition: (): boolean => {
+      let running = 0;
+      for (const s of GetAllServers()) {
+        running += s.runningScripts.length;
+      }
+      return running >= 1000;
+    },
+  },
+  "DRAIN_SERVER": {
+    ...achievementData['DRAIN_SERVER'],
+    Icon: "drain",
+    Condition: (): boolean => {
+      for (const s of GetAllServers()) {
+        if (s instanceof Server) {
+          if (s.moneyMax > 0 && s.moneyAvailable === 0) return true;
+        }
+      }
+      return false;
+    },
+  },
+  "MAX_RAM": {
+    ...achievementData['MAX_RAM'],
+    Icon: "maxram",
+    Condition: () => Player.getHomeComputer().maxRam === CONSTANTS.HomeComputerMaxRam
+  },
+  "MAX_CORES": {
+    ...achievementData['MAX_CORES'],
+    Icon: "maxcores",
+    Condition: () => Player.getHomeComputer().cpuCores === 8
+  },
+  "SCRIPTS_30": {
+    ...achievementData['SCRIPTS_30'],
+    Icon: "folders",
+    Condition: () => Player.getHomeComputer().scripts.length >= 30
+  },
+  "KARMA_1000000": {
+    ...achievementData['KARMA_1000000'],
+    Icon: "karma",
+    Secret: true,
+    Condition: () => Player.karma <= -1e6
+  },
+  "STOCK_1q": {
+    ...achievementData['STOCK_1q'],
+    Icon: "$1Q",
+    Condition: () => Player.moneySourceB.stock >= 1e15
+  },
+  "DISCOUNT": {
+    ...achievementData['DISCOUNT'],
+    Icon: "discount",
+    Condition: (): boolean => {
+      const p = GetServer("powerhouse-fitness");
+      if (!(p instanceof Server)) return false;
+      return p.backdoorInstalled;
+    },
+  },
+  "SCRIPT_32GB": {
+    ...achievementData['SCRIPT_32GB'],
+    Icon: "bigcost",
+    Condition: () => Player.getHomeComputer().scripts.some((s) => s.ramUsage >= 32),
+  },
+  "FIRST_HACKNET_NODE": {
+    ...achievementData['FIRST_HACKNET_NODE'],
+    Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
+  },
+  "30_HACKNET_NODE": {
+    ...achievementData['30_HACKNET_NODE'],
+    Icon: "hacknet-all",
+    Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length >= 30,
+  },
+  "MAX_HACKNET_NODE": {
+    ...achievementData['MAX_HACKNET_NODE'],
+    Icon: "hacknet-max",
+    Condition: (): boolean => {
+      if (hasHacknetServers(Player)) return false;
+      for (const h of Player.hacknetNodes) {
+        if (!(h instanceof HacknetNode)) return false;
+        if (
+          h.ram === HacknetNodeConstants.MaxRam &&
+          h.cores === HacknetNodeConstants.MaxCores &&
+          h.level === HacknetNodeConstants.MaxLevel
+        )
+          return true;
+      }
+      return false;
+    },
+  },
+  "HACKNET_NODE_10M": {
+    ...achievementData['HACKNET_NODE_10M'],
+    Icon: "hacknet-10m",
+    Condition: () => !hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 10e6,
+  },
+  "REPUTATION_10M": {
+    ...achievementData['REPUTATION_10M'],
+    Icon: "reputation",
+    Condition: () => Object.values(Factions).some((f) => f.playerReputation >= 10e6),
+  },
+  "DONATION": {
+    ...achievementData['DONATION'],
+    Icon: "donation",
+    Condition: () => Object.values(Factions).some((f) => f.favor >= 150),
+  },
+  "TRAVEL": {
+    ...achievementData['TRAVEL'],
+    Icon: "travel",
+    Condition: () => Player.city !== CityName.Sector12,
+  },
+  "WORKOUT": {
+    ...achievementData['WORKOUT'],
+    Icon: "WORKOUT",
+    Condition: () =>
+      [
+        CONSTANTS.ClassGymStrength,
+        CONSTANTS.ClassGymDefense,
+        CONSTANTS.ClassGymDexterity,
+        CONSTANTS.ClassGymAgility,
+      ].includes(Player.className),
+  },
+  "TOR": {
+    ...achievementData['TOR'],
+    Icon: "TOR",
+    Condition: () => Player.hasTorRouter(),
+  },
+  "HOSPITALIZED": {
+    ...achievementData['HOSPITALIZED'],
+    Icon: "OUCH",
+    Condition: () => Player.moneySourceB.hospitalization !== 0,
+  },
+  "GANG": {
+    ...achievementData['GANG'],
+    Icon: "GANG",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () => Player.gang !== null,
+  },
+  "FULL_GANG": {
+    ...achievementData['FULL_GANG'],
+    Icon: "GANGMAX",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () => Player.gang !== null && Player.gang.members.length === GangConstants.MaximumGangMembers,
+  },
+  "GANG_TERRITORY": {
+    ...achievementData['GANG_TERRITORY'],
+    Icon: "GANG100%",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () => Player.gang !== null && AllGangs[Player.gang.facName].territory >= 0.999,
+  },
+  "GANG_MEMBER_POWER": {
+    ...achievementData['GANG_MEMBER_POWER'],
+    Icon: "GANG10000",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () =>
+      Player.gang !== null &&
+      Player.gang.members.some((m) => m.hack >= 10000 || m.str >= 10000 || m.def >= 10000 || m.dex >= 10000 || m.agi >= 10000 || m.cha >= 10000),
+  },
+  "CORPORATION": {
+    ...achievementData['CORPORATION'],
+    Icon: "CORP",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: () => Player.corporation !== null,
+  },
+  "CORPORATION_BRIBE": {
+    ...achievementData['CORPORATION_BRIBE'],
+    Icon: "CORPLOBBY",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: () => Player.corporation !== null && Player.corporation.unlockUpgrades[6] === 1,
+  },
+  "CORPORATION_PROD_1000": {
+    ...achievementData['CORPORATION_PROD_1000'],
+    Icon: "CORP1000",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: () => Player.corporation !== null && Player.corporation.divisions.some((d) => d.prodMult >= 1000),
+  },
+  "CORPORATION_EMPLOYEE_3000": {
+    ...achievementData['CORPORATION_EMPLOYEE_3000'],
+    Icon: "CORPCITY",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: (): boolean => {
+      if (Player.corporation === null) return false;
+      for (const d of Player.corporation.divisions) {
+        for (const o of Object.values(d.offices)) {
+          if (o === 0) continue;
+          if (o.employees.length > 3000) return true;
+        }
+      }
+      return false;
+    },
+  },
+  "CORPORATION_REAL_ESTATE": {
+    ...achievementData['CORPORATION_REAL_ESTATE'],
+    Icon: "CORPRE",
+    Name: "Own the land",
+    Description: "Expand to the Real Estate division.",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: () => Player.corporation !== null && Player.corporation.divisions.some((d) => d.type === Industries.RealEstate),
+  },
+  "INTELLIGENCE_255": {
+    ...achievementData['INTELLIGENCE_255'],
+    Icon: "INT255",
+    Visible: () => hasAccessToSF(Player, 5),
+    Condition: () => Player.intelligence >= 255,
+  },
+  "BLADEBURNER_DIVISION": {
+    ...achievementData['BLADEBURNER_DIVISION'],
+    Icon: "BLADE",
+    Visible: () => hasAccessToSF(Player, 6),
+    Condition: () => Player.bladeburner !== null,
+  },
+  "BLADEBURNER_OVERCLOCK": {
+    ...achievementData['BLADEBURNER_OVERCLOCK'],
+    Icon: "BLADEOVERCLOCK",
+    Visible: () => hasAccessToSF(Player, 6),
+    Condition: () =>
+      Player.bladeburner !== null &&
+      Player.bladeburner.skills[SkillNames.Overclock] === Skills[SkillNames.Overclock].maxLvl,
+  },
+  "BLADEBURNER_UNSPENT_100000": {
+    ...achievementData['BLADEBURNER_UNSPENT_100000'],
+    Icon: "BLADE100K",
+    Visible: () => hasAccessToSF(Player, 6),
+    Condition: () => Player.bladeburner !== null && Player.bladeburner.skillPoints >= 100000,
+  },
+  "4S": {
+    ...achievementData['4S'],
+    Icon: "4S",
+    Condition: () => Player.has4SData
+  },
+  "FIRST_HACKNET_SERVER": {
+    ...achievementData['FIRST_HACKNET_SERVER'],
+    Icon: "HASHNET",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
+  },
+  "ALL_HACKNET_SERVER": {
+    ...achievementData['ALL_HACKNET_SERVER'],
+    Icon: "HASHNETALL",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
+  },
+  "MAX_HACKNET_SERVER": {
+    ...achievementData['MAX_HACKNET_SERVER'],
+    Icon: "HASHNETALL",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: (): boolean => {
+      if (!hasHacknetServers(Player)) return false;
+      for (const h of Player.hacknetNodes) {
+        if (typeof h !== "string") return false;
+        const hs = GetServer(h);
+        if (!(hs instanceof HacknetServer)) return false;
+        if (
+          hs.maxRam === HacknetServerConstants.MaxRam &&
+          hs.cores === HacknetServerConstants.MaxCores &&
+          hs.level === HacknetServerConstants.MaxLevel &&
+          hs.cache === HacknetServerConstants.MaxCache
+        )
+          return true;
+      }
+      return false;
+    },
+  },
+  "HACKNET_SERVER_1B": {
+    ...achievementData['HACKNET_SERVER_1B'],
+    Icon: "HASHNETMONEY",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: () => hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 1e9,
+  },
+  "MAX_CACHE": {
+    ...achievementData['MAX_CACHE'],
+    Icon: "HASHNETCAP",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: () => hasHacknetServers(Player) && Player.hashManager.hashes === Player.hashManager.capacity,
+  },
+  "SLEEVE_8": {
+    ...achievementData['SLEEVE_8'],
+    Icon: "SLEEVE8",
+    Visible: () => hasAccessToSF(Player, 10),
+    Condition: () => Player.sleeves.length === 8,
+  },
+  "INDECISIVE": {
+    ...achievementData['INDECISIVE'],
+    Icon: "1H",
+    Visible: () => knowsAboutBitverse(Player),
+    Condition: (function () {
+      let c = 0;
+      setInterval(() => {
+        if (Router.page() === Page.BitVerse) {
+          c++;
+        } else {
+          c = 0;
+        }
+      }, 60 * 1000);
+      return () => c > 60;
+    })(),
+  },
+  "FAST_BN": {
+    ...achievementData['FAST_BN'],
+    Icon: "2DAYS",
+    Visible: () => knowsAboutBitverse(Player),
+    Condition: () => bitNodeFinishedState() && Player.playtimeSinceLastBitnode < 1000 * 60 * 60 * 24 * 2,
+  },
+  "CHALLENGE_BN1": {
+    ...achievementData['CHALLENGE_BN1'],
+    Icon: "BN1+",
+    Visible: () => knowsAboutBitverse(Player),
+    Condition: () =>
+      Player.bitNodeN === 1 &&
+      bitNodeFinishedState() &&
+      Player.getHomeComputer().maxRam <= 128 &&
+      Player.getHomeComputer().cpuCores === 1,
+  },
+  "CHALLENGE_BN2": {
+    ...achievementData['CHALLENGE_BN2'],
+    Icon: "BN2+",
+    Visible: () => hasAccessToSF(Player, 2),
+    Condition: () => Player.bitNodeN === 2 && bitNodeFinishedState() && Player.gang === null,
+  },
+  "CHALLENGE_BN3": {
+    ...achievementData['CHALLENGE_BN3'],
+    Icon: "BN3+",
+    Visible: () => hasAccessToSF(Player, 3),
+    Condition: () => Player.bitNodeN === 3 && bitNodeFinishedState() && Player.corporation === null,
+  },
+  "CHALLENGE_BN6": {
+    ...achievementData['CHALLENGE_BN6'],
+    Icon: "BN6+",
+    Visible: () => hasAccessToSF(Player, 6),
+    Condition: () => Player.bitNodeN === 6 && bitNodeFinishedState() && Player.bladeburner === null,
+  },
+  "CHALLENGE_BN7": {
+    ...achievementData['CHALLENGE_BN7'],
+    Icon: "BN7+",
+    Visible: () => hasAccessToSF(Player, 7),
+    Condition: () => Player.bitNodeN === 7 && bitNodeFinishedState() && Player.bladeburner === null,
+  },
+  "CHALLENGE_BN8": {
+    ...achievementData['CHALLENGE_BN8'],
+    Icon: "BN8+",
+    Visible: () => hasAccessToSF(Player, 8),
+    Condition: () => Player.bitNodeN === 8 && bitNodeFinishedState() && !Player.has4SData && !Player.has4SDataTixApi,
+  },
+  "CHALLENGE_BN9": {
+    ...achievementData['CHALLENGE_BN9'],
+    Icon: "BN9+",
+    Visible: () => hasAccessToSF(Player, 9),
+    Condition: () =>
+      Player.bitNodeN === 9 &&
+      bitNodeFinishedState() &&
+      Player.moneySourceB.hacknet === 0 &&
+      Player.moneySourceB.hacknet_expenses === 0,
+  },
+  "CHALLENGE_BN10": {
+    ...achievementData['CHALLENGE_BN10'],
+    Icon: "BN10+",
+    Visible: () => hasAccessToSF(Player, 10),
+    Condition: () =>
+      Player.bitNodeN === 10 &&
+      bitNodeFinishedState() &&
+      !Player.sleeves.some(
+        (s) =>
+          s.augmentations.length > 0 ||
+          s.hacking_exp > 0 ||
+          s.strength_exp > 0 ||
+          s.defense_exp > 0 ||
+          s.agility_exp > 0 ||
+          s.dexterity_exp > 0 ||
+          s.charisma_exp > 0,
+      ),
+  },
+  "CHALLENGE_BN12": {
+    ...achievementData['CHALLENGE_BN12'],
+    Icon: "BN12+",
+    Visible: () => hasAccessToSF(Player, 12),
+    Condition: () => Player.sourceFileLvl(12) >= 50
+  },
+  "BYPASS": {
+    ...achievementData['BYPASS'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.Bypass)
+  },
+  "PROTOTYPETAMPERING": {
+    ...achievementData['PROTOTYPETAMPERING'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.PrototypeTampering)
+  },
+  "UNCLICKABLE": {
+    ...achievementData['UNCLICKABLE'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.Unclickable)
+  },
+  "UNDOCUMENTEDFUNCTIONCALL": {
+    ...achievementData['UNDOCUMENTEDFUNCTIONCALL'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.UndocumentedFunctionCall)
+  },
+  "TIMECOMPRESSION": {
+    ...achievementData['TIMECOMPRESSION'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.TimeCompression)
+  },
+  "REALITYALTERATION": {
+    ...achievementData['REALITYALTERATION'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.RealityAlteration)
+  },
+  "N00DLES": {
+    ...achievementData['N00DLES'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.N00dles)
+  },
+  "EDITSAVEFILE": {
+    ...achievementData['EDITSAVEFILE'],
+    Icon: "SF-1",
+    Secret: true,
+    Condition: () => Player.exploits.includes(Exploit.EditSaveFile)
+  },
+  "UNACHIEVABLE": {
+    ...achievementData['UNACHIEVABLE'],
+    Icon: "SF-1",
+    Secret: true,
+    // Hey Players! Yes, you're supposed to modify this to get the achievement!
+    Condition: () => false,
+  },
+  "CHALLENGE_BN13": {
+    ...achievementData['CHALLENGE_BN13'],
+    Icon: "BN13+",
+    Visible: () => hasAccessToSF(Player, 13),
+    Condition: () =>
+      Player.bitNodeN === 13 &&
+      bitNodeFinishedState() &&
+      !Player.augmentations.some((a) => a.name === AugmentationNames.StaneksGift1),
+  },
+  "DEVMENU": {
+    ...achievementData['DEVMENU'],
+    Icon: "SF-1",
+    Condition: () => Player.exploits.includes(Exploit.YoureNotMeantToAccessThis)
+  }
+}
+
+  // Steam has a limit of 100 achievement. So these were planned but commented for now.
+  // { ID: "ECORP", Condition: () => Player.factions.includes("ECorp") },
+  // { ID: "MEGACORP", Condition: () => Player.factions.includes("MegaCorp") },
+  // { ID: "BACHMAN_&_ASSOCIATES", Condition: () => Player.factions.includes("Bachman & Associates") },
+  // { ID: "BLADE_INDUSTRIES", Condition: () => Player.factions.includes("Blade Industries") },
+  // { ID: "NWO", Condition: () => Player.factions.includes("NWO") },
+  // { ID: "CLARKE_INCORPORATED", Condition: () => Player.factions.includes("Clarke Incorporated") },
+  // { ID: "OMNITEK_INCORPORATED", Condition: () => Player.factions.includes("OmniTek Incorporated") },
+  // { ID: "FOUR_SIGMA", Condition: () => Player.factions.includes("Four Sigma") },
+  // { ID: "KUAIGONG_INTERNATIONAL", Condition: () => Player.factions.includes("KuaiGong International") },
+  // { ID: "FULCRUM_SECRET_TECHNOLOGIES", Condition: () => Player.factions.includes("Fulcrum Secret Technologies") },
+  // { ID: "AEVUM", Condition: () => Player.factions.includes("Aevum") },
+  // { ID: "CHONGQING", Condition: () => Player.factions.includes("Chongqing") },
+  // { ID: "ISHIMA", Condition: () => Player.factions.includes("Ishima") },
+  // { ID: "NEW_TOKYO", Condition: () => Player.factions.includes("New Tokyo") },
+  // { ID: "SECTOR-12", Condition: () => Player.factions.includes("Sector-12") },
+  // { ID: "VOLHAVEN", Condition: () => Player.factions.includes("Volhaven") },
+  // { ID: "SPEAKERS_FOR_THE_DEAD", Condition: () => Player.factions.includes("Speakers for the Dead") },
+  // { ID: "THE_DARK_ARMY", Condition: () => Player.factions.includes("The Dark Army") },
+  // { ID: "THE_SYNDICATE", Condition: () => Player.factions.includes("The Syndicate") },
+  // { ID: "SILHOUETTE", Condition: () => Player.factions.includes("Silhouette") },
+  // { ID: "TETRADS", Condition: () => Player.factions.includes("Tetrads") },
+  // { ID: "SLUM_SNAKES", Condition: () => Player.factions.includes("Slum Snakes") },
+  // { ID: "NETBURNERS", Condition: () => Player.factions.includes("Netburners") },
+  // { ID: "TIAN_DI_HUI", Condition: () => Player.factions.includes("Tian Di Hui") },
+  // { ID: "BLADEBURNERS", Condition: () => Player.factions.includes("Bladeburners") },
+  // { ID: "DEEPSCANV1.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.DeepscanV1.name) },
+  // { ID: "DEEPSCANV2.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.DeepscanV2.name) },
+  // {
+  //   ID: "SERVERPROFILER.EXE",
+  //   Condition: () => Player.getHomeComputer().programs.includes(Programs.ServerProfiler.name),
+  // },
+  // { ID: "AUTOLINK.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.AutoLink.name) },
+  // { ID: "FLIGHT.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.Flight.name) },
+
+export function calculateAchievements(): void {
+  const availableAchievements = Object.values(achievements).filter((a) => a.Condition()).map((a) => a.ID);
+  const playerAchievements = Player.achievements.map((a) => a.ID);
+  const newAchievements = availableAchievements.filter(a => !playerAchievements.includes(a));
+
+  for (const id of newAchievements) {
+    Player.giveAchievement(id);
+  }
+
+  // Write all player's achievements to document for Steam/Electron
+  // This could be replaced by "availableAchievements"
+  // if we don't want to grant the save game achievements to steam but only currently available
+  (document as any).achievements = [...Player.achievements.map(a => a.ID)];
+}
diff --git a/src/Achievements/AchievementsRoot.tsx b/src/Achievements/AchievementsRoot.tsx
new file mode 100644
index 000000000..12bf0cd93
--- /dev/null
+++ b/src/Achievements/AchievementsRoot.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+
+import makeStyles from "@mui/styles/makeStyles";
+import createStyles from "@mui/styles/createStyles";
+import { Theme } from "@mui/material/styles";
+
+import { AchievementList } from "./AchievementList";
+import { achievements } from "./Achievements";
+import { Typography } from "@mui/material";
+import { Player } from "../Player";
+
+const useStyles = makeStyles((theme: Theme) =>
+  createStyles({
+    root: {
+      width: 50,
+      padding: theme.spacing(2),
+      userSelect: "none",
+    },
+  }),
+);
+
+export function AchievementsRoot(): JSX.Element {
+  const classes = useStyles();
+  return (
+    <div className={classes.root} style={{ width: "90%" }}>
+      <Typography variant="h4">Achievements</Typography>
+      <AchievementList achievements={Object.values(achievements)} playerAchievements={Player.achievements} />
+    </div>
+  );
+}
diff --git a/src/Achievements/README.md b/src/Achievements/README.md
new file mode 100644
index 000000000..414145b13
--- /dev/null
+++ b/src/Achievements/README.md
@@ -0,0 +1,9 @@
+# Adding Achievements
+
+* Add a .svg in `./assets/Steam/achievements/real`
+* Create the achievement in Steam Dev Portal
+* Run `sh ./assets/Steam/achievements/pack-for-web.sh`
+* Run `node ./tools/fetch-steam-achievements-data DEVKEYHERE`
+  * Get your key here: https://steamcommunity.com/dev/apikey
+* Add an entry in `./src/Achievements/Achievements.ts` -> achievements
+* Commit `./dist/icons/achievements` & `./src/Achievements/AchievementData.json`
diff --git a/src/DevMenu.tsx b/src/DevMenu.tsx
index 856e44f9c..62300a430 100644
--- a/src/DevMenu.tsx
+++ b/src/DevMenu.tsx
@@ -22,6 +22,7 @@ import { StockMarket } from "./DevMenu/ui/StockMarket";
 import { Sleeves } from "./DevMenu/ui/Sleeves";
 import { Stanek } from "./DevMenu/ui/Stanek";
 import { TimeSkip } from "./DevMenu/ui/TimeSkip";
+import { Achievements } from "./DevMenu/ui/Achievements";
 import Typography from "@mui/material/Typography";
 import { Exploit } from "./Exploits/Exploit";
 
@@ -61,6 +62,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
       {props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && <Stanek />}
 
       <TimeSkip player={props.player} engine={props.engine} />
+      <Achievements player={props.player} engine={props.engine} />
     </>
   );
 }
diff --git a/src/DevMenu/ui/Achievements.tsx b/src/DevMenu/ui/Achievements.tsx
new file mode 100644
index 000000000..2d257dcd3
--- /dev/null
+++ b/src/DevMenu/ui/Achievements.tsx
@@ -0,0 +1,109 @@
+import React, { useState } from "react";
+
+import Accordion from "@mui/material/Accordion";
+import AccordionSummary from "@mui/material/AccordionSummary";
+import AccordionDetails from "@mui/material/AccordionDetails";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import Typography from "@mui/material/Typography";
+import Button from "@mui/material/Button";
+import ButtonGroup from "@mui/material/ButtonGroup";
+import { Tooltip } from "@mui/material";
+import LockIcon from '@mui/icons-material/Lock';
+import LockOpenIcon from '@mui/icons-material/LockOpen';
+
+import { IPlayer } from "../../PersonObjects/IPlayer";
+import { achievements } from "../../Achievements/Achievements";
+import { IEngine } from "../../IEngine";
+
+interface IProps {
+  player: IPlayer;
+  engine: IEngine;
+}
+
+export function Achievements(props: IProps): React.ReactElement {
+  const [playerAchievement, setPlayerAchievements] = useState(props.player.achievements.map(m => m.ID));
+
+  function grantAchievement(id: string): void {
+    props.player.giveAchievement(id);
+    setPlayerAchievements(props.player.achievements.map(m => m.ID));
+  }
+
+  function grantAllAchievements(): void {
+    Object.values(achievements).forEach(a => props.player.giveAchievement(a.ID));
+    setPlayerAchievements(props.player.achievements.map(m => m.ID));
+  }
+
+  function removeAchievement(id: string): void {
+    props.player.achievements = props.player.achievements.filter(a => a.ID !== id);
+    setPlayerAchievements(props.player.achievements.map(m => m.ID));
+  }
+
+  function clearAchievements(): void {
+    props.player.achievements = [];
+    setPlayerAchievements(props.player.achievements.map(m => m.ID));
+  }
+
+  function disableEngine(): void {
+    props.engine.Counters.achievementsCounter = Number.MAX_VALUE;
+  }
+
+  function enableEngine(): void {
+    props.engine.Counters.achievementsCounter = 0
+  }
+
+  return (
+    <Accordion TransitionProps={{ unmountOnExit: true }}>
+      <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+        <Typography>Achievements</Typography>
+      </AccordionSummary>
+      <AccordionDetails>
+        <table>
+          <tbody>
+            <tr>
+              <td>
+              </td>
+              <td>
+                <Typography>Achievements:</Typography>
+              </td>
+              <td>
+                <ButtonGroup>
+                  <Button onClick={grantAllAchievements}>Grant All</Button>
+                  <Button onClick={clearAchievements}>Clear</Button>
+                  <Button onClick={disableEngine}>Disable Engine</Button>
+                  <Button onClick={enableEngine}>Enable Engine</Button>
+                </ButtonGroup>
+              </td>
+            </tr>
+            {Object.values(achievements).map((i) => {
+              const achieved = playerAchievement.includes(i.ID);
+              return <tr key={"ach-" + i.ID}>
+                <td>
+                  {achieved ? (
+                    <Tooltip title="Achieved">
+                      <LockOpenIcon color="primary" />
+                    </Tooltip>
+                  ) : (
+                    <Tooltip title="Locked">
+                      <LockIcon color="secondary" />
+                    </Tooltip>
+                  )}
+                </td>
+                <td>
+                  <Tooltip title={<>{i.ID}<br />{i.Description}</>}>
+                    <Typography color={achieved ? 'primary': 'secondary'}>{i.Name}:</Typography>
+                  </Tooltip>
+                </td>
+                <td>
+                  <ButtonGroup>
+                    <Button onClick={() => grantAchievement(i.ID)}>Grant</Button>
+                    <Button onClick={() => removeAchievement(i.ID)}>Clear</Button>
+                  </ButtonGroup>
+                </td>
+              </tr>
+            })}
+          </tbody>
+        </table>
+      </AccordionDetails>
+    </Accordion>
+  );
+}
diff --git a/src/Electron.tsx b/src/Electron.tsx
index 44986e397..b4f4ba684 100644
--- a/src/Electron.tsx
+++ b/src/Electron.tsx
@@ -1,431 +1,18 @@
-import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
-import { SkillNames } from "./Bladeburner/data/SkillNames";
-import { Skills } from "./Bladeburner/Skills";
-import { CONSTANTS } from "./Constants";
-import { Industries } from "./Corporation/IndustryData";
-import { Exploit } from "./Exploits/Exploit";
-import { Factions } from "./Faction/Factions";
-import { AllGangs } from "./Gang/AllGangs";
-import { GangConstants } from "./Gang/data/Constants";
-import { HacknetNodeConstants, HacknetServerConstants } from "./Hacknet/data/Constants";
-import { hasHacknetServers } from "./Hacknet/HacknetHelpers";
-import { HacknetNode } from "./Hacknet/HacknetNode";
-import { HacknetServer } from "./Hacknet/HacknetServer";
-import { CityName } from "./Locations/data/CityNames";
 import { Player } from "./Player";
-import { Programs } from "./Programs/Programs";
 import { isScriptFilename } from "./Script/isScriptFilename";
 import { Script } from "./Script/Script";
-import { GetAllServers, GetServer } from "./Server/AllServers";
-import { SpecialServers } from "./Server/data/SpecialServers";
-import { Server } from "./Server/Server";
-import { Router } from "./ui/GameRoot";
-import { Page } from "./ui/Router";
 import { removeLeadingSlash } from "./Terminal/DirectoryHelpers";
 import { Terminal } from "./Terminal";
 import { SnackbarEvents } from "./ui/React/Snackbar";
 import { IMap } from "./types";
-
-interface Achievement {
-  ID: string;
-  Condition: () => boolean;
-}
-
-function bitNodeFinishedState(): boolean {
-  const wd = GetServer(SpecialServers.WorldDaemon);
-  if (!(wd instanceof Server)) return false;
-  if (wd.backdoorInstalled) return true;
-  return Player.bladeburner !== null && Player.bladeburner.blackops.hasOwnProperty("Operation Daedalus");
-}
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-function sfAchievement(): Achievement[] {
-  const achs: Achievement[] = [];
-  for (let i = 0; i <= 11; i++) {
-    for (let j = 1; j <= 3; j++) {
-      achs.push({
-        ID: `SF${i}.${j}`,
-        Condition: () => Player.sourceFileLvl(i) >= j,
-      });
-    }
-  }
-  return achs;
-}
-
-const achievements: Achievement[] = [
-  { ID: "CYBERSEC", Condition: () => Player.factions.includes("CyberSec") },
-  { ID: "NITESEC", Condition: () => Player.factions.includes("NiteSec") },
-  { ID: "THE_BLACK_HAND", Condition: () => Player.factions.includes("The Black Hand") },
-  { ID: "BITRUNNERS", Condition: () => Player.factions.includes("BitRunners") },
-  { ID: "THE_COVENANT", Condition: () => Player.factions.includes("The Covenant") },
-  { ID: "DAEDALUS", Condition: () => Player.factions.includes("Daedalus") },
-  { ID: "ILLUMINATI", Condition: () => Player.factions.includes("Illuminati") },
-  { ID: "BRUTESSH.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.BruteSSHProgram.name) },
-  { ID: "FTPCRACK.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.FTPCrackProgram.name) },
-  { ID: "RELAYSMTP.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.RelaySMTPProgram.name) },
-  { ID: "HTTPWORM.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.HTTPWormProgram.name) },
-  { ID: "SQLINJECT.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.SQLInjectProgram.name) },
-  { ID: "FORMULAS.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.Formulas.name) },
-  { ID: "SF1.1", Condition: () => Player.sourceFileLvl(1) >= 1 },
-  { ID: "SF2.1", Condition: () => Player.sourceFileLvl(2) >= 1 },
-  { ID: "SF3.1", Condition: () => Player.sourceFileLvl(3) >= 1 },
-  { ID: "SF4.1", Condition: () => Player.sourceFileLvl(4) >= 1 },
-  { ID: "SF5.1", Condition: () => Player.sourceFileLvl(5) >= 1 },
-  { ID: "SF6.1", Condition: () => Player.sourceFileLvl(6) >= 1 },
-  { ID: "SF7.1", Condition: () => Player.sourceFileLvl(7) >= 1 },
-  { ID: "SF8.1", Condition: () => Player.sourceFileLvl(8) >= 1 },
-  { ID: "SF9.1", Condition: () => Player.sourceFileLvl(9) >= 1 },
-  { ID: "SF10.1", Condition: () => Player.sourceFileLvl(10) >= 1 },
-  { ID: "SF11.1", Condition: () => Player.sourceFileLvl(11) >= 1 },
-  { ID: "SF12.1", Condition: () => Player.sourceFileLvl(12) >= 1 },
-  {
-    ID: "MONEY_1Q",
-    Condition: () => Player.money >= 1e18,
-  },
-  {
-    ID: "MONEY_M1B",
-    Condition: () => Player.money <= -1e9,
-  },
-  {
-    ID: "INSTALL_1",
-    Condition: () => Player.augmentations.length >= 1,
-  },
-  {
-    ID: "INSTALL_100",
-    Condition: () => Player.augmentations.length >= 100,
-  },
-  {
-    ID: "QUEUE_40",
-    Condition: () => Player.queuedAugmentations.length >= 40,
-  },
-  {
-    ID: "HACKING_100000",
-    Condition: () => Player.hacking >= 100000,
-  },
-  {
-    ID: "COMBAT_3000",
-    Condition: () =>
-      Player.strength >= 3000 && Player.defense >= 3000 && Player.dexterity >= 3000 && Player.agility >= 3000,
-  },
-  {
-    ID: "NEUROFLUX_255",
-    Condition: () => Player.augmentations.some((a) => a.name === AugmentationNames.NeuroFluxGovernor && a.level >= 255),
-  },
-  {
-    ID: "NS2",
-    Condition: () =>
-      Player.getHomeComputer().scripts.some((s) => s.filename.endsWith(".js") || s.filename.endsWith(".ns")),
-  },
-  { ID: "FROZE", Condition: () => location.href.includes("noScripts") },
-  {
-    ID: "RUNNING_SCRIPTS_1000",
-    Condition: () => {
-      let running = 0;
-      for (const s of GetAllServers()) {
-        running += s.runningScripts.length;
-      }
-      return running >= 1000;
-    },
-  },
-  {
-    ID: "DRAIN_SERVER",
-    Condition: () => {
-      for (const s of GetAllServers()) {
-        if (s instanceof Server) {
-          if (s.moneyMax > 0 && s.moneyAvailable === 0) return true;
-        }
-      }
-      return false;
-    },
-  },
-  { ID: "MAX_RAM", Condition: () => Player.getHomeComputer().maxRam === CONSTANTS.HomeComputerMaxRam },
-  { ID: "MAX_CORES", Condition: () => Player.getHomeComputer().cpuCores === 8 },
-  { ID: "SCRIPTS_30", Condition: () => Player.getHomeComputer().scripts.length >= 30 },
-  { ID: "KARMA_1000000", Condition: () => Player.karma <= -1e6 },
-  { ID: "STOCK_1q", Condition: () => Player.moneySourceB.stock >= 1e15 },
-  {
-    ID: "DISCOUNT",
-    Condition: () => {
-      const p = GetServer("powerhouse-fitness");
-      if (!(p instanceof Server)) return false;
-      return p.backdoorInstalled;
-    },
-  },
-  { ID: "SCRIPT_32GB", Condition: () => Player.getHomeComputer().scripts.some((s) => s.ramUsage >= 32) },
-  { ID: "FIRST_HACKNET_NODE", Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length > 0 },
-  {
-    ID: "30_HACKNET_NODE",
-    Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length >= 30,
-  },
-  {
-    ID: "MAX_HACKNET_NODE",
-    Condition: () => {
-      if (hasHacknetServers(Player)) return false;
-      for (const h of Player.hacknetNodes) {
-        if (!(h instanceof HacknetNode)) return false;
-        if (
-          h.ram === HacknetNodeConstants.MaxRam &&
-          h.cores === HacknetNodeConstants.MaxCores &&
-          h.level === HacknetNodeConstants.MaxLevel
-        )
-          return true;
-      }
-      return false;
-    },
-  },
-  { ID: "HACKNET_NODE_10M", Condition: () => !hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 10e6 },
-  { ID: "REPUTATION_10M", Condition: () => Object.values(Factions).some((f) => f.playerReputation >= 10e6) },
-  { ID: "DONATION", Condition: () => Object.values(Factions).some((f) => f.favor >= 150) },
-  { ID: "TRAVEL", Condition: () => Player.city !== CityName.Sector12 },
-  {
-    ID: "WORKOUT",
-    Condition: () =>
-      [
-        CONSTANTS.ClassGymStrength,
-        CONSTANTS.ClassGymDefense,
-        CONSTANTS.ClassGymDexterity,
-        CONSTANTS.ClassGymAgility,
-      ].includes(Player.className),
-  },
-  { ID: "TOR", Condition: () => Player.hasTorRouter() },
-  { ID: "HOSPITALIZED", Condition: () => Player.moneySourceB.hospitalization !== 0 },
-  { ID: "GANG", Condition: () => Player.gang !== null },
-  {
-    ID: "FULL_GANG",
-    Condition: () => Player.gang !== null && Player.gang.members.length === GangConstants.MaximumGangMembers,
-  },
-  {
-    ID: "GANG_TERRITORY",
-    Condition: () => Player.gang !== null && AllGangs[Player.gang.facName].territory >= 0.999,
-  },
-  {
-    ID: "GANG_MEMBER_POWER",
-    Condition: () =>
-      Player.gang !== null &&
-      Player.gang.members.some(
-        (m) =>
-          m.hack >= 10000 || m.str >= 10000 || m.def >= 10000 || m.dex >= 10000 || m.agi >= 10000 || m.cha >= 10000,
-      ),
-  },
-  { ID: "CORPORATION", Condition: () => Player.corporation !== null },
-  {
-    ID: "CORPORATION_BRIBE",
-    Condition: () => Player.corporation !== null && Player.corporation.unlockUpgrades[6] === 1,
-  },
-  {
-    ID: "CORPORATION_PROD_1000",
-    Condition: () => Player.corporation !== null && Player.corporation.divisions.some((d) => d.prodMult >= 1000),
-  },
-  {
-    ID: "CORPORATION_EMPLOYEE_3000",
-    Condition: () => {
-      if (Player.corporation === null) return false;
-      for (const d of Player.corporation.divisions) {
-        for (const o of Object.values(d.offices)) {
-          if (o === 0) continue;
-          if (o.employees.length >= 3000) return true;
-        }
-      }
-      return false;
-    },
-  },
-  {
-    ID: "CORPORATION_REAL_ESTATE",
-    Condition: () =>
-      Player.corporation !== null && Player.corporation.divisions.some((d) => d.type === Industries.RealEstate),
-  },
-  { ID: "INTELLIGENCE_255", Condition: () => Player.intelligence >= 255 },
-  { ID: "BLADEBURNER_DIVISION", Condition: () => Player.bladeburner !== null },
-  {
-    ID: "BLADEBURNER_OVERCLOCK",
-    Condition: () =>
-      Player.bladeburner !== null &&
-      Player.bladeburner.skills[SkillNames.Overclock] === Skills[SkillNames.Overclock].maxLvl,
-  },
-  {
-    ID: "BLADEBURNER_UNSPENT_100000",
-    Condition: () => Player.bladeburner !== null && Player.bladeburner.skillPoints >= 100000,
-  },
-  { ID: "4S", Condition: () => Player.has4SData },
-  { ID: "FIRST_HACKNET_SERVER", Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length > 0 },
-  {
-    ID: "ALL_HACKNET_SERVER",
-    Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
-  },
-  {
-    ID: "MAX_HACKNET_SERVER",
-    Condition: () => {
-      if (!hasHacknetServers(Player)) return false;
-      for (const h of Player.hacknetNodes) {
-        if (typeof h !== "string") return false;
-        const hs = GetServer(h);
-        if (!(hs instanceof HacknetServer)) return false;
-        if (
-          hs.maxRam === HacknetServerConstants.MaxRam &&
-          hs.cores === HacknetServerConstants.MaxCores &&
-          hs.level === HacknetServerConstants.MaxLevel &&
-          hs.cache === HacknetServerConstants.MaxCache
-        )
-          return true;
-      }
-      return false;
-    },
-  },
-  { ID: "HACKNET_SERVER_1B", Condition: () => hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 1e9 },
-  {
-    ID: "MAX_CACHE",
-    Condition: () => hasHacknetServers(Player) &&
-      Player.hashManager.hashes === Player.hashManager.capacity &&
-      Player.hashManager.capacity > 0,
-  },
-  {
-    ID: "SLEEVE_8",
-    Condition: () => Player.sleeves.length === 8,
-  },
-  {
-    ID: "FAST_BN",
-    Condition: () => bitNodeFinishedState() && Player.playtimeSinceLastBitnode < 1000 * 60 * 60 * 24 * 2,
-  },
-  {
-    ID: "INDECISIVE",
-    Condition: (function () {
-      let c = 0;
-      setInterval(() => {
-        if (Router.page() === Page.BitVerse) {
-          c++;
-        } else {
-          c = 0;
-        }
-      }, 60 * 1000);
-      return () => c > 60;
-    })(),
-  },
-  {
-    ID: "CHALLENGE_BN1",
-    Condition: () =>
-      Player.bitNodeN === 1 &&
-      bitNodeFinishedState() &&
-      Player.getHomeComputer().maxRam <= 128 &&
-      Player.getHomeComputer().cpuCores === 1,
-  },
-  {
-    ID: "CHALLENGE_BN2",
-    Condition: () => Player.bitNodeN === 2 && bitNodeFinishedState() && Player.gang === null,
-  },
-  {
-    ID: "CHALLENGE_BN3",
-    Condition: () => Player.bitNodeN === 3 && bitNodeFinishedState() && Player.corporation === null,
-  },
-  {
-    ID: "CHALLENGE_BN6",
-    Condition: () => Player.bitNodeN === 6 && bitNodeFinishedState() && Player.bladeburner === null,
-  },
-  {
-    ID: "CHALLENGE_BN7",
-    Condition: () => Player.bitNodeN === 7 && bitNodeFinishedState() && Player.bladeburner === null,
-  },
-  {
-    ID: "CHALLENGE_BN8",
-    Condition: () => Player.bitNodeN === 8 && bitNodeFinishedState() && !Player.has4SData && !Player.has4SDataTixApi,
-  },
-  {
-    ID: "CHALLENGE_BN9",
-    Condition: () =>
-      Player.bitNodeN === 9 &&
-      bitNodeFinishedState() &&
-      Player.moneySourceB.hacknet === 0 &&
-      Player.moneySourceB.hacknet_expenses === 0,
-  },
-  {
-    ID: "CHALLENGE_BN10",
-    Condition: () =>
-      Player.bitNodeN === 10 &&
-      bitNodeFinishedState() &&
-      !Player.sleeves.some(
-        (s) =>
-          s.augmentations.length > 0 ||
-          s.hacking_exp > 0 ||
-          s.strength_exp > 0 ||
-          s.defense_exp > 0 ||
-          s.agility_exp > 0 ||
-          s.dexterity_exp > 0 ||
-          s.charisma_exp > 0,
-      ),
-  },
-  { ID: "CHALLENGE_BN12", Condition: () => Player.sourceFileLvl(12) >= 50 },
-  {
-    ID: "CHALLENGE_BN13",
-    Condition: () =>
-      Player.bitNodeN === 13 &&
-      bitNodeFinishedState() &&
-      !Player.augmentations.some((a) => a.name === AugmentationNames.StaneksGift1),
-  },
-  { ID: "BYPASS", Condition: () => Player.exploits.includes(Exploit.Bypass) },
-  { ID: "PROTOTYPETAMPERING", Condition: () => Player.exploits.includes(Exploit.PrototypeTampering) },
-  { ID: "UNCLICKABLE", Condition: () => Player.exploits.includes(Exploit.Unclickable) },
-  { ID: "UNDOCUMENTEDFUNCTIONCALL", Condition: () => Player.exploits.includes(Exploit.UndocumentedFunctionCall) },
-  { ID: "TIMECOMPRESSION", Condition: () => Player.exploits.includes(Exploit.TimeCompression) },
-  { ID: "REALITYALTERATION", Condition: () => Player.exploits.includes(Exploit.RealityAlteration) },
-  { ID: "N00DLES", Condition: () => Player.exploits.includes(Exploit.N00dles) },
-  { ID: "EDITSAVEFILE", Condition: () => Player.exploits.includes(Exploit.EditSaveFile) },
-  { ID: "DEVMENU", Condition: () => Player.exploits.includes(Exploit.YoureNotMeantToAccessThis) },
-  {
-    ID: "UNACHIEVABLE",
-    // Hey Players! Yes, you're supposed to modify this to get the achievement!
-    Condition: () => false,
-  },
-
-  // Steam has a limit of 100 achievement. So these were planned but commented for now.
-  // { ID: "ECORP", Condition: () => Player.factions.includes("ECorp") },
-  // { ID: "MEGACORP", Condition: () => Player.factions.includes("MegaCorp") },
-  // { ID: "BACHMAN_&_ASSOCIATES", Condition: () => Player.factions.includes("Bachman & Associates") },
-  // { ID: "BLADE_INDUSTRIES", Condition: () => Player.factions.includes("Blade Industries") },
-  // { ID: "NWO", Condition: () => Player.factions.includes("NWO") },
-  // { ID: "CLARKE_INCORPORATED", Condition: () => Player.factions.includes("Clarke Incorporated") },
-  // { ID: "OMNITEK_INCORPORATED", Condition: () => Player.factions.includes("OmniTek Incorporated") },
-  // { ID: "FOUR_SIGMA", Condition: () => Player.factions.includes("Four Sigma") },
-  // { ID: "KUAIGONG_INTERNATIONAL", Condition: () => Player.factions.includes("KuaiGong International") },
-  // { ID: "FULCRUM_SECRET_TECHNOLOGIES", Condition: () => Player.factions.includes("Fulcrum Secret Technologies") },
-  // { ID: "AEVUM", Condition: () => Player.factions.includes("Aevum") },
-  // { ID: "CHONGQING", Condition: () => Player.factions.includes("Chongqing") },
-  // { ID: "ISHIMA", Condition: () => Player.factions.includes("Ishima") },
-  // { ID: "NEW_TOKYO", Condition: () => Player.factions.includes("New Tokyo") },
-  // { ID: "SECTOR-12", Condition: () => Player.factions.includes("Sector-12") },
-  // { ID: "VOLHAVEN", Condition: () => Player.factions.includes("Volhaven") },
-  // { ID: "SPEAKERS_FOR_THE_DEAD", Condition: () => Player.factions.includes("Speakers for the Dead") },
-  // { ID: "THE_DARK_ARMY", Condition: () => Player.factions.includes("The Dark Army") },
-  // { ID: "THE_SYNDICATE", Condition: () => Player.factions.includes("The Syndicate") },
-  // { ID: "SILHOUETTE", Condition: () => Player.factions.includes("Silhouette") },
-  // { ID: "TETRADS", Condition: () => Player.factions.includes("Tetrads") },
-  // { ID: "SLUM_SNAKES", Condition: () => Player.factions.includes("Slum Snakes") },
-  // { ID: "NETBURNERS", Condition: () => Player.factions.includes("Netburners") },
-  // { ID: "TIAN_DI_HUI", Condition: () => Player.factions.includes("Tian Di Hui") },
-  // { ID: "BLADEBURNERS", Condition: () => Player.factions.includes("Bladeburners") },
-  // { ID: "DEEPSCANV1.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.DeepscanV1.name) },
-  // { ID: "DEEPSCANV2.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.DeepscanV2.name) },
-  // {
-  //   ID: "SERVERPROFILER.EXE",
-  //   Condition: () => Player.getHomeComputer().programs.includes(Programs.ServerProfiler.name),
-  // },
-  // { ID: "AUTOLINK.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.AutoLink.name) },
-  // { ID: "FLIGHT.EXE", Condition: () => Player.getHomeComputer().programs.includes(Programs.Flight.name) },
-];
-
-function setAchievements(achs: string[]): void {
-  (document as any).achievements = achs;
-}
-
-function calculateAchievements(): void {
-  setAchievements(achievements.filter((a) => a.Condition()).map((a) => a.ID));
-}
+import { GetServer } from "./Server/AllServers";
 
 export function initElectron(): void {
   const userAgent = navigator.userAgent.toLowerCase();
   if (userAgent.indexOf(" electron/") > -1) {
     // Electron-specific code
-    setAchievements([]);
+    (document as any).achievements = [];
     initWebserver();
-    setInterval(calculateAchievements, 5000);
     initAppNotifier();
   }
 }
diff --git a/src/IEngine.ts b/src/IEngine.ts
index d495e5e20..5f99fdf97 100644
--- a/src/IEngine.ts
+++ b/src/IEngine.ts
@@ -19,6 +19,7 @@ export interface IEngine {
     messages: number;
     mechanicProcess: number;
     contractGeneration: number;
+    achievementsCounter: number;
   };
   decrementAllCounters: (numCycles?: number) => void;
   checkCounters: () => void;
diff --git a/src/PersonObjects/IPlayer.ts b/src/PersonObjects/IPlayer.ts
index 3153cb2b5..e6aa717c5 100644
--- a/src/PersonObjects/IPlayer.ts
+++ b/src/PersonObjects/IPlayer.ts
@@ -30,6 +30,7 @@ import { IRouter } from "../ui/Router";
 import { WorkerScript } from "../Netscript/WorkerScript";
 import { HacknetServer } from "../Hacknet/HacknetServer";
 import { ISkillProgress } from "./formulas/skill";
+import { PlayerAchievement } from "../Achievements/Achievements";
 
 export interface IPlayer {
   // Class members
@@ -70,6 +71,7 @@ export interface IPlayer {
   sleevesFromCovenant: number;
   sourceFiles: IPlayerOwnedSourceFile[];
   exploits: Exploit[];
+  achievements: PlayerAchievement[];
   lastUpdate: number;
   totalPlaytime: number;
 
@@ -238,6 +240,7 @@ export interface IPlayer {
   takeDamage(amt: number): boolean;
   travel(to: CityName): boolean;
   giveExploit(exploit: Exploit): void;
+  giveAchievement(achievementId: string): void;
   queryStatFromString(str: string): number;
   getIntelligenceBonus(weight: number): number;
   getCasinoWinnings(): number;
diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts
index 8497e94a1..07d5bacef 100644
--- a/src/PersonObjects/Player/PlayerObject.ts
+++ b/src/PersonObjects/Player/PlayerObject.ts
@@ -35,6 +35,7 @@ import { CityName } from "../../Locations/data/CityNames";
 import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
 import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver";
 import { ISkillProgress } from "../formulas/skill";
+import { PlayerAchievement } from '../../Achievements/Achievements';
 
 export class PlayerObject implements IPlayer {
   // Class members
@@ -75,6 +76,7 @@ export class PlayerObject implements IPlayer {
   sleevesFromCovenant: number;
   sourceFiles: IPlayerOwnedSourceFile[];
   exploits: Exploit[];
+  achievements: PlayerAchievement[];
   lastUpdate: number;
   totalPlaytime: number;
 
@@ -243,6 +245,7 @@ export class PlayerObject implements IPlayer {
   takeDamage: (amt: number) => boolean;
   travel: (to: CityName) => boolean;
   giveExploit: (exploit: Exploit) => void;
+  giveAchievement: (achievementId: string) => void;
   queryStatFromString: (str: string) => number;
   getIntelligenceBonus: (weight: number) => number;
   getCasinoWinnings: () => number;
@@ -467,6 +470,7 @@ export class PlayerObject implements IPlayer {
     this.scriptProdSinceLastAug = 0;
 
     this.exploits = [];
+    this.achievements = [];
 
     this.init = generalMethods.init;
     this.prestigeAugmentation = generalMethods.prestigeAugmentation;
@@ -557,6 +561,7 @@ export class PlayerObject implements IPlayer {
     this.gotoLocation = generalMethods.gotoLocation;
     this.canAccessResleeving = generalMethods.canAccessResleeving;
     this.giveExploit = generalMethods.giveExploit;
+    this.giveAchievement = generalMethods.giveAchievement;
     this.getIntelligenceBonus = generalMethods.getIntelligenceBonus;
     this.getCasinoWinnings = generalMethods.getCasinoWinnings;
     this.hasAugmentation = augmentationMethods.hasAugmentation;
diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx b/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx
index 835ecffe4..3990540b0 100644
--- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx
+++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx
@@ -64,6 +64,7 @@ import React from "react";
 import { serverMetadata } from "../../Server/data/servers";
 import { SnackbarEvents } from "../../ui/React/Snackbar";
 import { calculateClassEarnings } from "../formulas/work";
+import { achievements } from "../../Achievements/Achievements";
 
 export function init(this: IPlayer): void {
   /* Initialize Player's home computer */
@@ -2634,6 +2635,15 @@ export function giveExploit(this: IPlayer, exploit: Exploit): void {
   }
 }
 
+export function giveAchievement(this: IPlayer, achievementId: string): void {
+  const achievement = achievements[achievementId];
+  if (!achievement) return;
+  if (!this.achievements.map(a => a.ID).includes(achievementId)) {
+    this.achievements.push({ ID: achievementId, unlockedOn: new Date().getTime() });
+    SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, 'success', 2000);
+  }
+}
+
 export function getIntelligenceBonus(this: IPlayer, weight: number): number {
   return calculateIntelligenceBonus(this.intelligence, weight);
 }
diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx
index 132758e92..0e51a2175 100644
--- a/src/Sidebar/ui/SidebarRoot.tsx
+++ b/src/Sidebar/ui/SidebarRoot.tsx
@@ -37,6 +37,7 @@ import CheckIcon from "@mui/icons-material/Check"; // Milestones
 import HelpIcon from "@mui/icons-material/Help"; // Tutorial
 import SettingsIcon from "@mui/icons-material/Settings"; // options
 import DeveloperBoardIcon from "@mui/icons-material/DeveloperBoard"; // Dev
+import EmojiEventsIcon from "@mui/icons-material/EmojiEvents"; // Achievements
 import AccountBoxIcon from "@mui/icons-material/AccountBox";
 import PublicIcon from "@mui/icons-material/Public";
 import LiveHelpIcon from "@mui/icons-material/LiveHelp";
@@ -256,6 +257,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
     props.router.toDevMenu();
   }
 
+  function clickAchievements(): void {
+    props.router.toAchievements();
+  }
+
   useEffect(() => {
     // Shortcuts to navigate through the game
     //  Alt-t - Terminal
@@ -747,6 +752,21 @@ export function SidebarRoot(props: IProps): React.ReactElement {
               </Typography>
             </ListItemText>
           </ListItem>
+          <ListItem
+            button
+            key={"Achievements"}
+            className={clsx({
+              [classes.active]: props.page === Page.Achievements,
+            })}
+            onClick={clickAchievements}
+          >
+            <ListItemIcon>
+              <EmojiEventsIcon color={props.page !== Page.Achievements ? "secondary" : "primary"} />
+            </ListItemIcon>
+            <ListItemText>
+              <Typography color={props.page !== Page.Achievements ? "secondary" : "primary"}>Achievements</Typography>
+            </ListItemText>
+          </ListItem>
           <ListItem
             button
             key={"Options"}
diff --git a/src/ThirdParty/colorUtils.ts b/src/ThirdParty/colorUtils.ts
new file mode 100644
index 000000000..5847186fa
--- /dev/null
+++ b/src/ThirdParty/colorUtils.ts
@@ -0,0 +1,315 @@
+// @ts-nocheck
+/* tslint:disable */
+/* eslint-disable */
+
+/*
+  Taken from:
+  https://codepen.io/sosuke/pen/Pjoqqp
+  --------------------------------------------------------
+  This utility transform an hex color into css filter rules.
+  Useful to change color of a black image to match a given color
+*/
+
+class Color {
+  constructor(r, g, b) {
+    this.set(r, g, b);
+  }
+
+  toString() {
+    return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;
+  }
+
+  set(r, g, b) {
+    this.r = this.clamp(r);
+    this.g = this.clamp(g);
+    this.b = this.clamp(b);
+  }
+
+  hueRotate(angle = 0) {
+    angle = angle / 180 * Math.PI;
+    const sin = Math.sin(angle);
+    const cos = Math.cos(angle);
+
+    this.multiply([
+      0.213 + cos * 0.787 - sin * 0.213,
+      0.715 - cos * 0.715 - sin * 0.715,
+      0.072 - cos * 0.072 + sin * 0.928,
+      0.213 - cos * 0.213 + sin * 0.143,
+      0.715 + cos * 0.285 + sin * 0.140,
+      0.072 - cos * 0.072 - sin * 0.283,
+      0.213 - cos * 0.213 - sin * 0.787,
+      0.715 - cos * 0.715 + sin * 0.715,
+      0.072 + cos * 0.928 + sin * 0.072,
+    ]);
+  }
+
+  grayscale(value = 1) {
+    this.multiply([
+      0.2126 + 0.7874 * (1 - value),
+      0.7152 - 0.7152 * (1 - value),
+      0.0722 - 0.0722 * (1 - value),
+      0.2126 - 0.2126 * (1 - value),
+      0.7152 + 0.2848 * (1 - value),
+      0.0722 - 0.0722 * (1 - value),
+      0.2126 - 0.2126 * (1 - value),
+      0.7152 - 0.7152 * (1 - value),
+      0.0722 + 0.9278 * (1 - value),
+    ]);
+  }
+
+  sepia(value = 1) {
+    this.multiply([
+      0.393 + 0.607 * (1 - value),
+      0.769 - 0.769 * (1 - value),
+      0.189 - 0.189 * (1 - value),
+      0.349 - 0.349 * (1 - value),
+      0.686 + 0.314 * (1 - value),
+      0.168 - 0.168 * (1 - value),
+      0.272 - 0.272 * (1 - value),
+      0.534 - 0.534 * (1 - value),
+      0.131 + 0.869 * (1 - value),
+    ]);
+  }
+
+  saturate(value = 1) {
+    this.multiply([
+      0.213 + 0.787 * value,
+      0.715 - 0.715 * value,
+      0.072 - 0.072 * value,
+      0.213 - 0.213 * value,
+      0.715 + 0.285 * value,
+      0.072 - 0.072 * value,
+      0.213 - 0.213 * value,
+      0.715 - 0.715 * value,
+      0.072 + 0.928 * value,
+    ]);
+  }
+
+  multiply(matrix) {
+    const newR = this.clamp(this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2]);
+    const newG = this.clamp(this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5]);
+    const newB = this.clamp(this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8]);
+    this.r = newR;
+    this.g = newG;
+    this.b = newB;
+  }
+
+  brightness(value = 1) {
+    this.linear(value);
+  }
+  contrast(value = 1) {
+    this.linear(value, -(0.5 * value) + 0.5);
+  }
+
+  linear(slope = 1, intercept = 0) {
+    this.r = this.clamp(this.r * slope + intercept * 255);
+    this.g = this.clamp(this.g * slope + intercept * 255);
+    this.b = this.clamp(this.b * slope + intercept * 255);
+  }
+
+  invert(value = 1) {
+    this.r = this.clamp((value + this.r / 255 * (1 - 2 * value)) * 255);
+    this.g = this.clamp((value + this.g / 255 * (1 - 2 * value)) * 255);
+    this.b = this.clamp((value + this.b / 255 * (1 - 2 * value)) * 255);
+  }
+
+  hsl() {
+    // Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA.
+    const r = this.r / 255;
+    const g = this.g / 255;
+    const b = this.b / 255;
+    const max = Math.max(r, g, b);
+    const min = Math.min(r, g, b);
+    let h, s, l = (max + min) / 2;
+
+    if (max === min) {
+      h = s = 0;
+    } else {
+      const d = max - min;
+      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+      switch (max) {
+        case r:
+          h = (g - b) / d + (g < b ? 6 : 0);
+          break;
+
+        case g:
+          h = (b - r) / d + 2;
+          break;
+
+        case b:
+          h = (r - g) / d + 4;
+          break;
+      }
+      h /= 6;
+    }
+
+    return {
+      h: h * 100,
+      s: s * 100,
+      l: l * 100,
+    };
+  }
+
+  clamp(value) {
+    if (value > 255) {
+      value = 255;
+    } else if (value < 0) {
+      value = 0;
+    }
+    return value;
+  }
+}
+
+export class Solver {
+  constructor(target) {
+    this.target = target;
+    this.targetHSL = target.hsl();
+    this.reusedColor = new Color(0, 0, 0);
+  }
+
+  solve() {
+    const result = this.solveNarrow(this.solveWide());
+    return {
+      values: result.values,
+      loss: result.loss,
+      filter: this.css(result.values),
+    };
+  }
+
+  solveWide() {
+    const A = 5;
+    const c = 15;
+    const a = [60, 180, 18000, 600, 1.2, 1.2];
+
+    let best = { loss: Infinity };
+    for (let i = 0; best.loss > 25 && i < 3; i++) {
+      const initial = [50, 20, 3750, 50, 100, 100];
+      const result = this.spsa(A, a, c, initial, 1000);
+      if (result.loss < best.loss) {
+        best = result;
+      }
+    }
+    return best;
+  }
+
+  solveNarrow(wide) {
+    const A = wide.loss;
+    const c = 2;
+    const A1 = A + 1;
+    const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1];
+    return this.spsa(A, a, c, wide.values, 500);
+  }
+
+  spsa(A, a, c, values, iters) {
+    const alpha = 1;
+    const gamma = 0.16666666666666666;
+
+    let best = null;
+    let bestLoss = Infinity;
+    const deltas = new Array(6);
+    const highArgs = new Array(6);
+    const lowArgs = new Array(6);
+
+    for (let k = 0; k < iters; k++) {
+      const ck = c / Math.pow(k + 1, gamma);
+      for (let i = 0; i < 6; i++) {
+        deltas[i] = Math.random() > 0.5 ? 1 : -1;
+        highArgs[i] = values[i] + ck * deltas[i];
+        lowArgs[i] = values[i] - ck * deltas[i];
+      }
+
+      const lossDiff = this.loss(highArgs) - this.loss(lowArgs);
+      for (let i = 0; i < 6; i++) {
+        const g = lossDiff / (2 * ck) * deltas[i];
+        const ak = a[i] / Math.pow(A + k + 1, alpha);
+        values[i] = fix(values[i] - ak * g, i);
+      }
+
+      const loss = this.loss(values);
+      if (loss < bestLoss) {
+        best = values.slice(0);
+        bestLoss = loss;
+      }
+    }
+    return { values: best, loss: bestLoss };
+
+    function fix(value, idx) {
+      let max = 100;
+      if (idx === 2 /* saturate */) {
+        max = 7500;
+      } else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) {
+        max = 200;
+      }
+
+      if (idx === 3 /* hue-rotate */) {
+        if (value > max) {
+          value %= max;
+        } else if (value < 0) {
+          value = max + value % max;
+        }
+      } else if (value < 0) {
+        value = 0;
+      } else if (value > max) {
+        value = max;
+      }
+      return value;
+    }
+  }
+
+  loss(filters) {
+    // Argument is array of percentages.
+    const color = this.reusedColor;
+    color.set(0, 0, 0);
+
+    color.invert(filters[0] / 100);
+    color.sepia(filters[1] / 100);
+    color.saturate(filters[2] / 100);
+    color.hueRotate(filters[3] * 3.6);
+    color.brightness(filters[4] / 100);
+    color.contrast(filters[5] / 100);
+
+    const colorHSL = color.hsl();
+    return (
+      Math.abs(color.r - this.target.r) +
+      Math.abs(color.g - this.target.g) +
+      Math.abs(color.b - this.target.b) +
+      Math.abs(colorHSL.h - this.targetHSL.h) +
+      Math.abs(colorHSL.s - this.targetHSL.s) +
+      Math.abs(colorHSL.l - this.targetHSL.l)
+    );
+  }
+
+  css(filters) {
+    function fmt(idx, multiplier = 1) {
+      return Math.round(filters[idx] * multiplier);
+    }
+    return `invert(${fmt(0)}%) sepia(${fmt(1)}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(4)}%) contrast(${fmt(5)}%)`
+  }
+}
+
+function hexToRgb(hex): number[] {
+  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+  const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+  hex = hex.replace(shorthandRegex, (m, r, g, b) => {
+    return r + r + g + g + b + b;
+  });
+
+  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+  return result
+    ? [
+      parseInt(result[1], 16),
+      parseInt(result[2], 16),
+      parseInt(result[3], 16),
+    ]
+    : null;
+}
+
+export function getFiltersFromHex(hex): string {
+  const rgb = hexToRgb(hex);
+  if (!rgb) return ''
+
+  const [r, g, b] = rgb;
+  const color = new Color(r, g, b);
+  const solver = new Solver(color);
+  return solver.solve().filter;
+}
diff --git a/src/engine.tsx b/src/engine.tsx
index d3afec3b7..4e2c34fa7 100644
--- a/src/engine.tsx
+++ b/src/engine.tsx
@@ -44,6 +44,7 @@ import { AlertEvents } from "./ui/React/AlertManager";
 import { exceptionAlert } from "./utils/helpers/exceptionAlert";
 
 import { startExploits } from "./Exploits/loops";
+import { calculateAchievements } from "./Achievements/Achievements";
 
 import React from "react";
 import { setupUncaughtPromiseHandler } from "./UncaughtPromiseHandler";
@@ -65,6 +66,7 @@ const Engine: {
     messages: number;
     mechanicProcess: number;
     contractGeneration: number;
+    achievementsCounter: number;
   };
   decrementAllCounters: (numCycles?: number) => void;
   checkCounters: () => void;
@@ -163,6 +165,7 @@ const Engine: {
     messages: 150,
     mechanicProcess: 5, // Processes certain mechanics (Corporation, Bladeburner)
     contractGeneration: 3000, // Generate Coding Contracts
+    achievementsCounter: 300, // Check if we have new achievements
   },
 
   decrementAllCounters: function (numCycles = 1) {
@@ -234,6 +237,11 @@ const Engine: {
       }
       Engine.Counters.contractGeneration = 3000;
     }
+
+    if (Engine.Counters.achievementsCounter <= 0) {
+      calculateAchievements();
+      Engine.Counters.achievementsCounter = 300;
+    }
   },
 
   load: function (saveString) {
diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx
index 2fe3afc86..d78b53029 100644
--- a/src/ui/GameRoot.tsx
+++ b/src/ui/GameRoot.tsx
@@ -76,6 +76,7 @@ import { InvitationModal } from "../Faction/ui/InvitationModal";
 import { enterBitNode } from "../RedPill";
 import { Context } from "./Context";
 import { RecoveryMode, RecoveryRoot } from "./React/RecoveryRoot";
+import { AchievementsRoot } from "../Achievements/AchievementsRoot";
 
 const htmlLocation = location;
 
@@ -183,6 +184,9 @@ export let Router: IRouter = {
   toStaneksGift: () => {
     throw new Error("Router called before initialization");
   },
+  toAchievements: () => {
+    throw new Error("Router called before initialization");
+  }
 };
 
 function determineStartPage(player: IPlayer): Page {
@@ -287,6 +291,9 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
     toStaneksGift: () => {
       setPage(Page.StaneksGift);
     },
+    toAchievements: () => {
+      setPage(Page.Achievements);
+    },
   };
 
   useEffect(() => {
@@ -413,7 +420,9 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
                       Router.toTerminal();
                     }}
                   />
-                ) : (
+                ) : page === Page.Achievements ? (
+                  <AchievementsRoot />
+                )  : (
                   <>
                     <Typography>Cannot load</Typography>
                   </>
diff --git a/src/ui/Router.ts b/src/ui/Router.ts
index 6b09983bb..4056a44ac 100644
--- a/src/ui/Router.ts
+++ b/src/ui/Router.ts
@@ -36,6 +36,7 @@ export enum Page {
   Loading,
   StaneksGift,
   Recovery,
+  Achievements,
 }
 
 export interface ScriptEditorRouteOptions {
@@ -80,4 +81,5 @@ export interface IRouter {
   toBladeburnerCinematic(): void;
   toLocation(location: Location): void;
   toStaneksGift(): void;
+  toAchievements(): void;
 }
diff --git a/tools/README.md b/tools/README.md
index f29ebd87e..0f2e5f759 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -10,3 +10,13 @@ It decodes the save and prettifies the output. Canno be used to modify a save ga
 ```sh
 node ./pretty-save.js 'C:\\Users\\martin\\Desktop\\bitburnerSave_1641395736_BN12x14.json' 'C:\\Users\\martin\\Desktop\\pretty.json'
 ```
+
+## Fetch Steam Achievements Data
+
+Used to synchronize the achievements info in steamworks to the game's data.json
+
+**Usage**
+```sh
+# Get your key here: https://steamcommunity.com/dev/apikey
+node fetch-steam-achievements-data.js DEVKEYDEVKEYDEVKEYDEVKEY
+```
diff --git a/tools/fetch-steam-achievements-data.js b/tools/fetch-steam-achievements-data.js
new file mode 100644
index 000000000..aef79c8c3
--- /dev/null
+++ b/tools/fetch-steam-achievements-data.js
@@ -0,0 +1,69 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+const https = require('https')
+const fs = require('fs').promises;
+const path = require('path');
+
+const key = process.argv[2]
+
+function getRawJSON() {
+  return new Promise((resolve, reject) => {
+    const options = {
+      hostname: 'api.steampowered.com',
+      port: 443,
+      path: `/ISteamUserStats/GetSchemaForGame/v0002/?appid=1812820&key=${key}`,
+      method: 'GET',
+      headers: {
+        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
+        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
+      }
+    }
+
+    let data = [];
+    const req = https.request(options, res => {
+      console.log(`statusCode: ${res.statusCode}`)
+
+      res.on('data', chunk => {
+        data.push(chunk)
+      })
+
+      res.on('end', () => {
+        console.log('Response ended: ');
+        resolve(Buffer.concat(data).toString());
+      });
+    })
+
+    req.on('error', error => {
+      console.error(error)
+      req.end();
+      reject(error);
+    });
+
+    req.end();
+  });
+}
+
+async function fetchAchievementsData() {
+  const raw = await getRawJSON();
+  const o = JSON.parse(raw);
+  const achievements = {};
+  o.game.availableGameStats.achievements.forEach((a) => {
+    achievements[a.name] = {
+      ID: a.name,
+      Name: a.displayName,
+      Description: a.description,
+    };
+  })
+
+  const data = {
+    note: '***** Generated from a script, overwritten by steam achievements data *****',
+    fetchedOn: new Date().getTime(),
+    achievements,
+  }
+
+  const jsonPath = path.resolve(__dirname, '../src/Achievements/AchievementData.json');
+  await fs.writeFile(jsonPath, JSON.stringify(data, null, 2));
+  return data;
+}
+
+fetchAchievementsData().
+  then((json) => console.log(JSON.stringify(json, null, 2)));
diff --git a/tsconfig.json b/tsconfig.json
index fcf8643fb..3cfda7488 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,7 +9,8 @@
     "target": "es6",
     "sourceMap": true,
     "strict": true,
-    "types": ["cypress", "@testing-library/cypress", "node", "raw-loader.d.ts"]
+    "resolveJsonModule": true,
+    "types": ["cypress", "@testing-library/cypress", "node"]
   },
   "exclude": ["node_modules"]
 }
diff --git a/webpack.config.js b/webpack.config.js
index f9203a87f..2b72bb10e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -142,7 +142,7 @@ module.exports = (env, argv) => {
     module: {
       rules: [
         {
-          test: /\.(js|jsx|ts|tsx)$/,
+          test: /\.(js$|jsx|ts|tsx)$/,
           exclude: /node_modules/,
           use: {
             loader: "babel-loader",