diff --git a/src/blog.py b/src/blog.py
new file mode 100644
index 0000000..1d409c5
--- /dev/null
+++ b/src/blog.py
@@ -0,0 +1,18 @@
+from os import getenv as env
+import psycopg2, logging
+
+
+log = logging.getLogger("blog")
+
+
+log.info("connecting to database")
+conn = psycopg2.connect(
+ host = env("PG_HOST"),
+ port = env("PG_PORT"),
+ dbname = env("PG_DBNAME"),
+ user= env("PG_USER"),
+ password = env("PG_PASSWORD")
+)
+cursor = conn.cursor()
+
+
diff --git a/static/js/furnix_widget.js b/static/js/furnix_widget.js
new file mode 100644
index 0000000..2b49a3c
--- /dev/null
+++ b/static/js/furnix_widget.js
@@ -0,0 +1,76 @@
+// onionring.js is made up of four files - onionring-widget.js (this one!), onionring-index.js, onionring-variables.js and onionring.css
+// it's licensed under the cooperative non-violent license (CNPL) v4+ (https://thufie.lain.haus/NPL.html)
+// it was originally made by joey + mord of allium (蒜) house, last updated 2020-11-24
+
+// === ONIONRING-WIDGET ===
+//this file contains the code which builds the widget shown on each page in the ring. ctrl+f 'EDIT THIS' if you're looking to change the actual html of the widget
+
+var tag = document.getElementById(ringID); //find the widget on the page
+
+thisSite = window.location.href; //get the url of the site we're currently on
+thisIndex = null;
+
+// FIX
+thisSite = thisSite.replace("alfieking.dev", "proot.uk"); // fix domain
+thisSite = thisSite.replace("http:\/\/127.0.0.1:5000", "https:\/\/proot.uk"); // For debug purposes
+
+// go through the site list to see if this site is on it and find its position
+for (i = 0; i < sites.length; i++) {
+ if (thisSite.startsWith(sites[i])) { //we use startswith so this will match any subdirectory, users can put the widget on multiple pages
+ thisIndex = i;
+ break; //when we've found the site, we don't need to search any more, so stop the loop
+ }
+}
+
+function randomSite() {
+ otherSites = sites.slice(); //create a copy of the sites list
+ otherSites.splice(thisIndex, 1); //remove the current site so we don't just land on it again
+ randomIndex = Math.floor(Math.random() * otherSites.length);
+ location.href = otherSites[randomIndex];
+}
+
+//if we didn't find the site in the list, the widget displays a warning instead
+if (thisIndex == null) {
+ tag.insertAdjacentHTML('afterbegin', `
+
+
+
This site isn't part of the ${ringName} webring yet 😿
+
+
+ `);
+}
+else {
+ //find the 'next' and 'previous' sites in the ring. this code looks complex
+ //because it's using a shorthand version of an if-else statement to make sure
+ //the first and last sites in the ring join together correctly
+ previousIndex = (thisIndex-1 < 0) ? sites.length-1 : thisIndex-1;
+ nextIndex = (thisIndex+1 >= sites.length) ? 0 : thisIndex+1;
+
+ indexText = ""
+ //if you've chosen to include an index, this builds the link to that
+ if (useIndex) {
+ indexText = `index | `;
+ }
+
+ randomText = ""
+ //if you've chosen to include a random button, this builds the link that does that
+ if (useRandom) {
+ randomText = `random | `;
+ }
+
+ //this is the code that displays the widget - EDIT THIS if you want to change the structure
+ tag.insertAdjacentHTML('afterbegin', `
+
+ `);
+
+}
diff --git a/static/js/ultraring_widget.js b/static/js/ultraring_widget.js
new file mode 100644
index 0000000..aef961b
--- /dev/null
+++ b/static/js/ultraring_widget.js
@@ -0,0 +1,78 @@
+//YELLOW TERMINAL
+
+// onionring.js is made up of four files - onionring-widget.js (this one!), onionring-index.js, onionring-variables.js and onionring.css
+// it's licensed under the cooperative non-violent license (CNPL) v4+ (https://thufie.lain.haus/NPL.html)
+// it was originally made by joey + mord of allium (蒜) house, last updated 2020-11-24
+
+// === ONIONRING-WIDGET ===
+//this file contains the code which builds the widget shown on each page in the ring. ctrl+f 'EDIT THIS' if you're looking to change the actual html of the widget
+
+var tag = document.getElementById(ringID); //find the widget on the page
+
+thisSite = window.location.href; //get the url of the site we're currently on
+thisIndex = null;
+
+// FIX
+thisSite = thisSite.replace("alfieking.dev", "proot.uk"); // fix domain
+thisSite = thisSite.replace("http:\/\/127.0.0.1:5000", "https:\/\/proot.uk"); // For debug purposes
+
+// go through the site list to see if this site is on it and find its position
+for (i = 0; i < sites.length; i++) {
+ if (thisSite.startsWith(sites[i])) { //we use startswith so this will match any subdirectory, users can put the widget on multiple pages
+ thisIndex = i;
+ break; //when we've found the site, we don't need to search any more, so stop the loop
+ }
+}
+
+function randomUltraRingSite() {
+ otherSites = sites.slice(); //create a copy of the sites list
+ otherSites.splice(thisIndex, 1); //remove the current site so we don't just land on it again
+ randomIndex = Math.floor(Math.random() * otherSites.length);
+ location.href = otherSites[randomIndex];
+}
+
+//if we didn't find the site in the list, the widget displays a warning instead
+if (thisIndex == null) {
+ tag.insertAdjacentHTML('afterbegin', `
+
+ `);
+}
+else {
+ //find the 'next' and 'previous' sites in the ring. this code looks complex
+ //because it's using a shorthand version of an if-else statement to make sure
+ //the first and last sites in the ring join together correctly
+ previousIndex = (thisIndex-1 < 0) ? sites.length-1 : thisIndex-1;
+ nextIndex = (thisIndex+1 >= sites.length) ? 0 : thisIndex+1;
+
+ indexText = ""
+ //if you've chosen to include an index, this builds the link to that
+ if (useIndex) {
+ indexText = `[INDEX] | `;
+ }
+
+ randomText = ""
+ //if you've chosen to include a random button, this builds the link that does that
+ if (useRandom) {
+ randomText = `[RANDOM]`;
+ }
+
+ //this is the code that displays the widget - EDIT THIS if you want to change the structure
+ tag.insertAdjacentHTML('afterbegin', `
+
+