diff --git a/.gitignore b/.gitignore
index 8e166d0..e4b2530 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,28 +1,28 @@
-# Node Modules
-node_modules
-
-# Local ENV files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-
-# Editor Directories/Files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
-.DS_Store
-
-yarn.lock
-
-# Custom
-.env
+# Node Modules
+node_modules
+
+# Local ENV files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor Directories/Files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+.DS_Store
+
+yarn.lock
+
+# Custom
+.env
config/config.json
\ No newline at end of file
diff --git a/package.json b/package.json
index 5a86df1..946d991 100644
--- a/package.json
+++ b/package.json
@@ -1,41 +1,41 @@
-{
- "name": "jays-host",
- "version": "1.0.0",
- "description": "A ShareX photo gallery.",
- "main": "index.js",
- "scripts": {
- "serve": "nodemon --ignore ./ui/"
- },
- "author": "Troplo",
- "license": "Internal use only.",
- "private": true,
- "dependencies": {
- "@discordjs/rest": "^0.1.0-canary.0",
- "axios": "^0.21.1",
- "bcryptjs": "^2.4.3",
- "body-parser": "^1.19.0",
- "btcpay": "^0.2.5",
- "btoa": "^1.2.1",
- "cloudflare": "^2.8.0",
- "cors": "^2.8.5",
- "crypto-random-string": "3.3.1",
- "discord.js": "^13.1.0",
- "dotenv": "^10.0.0",
- "express": "^4.17.1",
- "express-autosanitizer": "^1.0.2",
- "form-data": "^4.0.0",
- "helmet": "^4.6.0",
- "is-valid-domain": "^0.1.2",
- "jsonwebtoken": "^8.5.1",
- "jw-paginate": "^1.0.4",
- "microstats": "^0.1.2",
- "moment": "^2.29.1",
- "multer": "^1.4.2",
- "mysql2": "^2.2.5",
- "nodemon": "^2.0.12",
- "sequelize": "^6.6.5",
- "sequelize-cli": "^6.2.0",
- "speakeasy": "^2.0.0",
- "whois": "^2.13.5"
- }
-}
+{
+ "name": "jays-host",
+ "version": "1.0.0",
+ "description": "A ShareX photo gallery.",
+ "main": "index.js",
+ "scripts": {
+ "serve": "nodemon --ignore ./ui/"
+ },
+ "author": "Troplo",
+ "license": "Internal use only.",
+ "private": true,
+ "dependencies": {
+ "@discordjs/rest": "^0.1.0-canary.0",
+ "axios": "^0.21.1",
+ "bcryptjs": "^2.4.3",
+ "body-parser": "^1.19.0",
+ "btcpay": "^0.2.5",
+ "btoa": "^1.2.1",
+ "cloudflare": "^2.8.0",
+ "cors": "^2.8.5",
+ "crypto-random-string": "3.3.1",
+ "discord.js": "^13.1.0",
+ "dotenv": "^10.0.0",
+ "express": "^4.17.1",
+ "express-autosanitizer": "^1.0.2",
+ "form-data": "^4.0.0",
+ "helmet": "^4.6.0",
+ "is-valid-domain": "^0.1.2",
+ "jsonwebtoken": "^8.5.1",
+ "jw-paginate": "^1.0.4",
+ "microstats": "^0.1.2",
+ "moment": "^2.29.1",
+ "multer": "^1.4.2",
+ "mysql2": "^2.2.5",
+ "nodemon": "^2.0.12",
+ "sequelize": "^6.6.5",
+ "sequelize-cli": "^6.2.0",
+ "speakeasy": "^2.0.0",
+ "whois": "^2.13.5"
+ }
+}
diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js
index 8ad90db..44b5ddd 100644
--- a/ui/.eslintrc.js
+++ b/ui/.eslintrc.js
@@ -1,17 +1,17 @@
-module.exports = {
- root: true,
- env: {
- node: true
- },
- 'extends': [
- 'plugin:vue/essential',
- 'eslint:recommended'
- ],
- parserOptions: {
- parser: 'babel-eslint'
- },
- rules: {
- 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
- 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
- }
-}
+module.exports = {
+ root: true,
+ env: {
+ node: true
+ },
+ 'extends': [
+ 'plugin:vue/essential',
+ 'eslint:recommended'
+ ],
+ parserOptions: {
+ parser: 'babel-eslint'
+ },
+ rules: {
+ 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+ }
+}
diff --git a/ui/public/img/icons/safari-pinned-tab.svg b/ui/public/img/icons/safari-pinned-tab.svg
index e44c0d5..c011013 100644
--- a/ui/public/img/icons/safari-pinned-tab.svg
+++ b/ui/public/img/icons/safari-pinned-tab.svg
@@ -1,3 +1,3 @@
-
+
diff --git a/ui/public/index.html b/ui/public/index.html
index bc51465..03393e0 100644
--- a/ui/public/index.html
+++ b/ui/public/index.html
@@ -1,19 +1,19 @@
-
-
-
-
-
-
-
- <%= htmlWebpackPlugin.options.title %>
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+
+
diff --git a/ui/public/robots.txt b/ui/public/robots.txt
index eb05362..a82d96e 100644
--- a/ui/public/robots.txt
+++ b/ui/public/robots.txt
@@ -1,2 +1,2 @@
-User-agent: *
-Disallow:
+User-agent: *
+Disallow:
diff --git a/ui/src/App.vue b/ui/src/App.vue
index 30068fc..f241043 100644
--- a/ui/src/App.vue
+++ b/ui/src/App.vue
@@ -1,63 +1,63 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/components/Header.vue b/ui/src/components/Header.vue
index b441032..0b9651c 100644
--- a/ui/src/components/Header.vue
+++ b/ui/src/components/Header.vue
@@ -1,57 +1,58 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ui/src/components/HelloWorld.vue b/ui/src/components/HelloWorld.vue
index 8e95071..b04f6bf 100644
--- a/ui/src/components/HelloWorld.vue
+++ b/ui/src/components/HelloWorld.vue
@@ -1,151 +1,151 @@
-
-
-
-
-
-
-
-
-
- Welcome to Vuetify
-
-
-
- For help and collaboration with other Vuetify developers,
-
please join our online
- Discord Community
-
-
-
-
-
- What's next?
-
-
-
-
- {{ next.text }}
-
-
-
-
-
-
- Important Links
-
-
-
-
- {{ link.text }}
-
-
-
-
-
-
- Ecosystem
-
-
-
-
- {{ eco.text }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Welcome to Vuetify
+
+
+
+ For help and collaboration with other Vuetify developers,
+
please join our online
+ Discord Community
+
+
+
+
+
+ What's next?
+
+
+
+
+ {{ next.text }}
+
+
+
+
+
+
+ Important Links
+
+
+
+
+ {{ link.text }}
+
+
+
+
+
+
+ Ecosystem
+
+
+
+
+ {{ eco.text }}
+
+
+
+
+
+
+
+
diff --git a/ui/src/main.js b/ui/src/main.js
index 9d43a4f..7f7af44 100644
--- a/ui/src/main.js
+++ b/ui/src/main.js
@@ -1,15 +1,15 @@
-import Vue from 'vue'
-import App from './App.vue'
-import './registerServiceWorker'
-import router from './router'
-import vuetify from './plugins/vuetify'
-import store from './store'
-
-Vue.config.productionTip = false
-
-new Vue({
- router,
- vuetify,
- store,
- render: h => h(App)
-}).$mount('#app')
+import Vue from 'vue'
+import App from './App.vue'
+import './registerServiceWorker'
+import router from './router'
+import vuetify from './plugins/vuetify'
+import store from './store'
+
+Vue.config.productionTip = false
+
+new Vue({
+ router,
+ vuetify,
+ store,
+ render: h => h(App)
+}).$mount('#app')
diff --git a/ui/src/plugins/vuetify.js b/ui/src/plugins/vuetify.js
index 076c359..444aa2a 100644
--- a/ui/src/plugins/vuetify.js
+++ b/ui/src/plugins/vuetify.js
@@ -1,25 +1,25 @@
-import Vue from 'vue'
-import Vuetify from 'vuetify/lib/framework'
-import colors from "vuetify/es5/util/colors";
-
-Vue.use(Vuetify)
-
-export default new Vuetify({
- theme: {
- themes: {
- light: {
- primary: colors.blue.lighten3,
- secondary: colors.grey.darken1,
- accent: colors.shades.black,
- error: colors.red.accent3,
- dark: "#151515",
- text: "#000000"
- },
- dark: {
- primary: colors.blue,
- dark: "#151515",
- text: "#ffffff"
- },
- },
- }
-});
+import Vue from 'vue'
+import Vuetify from 'vuetify/lib/framework'
+import colors from "vuetify/es5/util/colors";
+
+Vue.use(Vuetify)
+
+export default new Vuetify({
+ theme: {
+ themes: {
+ light: {
+ primary: colors.blue.lighten3,
+ secondary: colors.grey.darken1,
+ accent: colors.shades.black,
+ error: colors.red.accent3,
+ dark: "#151515",
+ text: "#000000"
+ },
+ dark: {
+ primary: colors.blue,
+ dark: "#151515",
+ text: "#ffffff"
+ },
+ },
+ }
+});
diff --git a/ui/src/registerServiceWorker.js b/ui/src/registerServiceWorker.js
index 76cede0..cee5d4e 100644
--- a/ui/src/registerServiceWorker.js
+++ b/ui/src/registerServiceWorker.js
@@ -1,32 +1,32 @@
-/* eslint-disable no-console */
-
-import { register } from 'register-service-worker'
-
-if (process.env.NODE_ENV === 'production') {
- register(`${process.env.BASE_URL}service-worker.js`, {
- ready () {
- console.log(
- 'App is being served from cache by a service worker.\n' +
- 'For more details, visit https://goo.gl/AFskqB'
- )
- },
- registered () {
- console.log('Service worker has been registered.')
- },
- cached () {
- console.log('Content has been cached for offline use.')
- },
- updatefound () {
- console.log('New content is downloading.')
- },
- updated () {
- console.log('New content is available; please refresh.')
- },
- offline () {
- console.log('No internet connection found. App is running in offline mode.')
- },
- error (error) {
- console.error('Error during service worker registration:', error)
- }
- })
-}
+/* eslint-disable no-console */
+
+import { register } from 'register-service-worker'
+
+if (process.env.NODE_ENV === 'production') {
+ register(`${process.env.BASE_URL}service-worker.js`, {
+ ready () {
+ console.log(
+ 'App is being served from cache by a service worker.\n' +
+ 'For more details, visit https://goo.gl/AFskqB'
+ )
+ },
+ registered () {
+ console.log('Service worker has been registered.')
+ },
+ cached () {
+ console.log('Content has been cached for offline use.')
+ },
+ updatefound () {
+ console.log('New content is downloading.')
+ },
+ updated () {
+ console.log('New content is available; please refresh.')
+ },
+ offline () {
+ console.log('No internet connection found. App is running in offline mode.')
+ },
+ error (error) {
+ console.error('Error during service worker registration:', error)
+ }
+ })
+}
diff --git a/ui/src/router/index.js b/ui/src/router/index.js
index 29650c9..000a7cb 100644
--- a/ui/src/router/index.js
+++ b/ui/src/router/index.js
@@ -1,35 +1,35 @@
-import Vue from 'vue'
-import VueRouter from 'vue-router'
-
-Vue.use(VueRouter)
-
-const routes = [
- {
- path: '/',
- name: 'Home',
- component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
- },
- {
- path: '/projects',
- name: 'Projects',
- // route level code-splitting
- // this generates a separate chunk (about.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import(/* webpackChunkName: "projects" */ '../views/Projects.vue')
- },
- {
- path: '/nexus',
- name: 'Nexus',
- // route level code-splitting
- // this generates a separate chunk (about.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import(/* webpackChunkName: "nexus" */ '../views/Nexus.vue')
- },
-]
-
-const router = new VueRouter({
- routes,
- mode: "history"
-})
-
-export default router
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const routes = [
+ {
+ path: '/',
+ name: 'Home',
+ component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
+ },
+ {
+ path: '/projects',
+ name: 'Projects',
+ // route level code-splitting
+ // this generates a separate chunk (about.[hash].js) for this route
+ // which is lazy-loaded when the route is visited.
+ component: () => import(/* webpackChunkName: "projects" */ '../views/Projects.vue')
+ },
+ {
+ path: '/nexus',
+ name: 'Nexus',
+ // route level code-splitting
+ // this generates a separate chunk (about.[hash].js) for this route
+ // which is lazy-loaded when the route is visited.
+ component: () => import(/* webpackChunkName: "nexus" */ '../views/Nexus.vue')
+ },
+]
+
+const router = new VueRouter({
+ routes,
+ mode: "history"
+})
+
+export default router
diff --git a/ui/src/views/Home.vue b/ui/src/views/Home.vue
index 35caa71..8e22bf1 100644
--- a/ui/src/views/Home.vue
+++ b/ui/src/views/Home.vue
@@ -1,11 +1,11 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ui/src/views/Nexus.vue b/ui/src/views/Nexus.vue
index ec6d906..32d76be 100644
--- a/ui/src/views/Nexus.vue
+++ b/ui/src/views/Nexus.vue
@@ -1,15 +1,15 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ui/src/views/Projects.vue b/ui/src/views/Projects.vue
index 62ceff4..7c33de7 100644
--- a/ui/src/views/Projects.vue
+++ b/ui/src/views/Projects.vue
@@ -2,13 +2,148 @@
Projects
+
+
+
+
+
+ {{project.name}}
+
+ {{tag.icon}}
+ {{tag.name}}
+
+ {{project.description}}
+
+
+ mdi-web Website
+
+
+ mdi-git Git Repository
+
+
+
+
+
+
+
+
+