diff --git a/src/components/ImageUpload.vue b/src/components/ImageUpload.vue
index 8ee4ad45f2296097ef58ff6b336f4f7e9fbe1221..1adc2293e8be2febdefafcced503c01cb967d0e4 100644
--- a/src/components/ImageUpload.vue
+++ b/src/components/ImageUpload.vue
@@ -1,5 +1,46 @@
 <template>
   <div>
+    <div class="m-2">
+      Click on the image's preview to remove the entry from uploading
+    </div>
+    <div
+      v-for="(image, id) in imageList"
+      :key="image.url"
+      class="flex flex-row"
+    >
+      <img
+        :src="image.url"
+        @click="removeImage(id)"
+        alt=""
+        class="max-w-xs m-4"
+      />
+      <form :id="'image-update-form-' + id" class="flex flex-col">
+        <input
+          type="text"
+          placeholder="Source"
+          name="source"
+          class="payloadInput"
+        />
+        <input
+          type="text"
+          placeholder="Parent"
+          name="parent"
+          class="payloadInput"
+        />
+        <textarea
+          type="text"
+          placeholder="Commentary"
+          name="commentary"
+          class="payloadInput"
+        />
+        <textarea
+          type="text"
+          placeholder="Commentary translation"
+          name="commentary_translation"
+          class="payloadInput"
+        />
+      </form>
+    </div>
     <div
       class="h-48 m-4 border-dotted border-4 border-gray-400"
       @drop.prevent="
@@ -20,7 +61,6 @@
           class="h-full w-full opacity-0 absolute z-10 cursor-pointer"
         />
         <div
-          v-show="!imageList.length"
           class="
             h-full
             font-semibold
@@ -32,19 +72,6 @@
         >
           Drag and drop images here or click here to browse.
         </div>
-        <div
-          v-show="imageList.length"
-          class="h-full flex flex-row flex-wrap content-start overflow-y-auto"
-        >
-          <img
-            v-for="(preview, index) in previews"
-            :key="index"
-            :src="preview.url"
-            @click="removeImage(preview.image)"
-            alt=""
-            class="max-h-28 relative z-10"
-          />
-        </div>
       </div>
     </div>
     <div class="flex flex-col items-center m-4">
@@ -61,7 +88,8 @@
           mx-auto
           font-semibold
           text-gray-800
-          hover:bg-gray-800 hover:text-gray-100
+          hover:bg-gray-800
+          hover:text-gray-100
         "
       >
         Submit
@@ -85,13 +113,6 @@ export default {
     };
   },
   computed: {
-    previews: function () {
-      let tempArray = [];
-      this.imageList.forEach((image) =>
-        tempArray.push({ url: URL.createObjectURL(image), image })
-      );
-      return tempArray;
-    },
     ...mapState(["stateUser"]),
   },
   methods: {
@@ -102,9 +123,18 @@ export default {
     },
     updateImageList(event) {
       this.imageList = this.imageList.concat(
-        event ? [...event.dataTransfer.files] : [...this.$refs.imageInput.files]
+        event
+          ? this.addMetadata([...event.dataTransfer.files])
+          : this.addMetadata([...this.$refs.imageInput.files])
       );
     },
+    addMetadata(files) {
+      let tempArray = [];
+      files.forEach((file) => {
+        tempArray.push({ file, url: URL.createObjectURL(file) });
+      });
+      return tempArray;
+    },
     checkImageType(event) {
       const acceptedTypes = ["image/png", "image/jpeg", "image/gif"];
       let imageList = event
@@ -119,36 +149,59 @@ export default {
       this.invalidType = false;
       return true;
     },
-    removeImage(image) {
-      this.imageList.splice(this.imageList.indexOf(image), 1);
+    removeImage(id) {
+      this.imageList.splice(id, 1);
     },
-    submitImage() {
+    async submitImage() {
       let formData = new FormData();
       for (let i = 0; i < this.imageList.length; i++) {
-        formData.set("image", this.imageList[i]);
-        this.postImage(formData);
+        formData.set("image", this.imageList[i].file);
+        let data = await this.postImage(formData);
+        this.updateImage(
+          data.snowflake,
+          this.serializeForm("image-update-form-" + i)
+        );
       }
       // Clean up
       this.invalidType = false;
       this.imageList = [];
     },
+    // Serialize form inputs into JSON object that can be sent to API
+    serializeForm(formID) {
+      return JSON.stringify(
+        Object.fromEntries(new FormData(document.getElementById(formID)))
+      );
+    },
+    async updateImage(flake, imageUpdatePayload) {
+      const options = {
+        method: "PATCH",
+        headers: {
+          secret: this.stateUser.secret,
+        },
+        body: imageUpdatePayload,
+      };
+      await fetch(`/api/image/${flake}`, options);
+    },
     async postImage(fd) {
-      try {
-        const options = {
-          method: "POST",
-          headers: {
-            secret: this.stateUser.secret,
-          },
-          body: fd,
-        };
-        const response = await fetch("/api/image", options);
-        const data = await response.json();
-        this.addStateImageSnowflake(data.snowflake);
-      } catch {
-        (error) => console.error(error);
-      }
+      const options = {
+        method: "POST",
+        headers: {
+          secret: this.stateUser.secret,
+        },
+        body: fd,
+      };
+      const response = await fetch("/api/image", options);
+      const data = await response.json();
+      this.addStateImageSnowflake(data.snowflake);
+      return data;
     },
     ...mapActions(["addStateImageSnowflake"]),
   },
 };
 </script>
+
+<style>
+.payloadInput {
+  @apply border-2 focus:outline-none focus:ring-2 focus:ring-blue-300 pl-1 my-2;
+}
+</style>
\ No newline at end of file