diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 0000000..a95c854
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,4 @@
+# supported browsers
+
+defaults
+not ie > 0
diff --git a/LICENSE b/LICENSE
index f5e88cb..69e15de 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2022 Magrathea
+Copyright (c) 2022 Magrathea (https://github.com/magratheaguide).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4501302
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Huningto: Discord Messages via Webhook
+
+> In the _Mass Effect_ series, Huningto is a planet with a magnetic field so strong, it "creates strong radio interference throughout the inner system" (["Huningto," Mass Effect Wiki](https://masseffect.fandom.com/wiki/Huningto)).
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..a1a6c4a
--- /dev/null
+++ b/index.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+ Huningto: Discord Messages via Webhook, A Magrathea Project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/dependent-fields.js b/js/dependent-fields.js
new file mode 100644
index 0000000..09dc1eb
--- /dev/null
+++ b/js/dependent-fields.js
@@ -0,0 +1,30 @@
+"use strict";
+
+(function () {
+ const form = document.querySelector("form");
+
+ const dependencyTriggers = form.querySelectorAll("input.js-dependency");
+ const dependencyFollowers = form.querySelectorAll(".js-dependency:not(input)");
+
+ dependencyTriggers.forEach(trigger => {
+ // consider initial states
+ if (trigger.checked) {
+ updateDependencyFollowers(trigger.name, trigger.value);
+ }
+
+ // update on change
+ trigger.addEventListener("change", () => {
+ updateDependencyFollowers(trigger.name, trigger.value, trigger.checked);
+ });
+ });
+
+ function updateDependencyFollowers(key, value, checked = true) {
+ dependencyFollowers.forEach(follower => {
+ if (follower.dataset[key]) {
+ if (checked && follower.dataset[key] == value) follower.removeAttribute("hidden");
+ else follower.setAttribute("hidden", "");
+ }
+ });
+ }
+})();
+
\ No newline at end of file
diff --git a/js/main.js b/js/main.js
new file mode 100644
index 0000000..f8f6310
--- /dev/null
+++ b/js/main.js
@@ -0,0 +1,73 @@
+"use strict";
+
+(function () {
+ const form = document.querySelector("form");
+ const output = document.querySelector("output");
+
+ form.addEventListener("submit", event => {
+ event.preventDefault();
+
+ let submitButton = form.querySelector("button[type='submit']");
+ let url = constructUrl(form.elements);
+ let body = new FormData();
+
+ output.value = "";
+ submitButton.setAttribute("disabled", "");
+
+ // TODO: Need to teach this how to check dependent fields
+ if (form.elements.buildFrom.value === "json") {
+ body.append("payload_json", form.elements.payload_json.value);
+ } else {
+ body.append("content", form.elements.content.value);
+ }
+
+ fetch(url, {
+ body: body,
+ method: "POST"
+ }).then(response => {
+ console.log(response);
+
+ displayResponse(response);
+ });
+
+ submitButton.removeAttribute("disabled");
+ });
+
+ function constructUrl(elements) {
+ let baseUrl = elements.action.value;
+ let threadId = elements.thread_id.value.trim();
+
+ if (threadId) {
+ return `${ baseUrl }?thread_id=${ threadId }`;
+ }
+
+ return baseUrl;
+ }
+
+ function displayResponse(response) {
+ if (response.ok) {
+ linebreak(output);
+ output.value = ("Message sent successfully");
+ } else {
+ output.value = (`HTTP Status Code ${ response.status }: ${ response.statusText }`);
+
+ response.text().then(text => {
+ try {
+ let json = JSON.parse(text);
+
+ for (const [key, value] of Object.entries(json)) {
+ linebreak(output);
+ output.append(`${ key }: ${ value }`);
+ }
+ } catch {
+ linebreak(output);
+ output.append(text);
+ }
+ });
+ }
+ }
+
+ function linebreak(element) {
+ element.append(document.createElement("br"));
+ }
+})();
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..e736fc9
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,62 @@
+:root {
+ --border: 2px dotted var(--color-grey);
+
+ --color-grey: hsl(0deg 0% 50%);
+}
+
+body {
+ margin-inline: auto;
+ max-width: 65ch;
+ min-height: 100%;
+ padding: 2em;
+}
+
+fieldset {
+ display: grid;
+ gap: 1em;
+ grid-template-columns: [input] auto [label] 1fr;
+ padding-block: 1em;
+}
+
+fieldset input {
+ grid-column: input;
+}
+
+fieldset label {
+ grid-column: label;
+}
+
+footer {
+ border-block-start: var(--border);
+ padding-block-start: 1em;
+ text-align: center;
+}
+
+form button {
+ min-inline-size: 15ch;
+}
+
+form p {
+ display: flex;
+ flex-direction: column;
+}
+
+header {
+ border-block-end: var(--border);
+ padding-block-end: 1em;
+ text-align: center;
+}
+
+hr {
+ border: none;
+ border-block-start: var(--border);
+ margin-block: 2em;
+}
+
+[hidden] {
+ display: none;
+}
+
+.flow > * + * {
+ margin-block-start: var(--flow-space, 1em);
+}