diff --git a/apps/frontend-masters-bootcamp/src/lessons/forms/css/forms.css b/apps/frontend-masters-bootcamp/src/lessons/forms/css/forms.css
new file mode 100644
index 0000000..d4a193a
--- /dev/null
+++ b/apps/frontend-masters-bootcamp/src/lessons/forms/css/forms.css
@@ -0,0 +1,37 @@
+html {
+ box-sizing: border-box;
+}
+
+*, *:before, *:after {
+ box-sizing: inherit;
+}
+
+body {
+ font-family: Arial, Helvetica, sans-serif;
+ margin: 0;
+ padding: 0;
+ background-image: url('../img/galaxy.jpg');
+ color: white;
+}
+
+.wrapper {
+ width: 80%;
+ margin: 0 auto;
+ padding: 1em;
+ display: flex;
+ flex-flow: row nowrap;
+}
+
+p {
+ margin-bottom: 0;
+ margin-top: 2rem;
+}
+
+section {
+ flex-basis: 57%;
+ margin-right: 10%;
+}
+
+aside {
+ flex-basis: 33%;
+}
\ No newline at end of file
diff --git a/apps/frontend-masters-bootcamp/src/lessons/forms/forms.html b/apps/frontend-masters-bootcamp/src/lessons/forms/forms.html
new file mode 100644
index 0000000..5602fc9
--- /dev/null
+++ b/apps/frontend-masters-bootcamp/src/lessons/forms/forms.html
@@ -0,0 +1,87 @@
+
+
+
+
+
+ Alien Abduction Order Form
+
+
+
+
+
+
+
+ Alien Abduction Order Form
+ Fill out the form below to place an order for an alien abduction by one of our fine UFOs.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/frontend-masters-bootcamp/src/lessons/forms/img/galaxy.jpg b/apps/frontend-masters-bootcamp/src/lessons/forms/img/galaxy.jpg
new file mode 100644
index 0000000..3c9a7b2
Binary files /dev/null and b/apps/frontend-masters-bootcamp/src/lessons/forms/img/galaxy.jpg differ
diff --git a/apps/frontend-masters-bootcamp/src/lessons/forms/img/image credit.rtf b/apps/frontend-masters-bootcamp/src/lessons/forms/img/image credit.rtf
new file mode 100644
index 0000000..31f620c
--- /dev/null
+++ b/apps/frontend-masters-bootcamp/src/lessons/forms/img/image credit.rtf
@@ -0,0 +1,10 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+{\*\expandedcolortbl;;}
+\margl1440\margr1440\vieww10800\viewh8400\viewkind0
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
+
+\f0\fs24 \cf0 https://images.nasa.gov/details-GSFC_20171208_Archive_e000056.html\
+\
+Photo caption: Galaxy cluster Abell 370 contains several hundred galaxies tied together by the mutual pull of gravity. Photographed in a combination of visible and near-infrared light, the brightest and largest galaxies are the yellow-white, massive, elliptical galaxies containing many hundreds of billions of stars each. Spiral galaxies have younger populations of stars and are bluish. Mysterious-looking arcs of blue light are distorted images of remote galaxies behind the cluster. The cluster acts as a huge lens in space that magnifies and stretches images of background galaxies like a funhouse mirror. Photo Credit: NASA, ESA, and J. Lotz and the HFF Team (STScI).}
\ No newline at end of file
diff --git a/apps/frontend-masters-bootcamp/src/lessons/forms/js/forms.js b/apps/frontend-masters-bootcamp/src/lessons/forms/js/forms.js
new file mode 100644
index 0000000..42159f0
--- /dev/null
+++ b/apps/frontend-masters-bootcamp/src/lessons/forms/js/forms.js
@@ -0,0 +1,104 @@
+var form = document.getElementsByTagName("form")[0];
+
+form.addEventListener("submit", function(e) {
+ console.log('hello')
+ console.log({ form: new FormData(e.target)});
+ e.preventDefault();
+ sendData(e);
+});
+
+// https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript
+function sendData(e) {
+ var XHR = new XMLHttpRequest();
+ const formData = new FormData(e.target)
+ var urlEncodedDataPairs = Array.from(formData.entries()).map(d => d.join('='));
+
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("name") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='name']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("send_to") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='send_to']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("email") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='email']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("phone") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='phone']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("date") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='date']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("qty") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='qty']").value)
+ // );
+
+ // // radio buttons
+ // let radio = document.getElementsByName("ufotype");
+ // for (var i = 0, length = radio.length; i < length; i++) {
+ // if (radio[i].checked) {
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("ufotype") + "=" + encodeURIComponent(radio[i].value)
+ // );
+ // }
+ // }
+
+ // // dropdown menu
+ // var dropdown = form.querySelector("[name='abtype']");
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("abtype") +
+ // "=" +
+ // encodeURIComponent(dropdown.options[dropdown.selectedIndex].text)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("comments") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='comments']").value)
+ // );
+ // urlEncodedDataPairs.push(
+ // encodeURIComponent("subscribe") +
+ // "=" +
+ // encodeURIComponent(form.querySelector("[name='subscribe']").checked)
+ // );
+
+ // Combine the pairs into a single string and replace all %-encoded spaces to
+ // the '+' character; matches the behaviour of browser form submissions.
+ const urlEncodedData = urlEncodedDataPairs.join("&").replace(/%20/g, "+");
+
+ // Define what happens on successful data submission
+ XHR.addEventListener("load", function(event) {
+ if (XHR.readyState === XHR.DONE) {
+ if (XHR.status === 200) {
+ alert("Your order has been received! Check your email.");
+ } else {
+ alert("Oh oh! We have a problem! " + XHR.responseText + ".");
+ }
+ }
+ });
+
+ // Define what happens in case of error
+ XHR.addEventListener("error", function(event) {
+ // This is normally a timeout or connection error.
+ alert("Oops! Something went wrong.");
+ });
+
+ // Set up our request
+ XHR.open(form.getAttribute("method"), form.getAttribute("action"));
+
+ // Add the required HTTP header for form data POST requests
+ XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+ // Finally, send our data.
+ XHR.send(urlEncodedData);
+}