diff --git a/AlphalandUtilityJsSource.txt b/AlphalandUtilityJsSource.txt
new file mode 100644
index 0000000..d3624ca
--- /dev/null
+++ b/AlphalandUtilityJsSource.txt
@@ -0,0 +1,273 @@
+/*
+ Alphaland JS Utilities 2021
+ I maintain all the code on Alphaland myself, so this is probably not the cleanest
+*/
+
+//utility for populating HTML with data from object OR calling a function with the objects current position and replacing the marker with returned data
+//[] for calling a function and replacing the marker with the return data (allows for more logic) (turned out to be incredibly useful)
+//{} for replacing the marker with the objects data
+//TODO: clean up?
+function parseHtml(html, limit, object, message, singleObject=false) {
+ var html_result = '';
+ var buffer = "";
+
+ for (var i = 0; i < limit; i++) {
+ if (singleObject) {
+ var objectData = object;
+ } else {
+ var objectData = object[i];
+ }
+
+ buffer = html;
+
+ //we have reached the end of the data available
+ if (objectData === undefined) {
+ break;
+ }
+
+ for (var pos = 0; pos <= html.length; pos++) {
+ if (html.charAt(pos) == "{") { //first position
+ for (var len = pos; len; len++) {
+ if (html.charAt(len) == "}") { //second position
+ var marker = "";
+ for (var d = pos; d < len+1; d++) { //data between the two positions
+ marker += html.charAt(d);
+ }
+
+ buffer = buffer.replace(marker, objectData[marker.substring(1, marker.length - 1)]); //using replace instead of replaceAll for compatibility
+ break;
+ }
+ }
+ }
+ else if (html.charAt(pos) == "[") { //first position
+ for (var len = pos; len; len++) {
+ if (html.charAt(len) == "]") { //second position
+ var marker = "";
+ for (var d = pos; d < len+1; d++) { //data between the two positions
+ marker += html.charAt(d);
+ }
+
+ var call = marker.substring(1, marker.length - 1); //grab the function name we wanna call
+ try {
+ call = window[call](objectData) //call the function with the object passed as a parameter
+ buffer = buffer.replace(marker, call); //replace the marker with the data returned from the call //using replace instead of replaceAll for compatibility
+ }
+ catch (error) {
+ //do nothing
+ }
+ break;
+ }
+ }
+ }
+ }
+ html_result += buffer;
+ }
+ if (html_result == "") {
+ html_result = message;
+ }
+ return html_result;
+}
+
+//http get json no cds
+function getJSON(url) {
+ return $.getJSON(url);
+}
+
+//http get json cds
+function getJSONCDS(url) {
+ return $.ajax(url, {
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true
+ });
+}
+
+//http post json cds
+function postJSONCDS(url, jsondata) {
+ return $.ajax({
+ type: 'POST',
+ url: url,
+ xhrFields: {
+ withCredentials: true
+ },
+ crossDomain: true,
+ data: jsondata,
+ dataType: 'json',
+ });
+}
+
+//pretty ghetto but is incredibly useful for multi page helper, ex output: ,1,"ass",2
+function parseArrayArgs(args) {
+ var parsed = ",";
+ for (const arg of args) {
+ if (typeof arg == "string") {
+ parsed += "'"+arg+"',";
+ } else {
+ parsed += arg+",";
+ }
+ }
+ return parsed.substring(0, parsed.length - 1); //remove last comma
+}
+
+//utility is for making pages easier
+function staticPageHelper(api, loadingurl, container, html, page, limit, keyword, message, optionalArgs = "") {
+ if (loadingurl !== "") {
+ var loadingHtml = '