diff --git a/notes/time_report.md b/notes/time_report.md
index 31bd396..6870b8c 100644
--- a/notes/time_report.md
+++ b/notes/time_report.md
@@ -125,3 +125,14 @@
* Adjust header and crc size
* Clear up CRC error correction rate
* Add glossary
+
+# 2022-11-04
+* Meeting with Expert
+ * Defense: 27.01.2023 10:30 - 11:30
+ * Describe pro and cons of other NFC methods
+
+# 2022-11-09+
+* Developing website
+
+# 2022-11-21
+* Cleanup and finish up website
diff --git a/src/.editorconfig b/src/.editorconfig
new file mode 100644
index 0000000..f9726f7
--- /dev/null
+++ b/src/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+max_line_length = 120
+end_of_line = lf
+insert_final_newline = true
diff --git a/src/website/index.html b/src/website/index.html
new file mode 100644
index 0000000..05ac104
--- /dev/null
+++ b/src/website/index.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/website/scripts/Constants.js b/src/website/scripts/Constants.js
new file mode 100644
index 0000000..a5267b5
--- /dev/null
+++ b/src/website/scripts/Constants.js
@@ -0,0 +1,13 @@
+/**
+ * The amount of time in ms a bit takes to transmit.
+ *
+ * @type {Number}
+ */
+const CLOCK_TIME = 500;
+
+/**
+ * The preamble that is sent before the packet.
+ *
+ * @type {Number[]}
+ */
+const PREAMBLE = [1, 1, 1, 0, 0, 0, 1, 1, 1];
diff --git a/src/website/scripts/Packet.js b/src/website/scripts/Packet.js
new file mode 100644
index 0000000..f30d5d1
--- /dev/null
+++ b/src/website/scripts/Packet.js
@@ -0,0 +1,99 @@
+
+/**
+ *
+ */
+class Packet {
+ /**
+ * The header is a nibble that contains the length of the payload in
+ * bytes.
+ *
+ * @type {Number[]}
+ */
+ #header = [];
+
+ /**
+ * The payload of the packet. This can be up to 16 bytes in length.
+ *
+ * @type {Number[]}
+ */
+ #payload = [];
+
+ /**
+ * The checksum of the payload.
+ *
+ * @type {Number[]}
+ */
+ #checksum = [];
+
+ /**
+ * @param {String} payloadText
+ */
+ constructor(payloadText) {
+ this.#header = this.#numberToBitArray(payloadText.length, 4);
+ this.#payload = this.#textToBitArray(payloadText);
+ this.#checksum = this.#calculateChecksum(this.#textToCodePoints(payloadText));
+ }
+
+ /**
+ * This methods turns a number into an array of bits of the size
+ * denoted by length.
+ *
+ * @param {Number} number
+ * @param {Number} length
+ * @return {Number[]}
+ */
+ #numberToBitArray(number, length) {
+ const bitArray = [];
+ for (var i = length - 1; i >= 0; i--) {
+ let bit = number & (1 << i);
+ bit = bit ? 1 : 0;
+ bitArray.push(bit);
+ }
+ return bitArray;
+ }
+
+ /**
+ * Turn a string into an array of ASCII code points.
+ *
+ * @param {String} text
+ * @return {Number[]}
+ */
+ #textToCodePoints(text) {
+ const codePoints = [];
+ for (let i = 0; i < text.length; i++) {
+ codePoints.push(text.charCodeAt(i));
+ }
+ return codePoints;
+ }
+
+ /**
+ * Turn a string into an bit array.
+ *
+ * @param {String} text
+ * @return {Number[]}
+ */
+ #textToBitArray(text) {
+ const codePoints = this.#textToCodePoints(text);
+ let bitArray = [];
+ for (const codePoint of codePoints) {
+ bitArray = bitArray.concat(this.#numberToBitArray(codePoint, 8));
+ }
+ return bitArray;
+ }
+
+ /**
+ * Calculate the checksum of the given array of bytes and return it
+ * as an bit array.
+ *
+ * @param {Number[]} bytes
+ * @return {Number[]}
+ */
+ #calculateChecksum(bytes) {
+ const checksum = Utility.crc8Autosar(bytes);
+ return this.#numberToBitArray(checksum, 8);
+ }
+
+ getData() {
+ return [...this.#header, ...this.#payload, ...this.#checksum];
+ }
+}
diff --git a/src/website/scripts/Utility.js b/src/website/scripts/Utility.js
new file mode 100644
index 0000000..1f23cce
--- /dev/null
+++ b/src/website/scripts/Utility.js
@@ -0,0 +1,73 @@
+const logParagraph = document.getElementById("log");
+
+class Utility {
+ /**
+ * This method calculates the CRC-8-AUTOSAR checksum of the given
+ * array of bytes.
+ *
+ * This code is based on the code examples from the following page:
+ * http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html
+ *
+ * The specifics of the algorithm is coming from the AUTOSAR CRC specification:
+ * https://www.autosar.org/fileadmin/user_upload/standards/classic/21-11/AUTOSAR_SWS_CRCLibrary.pdf
+ *
+ * > Utility.crc8([0x0, 0x0, 0x0, 0x0]).toString(16)
+ * "12"
+ * > Utility.crc8([0xF2, 0x01, 0x83]).toString(16)
+ * "c2"
+ * > Utility.crc8([0x0F, 0xAA, 0x00, 0x55]).toString(16)
+ * "c6"
+ * > Utility.crc8([0x00, 0xff, 0x55, 0x11]).toString(16)
+ * "77"
+ * > Utility.crc8([0x33, 0x22, 0x55, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]).toString(16)
+ * "11"
+ * > Utility.crc8([0x92, 0x6b, 0x55]).toString(16)
+ * "33"
+ * > Utility.crc8([0xff, 0xff, 0xff, 0xff]).toString(16)
+ * "6c"
+ *
+ * @param {Number[]} bytes
+ * @return {Number}
+ */
+ static crc8Autosar(bytes) {
+ const polynomial = 0x2f;
+ const xorOut = 0xff;
+ let crc = 0xff;
+
+ for (const byte of bytes) {
+ crc ^= byte;
+
+ for (let i = 0; i < 8; i++) {
+ if ((crc & 0x80) != 0) {
+ crc = ((crc << 1) ^ polynomial) & 0xff;
+ } else {
+ crc <<= 1;
+ }
+ }
+ }
+
+ return crc ^ xorOut;
+ }
+
+ /**
+ * Take a bit array and encode the contents using manchester encoding.
+ *
+ * @param {Number[]} bitArray
+ * @return {Number[]}
+ */
+ static manchesterEncode(bitArray) {
+ const encodedBits = [];
+
+ for (const bit of bitArray) {
+ encodedBits.push(bit ^ 1);
+ encodedBits.push(bit ^ 0);
+ }
+
+ return encodedBits;
+ }
+
+ static log(text) {
+ //logParagraph.innerHTML = `${text}
${logParagraph.innerHTML}`;
+ console.log(text);
+ }
+}
diff --git a/src/website/scripts/Worker.js b/src/website/scripts/Worker.js
new file mode 100644
index 0000000..1fa180e
--- /dev/null
+++ b/src/website/scripts/Worker.js
@@ -0,0 +1 @@
+while (true) {}
diff --git a/src/website/styles/main.css b/src/website/styles/main.css
new file mode 100644
index 0000000..fcc9069
--- /dev/null
+++ b/src/website/styles/main.css
@@ -0,0 +1,75 @@
+:root {
+ --spacing: 12px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: sans-serif;
+}
+
+main {
+ width: 100%;
+ max-width: 400px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+input {
+ width: 100%;
+}
+
+#message {
+ position: relative;
+}
+
+#log {
+ height: 300px;
+ font-size: 0.8rem;
+ overflow: scroll;
+}
+
+.buttons {
+ width: 100%;
+ display: flex;
+ gap: var(--spacing);
+}
+
+button {
+ width: 100%;
+ display: block;
+}
+
+.hide {
+ display: none;
+}
+
+/*https://loading.io/css/*/
+#message:not(:empty):after {
+ content: " ";
+ display: block;
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ border: 2px solid black;
+ border-color: black transparent black transparent;
+ animation: loading-indicator 1.2s linear infinite;
+ right: 0;
+ top: 0;
+ position: absolute;
+}
+
+@keyframes loading-indicator {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}