From 57ea28385e3d4f0c4c1a69a6bd33c5a80fe55742 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:02:42 +0100 Subject: [PATCH 01/10] feat(index.html): use dynamic paths --- public/index.html | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/public/index.html b/public/index.html index ceb16a4965..0e471f40d1 100644 --- a/public/index.html +++ b/public/index.html @@ -7,11 +7,12 @@ - - - - - + + + + + + Dashy From 5b4f832ccfdb4cb775fcadda5d32d944681f7631 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:03:20 +0100 Subject: [PATCH 02/10] feat(router.js): dynamic langing page based on BASE_URL --- src/router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/router.js b/src/router.js index 57d43783a3..c4329f9521 100644 --- a/src/router.js +++ b/src/router.js @@ -59,7 +59,7 @@ const router = new Router({ routes: [ // ...makeMultiPageRoutes(pages), { // The default view can be customized by the user - path: '/', + path: process.env.BASE_URL || '/', name: `landing-page-${startingView}`, component: getStartingComponent(), meta: makeMetaTags('Home Page'), From 9e15987c8f7c0bb3b8046074b49d7d7595f45db3 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:04:00 +0100 Subject: [PATCH 03/10] feat(InitServiceWorker.js): configurable configFilePath --- src/utils/InitServiceWorker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/InitServiceWorker.js b/src/utils/InitServiceWorker.js index 7cc6b6c116..bcd6c64b03 100644 --- a/src/utils/InitServiceWorker.js +++ b/src/utils/InitServiceWorker.js @@ -33,7 +33,8 @@ const setSwStatus = (swStateToSet) => { * Or disable if user specified to disable */ const shouldEnableServiceWorker = async () => { - const conf = yaml.load((await axios.get('/conf.yml')).data); + const configFilePath = process.env.VUE_APP_CONFIG_PATH || './conf.yml'; + const conf = yaml.load((await axios.get(configFilePath)).data); if (conf && conf.appConfig && conf.appConfig.enableServiceWorker) { setSwStatus({ disabledByUser: false }); return true; From 7767d61da178e9852176b0946b41619050d332b2 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:04:51 +0100 Subject: [PATCH 04/10] feat(fonts): load all dynamically --- .../assets}/fonts/Audiowide-Regular.ttf | Bin .../assets}/fonts/CutiveMono-Regular.ttf | Bin .../assets}/fonts/Digital-Regular.ttf | Bin .../assets}/fonts/FrancoisOne-Regular.ttf | Bin .../assets}/fonts/Podkova-Medium.ttf | Bin {public => src/assets}/fonts/Roboto-Light.ttf | Bin .../assets}/fonts/Shrikhand-Regular.ttf | Bin .../assets}/fonts/Sniglet-Regular.ttf | Bin {public => src/assets}/fonts/VT323-Regular.ttf | Bin src/styles/typography.scss | 17 +++++++++-------- 10 files changed, 9 insertions(+), 8 deletions(-) rename {public => src/assets}/fonts/Audiowide-Regular.ttf (100%) rename {public => src/assets}/fonts/CutiveMono-Regular.ttf (100%) rename {public => src/assets}/fonts/Digital-Regular.ttf (100%) rename {public => src/assets}/fonts/FrancoisOne-Regular.ttf (100%) rename {public => src/assets}/fonts/Podkova-Medium.ttf (100%) rename {public => src/assets}/fonts/Roboto-Light.ttf (100%) rename {public => src/assets}/fonts/Shrikhand-Regular.ttf (100%) rename {public => src/assets}/fonts/Sniglet-Regular.ttf (100%) rename {public => src/assets}/fonts/VT323-Regular.ttf (100%) diff --git a/public/fonts/Audiowide-Regular.ttf b/src/assets/fonts/Audiowide-Regular.ttf similarity index 100% rename from public/fonts/Audiowide-Regular.ttf rename to src/assets/fonts/Audiowide-Regular.ttf diff --git a/public/fonts/CutiveMono-Regular.ttf b/src/assets/fonts/CutiveMono-Regular.ttf similarity index 100% rename from public/fonts/CutiveMono-Regular.ttf rename to src/assets/fonts/CutiveMono-Regular.ttf diff --git a/public/fonts/Digital-Regular.ttf b/src/assets/fonts/Digital-Regular.ttf similarity index 100% rename from public/fonts/Digital-Regular.ttf rename to src/assets/fonts/Digital-Regular.ttf diff --git a/public/fonts/FrancoisOne-Regular.ttf b/src/assets/fonts/FrancoisOne-Regular.ttf similarity index 100% rename from public/fonts/FrancoisOne-Regular.ttf rename to src/assets/fonts/FrancoisOne-Regular.ttf diff --git a/public/fonts/Podkova-Medium.ttf b/src/assets/fonts/Podkova-Medium.ttf similarity index 100% rename from public/fonts/Podkova-Medium.ttf rename to src/assets/fonts/Podkova-Medium.ttf diff --git a/public/fonts/Roboto-Light.ttf b/src/assets/fonts/Roboto-Light.ttf similarity index 100% rename from public/fonts/Roboto-Light.ttf rename to src/assets/fonts/Roboto-Light.ttf diff --git a/public/fonts/Shrikhand-Regular.ttf b/src/assets/fonts/Shrikhand-Regular.ttf similarity index 100% rename from public/fonts/Shrikhand-Regular.ttf rename to src/assets/fonts/Shrikhand-Regular.ttf diff --git a/public/fonts/Sniglet-Regular.ttf b/src/assets/fonts/Sniglet-Regular.ttf similarity index 100% rename from public/fonts/Sniglet-Regular.ttf rename to src/assets/fonts/Sniglet-Regular.ttf diff --git a/public/fonts/VT323-Regular.ttf b/src/assets/fonts/VT323-Regular.ttf similarity index 100% rename from public/fonts/VT323-Regular.ttf rename to src/assets/fonts/VT323-Regular.ttf diff --git a/src/styles/typography.scss b/src/styles/typography.scss index 829d604176..ed0ab6b68c 100644 --- a/src/styles/typography.scss +++ b/src/styles/typography.scss @@ -45,33 +45,34 @@ html { /* These fonts are loaded from ./public so not bundled within dist */ @font-face { // Used by body text in Matrix and Hacker themes. Credit to the late Vernon Adams, RIP font-family: 'Cutive Mono'; - src: url('/fonts/CutiveMono-Regular.ttf'); + src: url('./assets/fonts/CutiveMono-Regular.ttf'); } @font-face { // Heading text in Material and Material Dark. Credit to Vernon Adams font-family: 'Francois One'; - src: url('/fonts/FrancoisOne-Regular.ttf'); + src: url('./assets/fonts/FrancoisOne-Regular.ttf'); } @font-face { // Heading text in Colorful theme. Credit to Cyreal font-family: 'Podkova'; - src: url('/fonts/Podkova-Medium.ttf'); + src: url('./assets/fonts/Podkova-Medium.ttf'); } @font-face { // Standard body text in material original. Credit to Christian Robertson font-family: 'Roboto'; - src: url('/fonts/Roboto-Light.ttf'); + src: url('./assets/fonts/Roboto-Light.ttf'); } + @font-face { // Heading text in Jam, Bee and Tiger themes. Credit to Haley Fiege font-family: 'Sniglet'; - src: url('/fonts/Sniglet-Regular.ttf'); + src: url('./assets/fonts/Sniglet-Regular.ttf'); } @font-face { // Used by heading text in Matrix and Hacker themes. Credit to Peter Hull font-family: 'VT323'; - src: url('/fonts/VT323-Regular.ttf'); + src: url('./assets/fonts/VT323-Regular.ttf'); } @font-face { // Used by cyberpunk theme. Credit to Astigmatic font-family: 'Audiowide'; - src: url('/fonts/Audiowide-Regular.ttf'); + src: url('./assets/fonts/Audiowide-Regular.ttf'); } @font-face { // Used by Dracula, Lissy themes. Credit to Jonny Pinhorn font-family: 'Shrikhand'; - src: url('/fonts/Shrikhand-Regular.ttf'); + src: url('./assets/fonts/Shrikhand-Regular.ttf'); } From 1a4adad88f7eb06e885380fb068cc2c7f814a6b2 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:18:40 +0100 Subject: [PATCH 05/10] fix(ConfigHelper.js): formatConfigPath triggering false positive for being an url --- src/utils/ConfigHelpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js index a2944bf1df..9ae6d4ef40 100644 --- a/src/utils/ConfigHelpers.js +++ b/src/utils/ConfigHelpers.js @@ -28,7 +28,7 @@ export const makePageSlug = (pageName, pageType) => { /* Put fetch path for additional configs in correct format */ export const formatConfigPath = (configPath) => { - if (configPath.includes('http')) return configPath; + if (/^https?:\/\//.test(configPath)) return configPath; if (configPath.substring(0, 1) !== '/') return `/${configPath}`; return configPath; }; From 608df193646a7b775f66c165f9c1b085d729c833 Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:26:45 +0100 Subject: [PATCH 06/10] feat: resolving conf file considering the baseUrl --- src/store.js | 4 ++-- src/utils/ConfigHelpers.js | 13 +++++++++++++ src/utils/InitServiceWorker.js | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/store.js b/src/store.js index 9130139c68..3be8e80363 100644 --- a/src/store.js +++ b/src/store.js @@ -4,7 +4,7 @@ import Vuex from 'vuex'; import axios from 'axios'; import yaml from 'js-yaml'; import Keys from '@/utils/StoreMutations'; -import { makePageName, formatConfigPath, componentVisibility } from '@/utils/ConfigHelpers'; +import { makePageName, formatConfigPath, getConfigFilePath, componentVisibility } from '@/utils/ConfigHelpers'; import { applyItemId } from '@/utils/SectionHelpers'; import filterUserSections from '@/utils/CheckSectionVisibility'; import ErrorHandler, { InfoHandler, InfoKeys } from '@/utils/ErrorHandler'; @@ -353,7 +353,7 @@ const store = new Vuex.Store({ actions: { /* Fetches the root config file, only ever called by INITIALIZE_CONFIG */ async [INITIALIZE_ROOT_CONFIG]({ commit }) { - const configFilePath = process.env.VUE_APP_CONFIG_PATH || '/conf.yml'; + const configFilePath = getConfigFilePath(); try { // Attempt to fetch the YAML file const response = await axios.get(configFilePath, makeBasicAuthHeaders()); diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js index 9ae6d4ef40..a941c7ed2a 100644 --- a/src/utils/ConfigHelpers.js +++ b/src/utils/ConfigHelpers.js @@ -33,6 +33,19 @@ export const formatConfigPath = (configPath) => { return configPath; }; +/** + * Resolves the complete config file path by combining BASE_URL with the config path. + * If VUE_APP_CONFIG_PATH is a full URL (http:// or https://), returns it as-is. + * Otherwise, joins BASE_URL with the config path. Defaults to '/conf.yml' if no path is set. + * @param {string} configDefault - Default config path if VUE_APP_CONFIG_PATH is not set + * @returns {string} The complete config file path + */ +export const getConfigFilePath = (configDefault = '/conf.yml') => { + const baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, '') || '/'; + const configPath = process.env.VUE_APP_CONFIG_PATH || configDefault; + return /^https?:\/\//.test(configPath) ? configPath : baseUrl + formatConfigPath(configPath); +}; + /** * Initiates the Accumulator class and generates a complete config object * Self-executing function, returns the full user config as a JSON object diff --git a/src/utils/InitServiceWorker.js b/src/utils/InitServiceWorker.js index bcd6c64b03..b2fd25800f 100644 --- a/src/utils/InitServiceWorker.js +++ b/src/utils/InitServiceWorker.js @@ -2,6 +2,7 @@ import axios from 'axios'; import yaml from 'js-yaml'; import { register } from 'register-service-worker'; import { sessionStorageKeys } from '@/utils/defaults'; +import { getConfigFilePath } from '@/utils/ConfigHelpers'; import { statusMsg, statusErrorMsg } from '@/utils/CoolConsole'; /* Sets a local storage item with the state from the SW lifecycle */ @@ -33,7 +34,7 @@ const setSwStatus = (swStateToSet) => { * Or disable if user specified to disable */ const shouldEnableServiceWorker = async () => { - const configFilePath = process.env.VUE_APP_CONFIG_PATH || './conf.yml'; + const configFilePath = getConfigFilePath('/conf.yml'); const conf = yaml.load((await axios.get(configFilePath)).data); if (conf && conf.appConfig && conf.appConfig.enableServiceWorker) { setSwStatus({ disabledByUser: false }); From c97e74413506d22807eb1395e48db3dd9e75742b Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 22:30:01 +0100 Subject: [PATCH 07/10] chore(store.js):eslint formating --- src/store.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/store.js b/src/store.js index 3be8e80363..088a42e41a 100644 --- a/src/store.js +++ b/src/store.js @@ -4,7 +4,12 @@ import Vuex from 'vuex'; import axios from 'axios'; import yaml from 'js-yaml'; import Keys from '@/utils/StoreMutations'; -import { makePageName, formatConfigPath, getConfigFilePath, componentVisibility } from '@/utils/ConfigHelpers'; +import { + makePageName, + formatConfigPath, + getConfigFilePath, + componentVisibility, +} from '@/utils/ConfigHelpers'; import { applyItemId } from '@/utils/SectionHelpers'; import filterUserSections from '@/utils/CheckSectionVisibility'; import ErrorHandler, { InfoHandler, InfoKeys } from '@/utils/ErrorHandler'; From 65f1993b2f87803295f15093fc8132b4ce20b5ec Mon Sep 17 00:00:00 2001 From: flox Date: Mon, 2 Mar 2026 23:43:33 +0100 Subject: [PATCH 08/10] fix: relative default conf --- src/utils/ConfigHelpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js index a941c7ed2a..7aa3304715 100644 --- a/src/utils/ConfigHelpers.js +++ b/src/utils/ConfigHelpers.js @@ -40,7 +40,7 @@ export const formatConfigPath = (configPath) => { * @param {string} configDefault - Default config path if VUE_APP_CONFIG_PATH is not set * @returns {string} The complete config file path */ -export const getConfigFilePath = (configDefault = '/conf.yml') => { +export const getConfigFilePath = (configDefault = './conf.yml') => { const baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, '') || '/'; const configPath = process.env.VUE_APP_CONFIG_PATH || configDefault; return /^https?:\/\//.test(configPath) ? configPath : baseUrl + formatConfigPath(configPath); From 60a65f4766292a557d9d900514bfae4fb0d39bde Mon Sep 17 00:00:00 2001 From: flox Date: Tue, 3 Mar 2026 00:19:47 +0100 Subject: [PATCH 09/10] fix(ConfigHelper.js): include edgecases --- src/utils/ConfigHelpers.js | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js index 7aa3304715..784af1649e 100644 --- a/src/utils/ConfigHelpers.js +++ b/src/utils/ConfigHelpers.js @@ -36,14 +36,42 @@ export const formatConfigPath = (configPath) => { /** * Resolves the complete config file path by combining BASE_URL with the config path. * If VUE_APP_CONFIG_PATH is a full URL (http:// or https://), returns it as-is. - * Otherwise, joins BASE_URL with the config path. Defaults to '/conf.yml' if no path is set. + * Otherwise, joins BASE_URL with the config path. Defaults to './conf.yml' if no path is set. + * If BASE_URL is incomplete, falls back to a relative path. * @param {string} configDefault - Default config path if VUE_APP_CONFIG_PATH is not set * @returns {string} The complete config file path */ export const getConfigFilePath = (configDefault = './conf.yml') => { - const baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, '') || '/'; const configPath = process.env.VUE_APP_CONFIG_PATH || configDefault; - return /^https?:\/\//.test(configPath) ? configPath : baseUrl + formatConfigPath(configPath); + + // If it's already a full URL, return as-is + if (/^https?:\/\//.test(configPath)) { + return configPath; + } + + // Get BASE_URL and ensure it's valid + let baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, ''); + + // If BASE_URL is incomplete (just protocol or empty), fall back to relative path + if (!baseUrl || /^https?:$/.test(baseUrl)) { + return formatConfigPath(configPath); + } + + // Combine baseUrl with the formatted config path + const normalizedPath = formatConfigPath(configPath); + + const rawBase = process.env.BASE_URL || '/'; + if (rawBase.startsWith('./') || rawBase.startsWith('/')) { + // Join and clean: + // 1. Replaces /./ with / + // 2. Replaces // with / + // 3. Removes leading . if the path starts with ./ + return (baseUrl + '/' + normalizedPath) + .replace(/\/\.\//g, '/') + .replace(/\/+/g, '/'); + } + + return normalizedPath; }; /** From 6942d373e754200aeb26062abcd572f21a486fdd Mon Sep 17 00:00:00 2001 From: flox Date: Tue, 3 Mar 2026 00:22:33 +0100 Subject: [PATCH 10/10] chore(ConfigHelpers.js): eslint --- src/utils/ConfigHelpers.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js index 784af1649e..45540becb2 100644 --- a/src/utils/ConfigHelpers.js +++ b/src/utils/ConfigHelpers.js @@ -43,35 +43,23 @@ export const formatConfigPath = (configPath) => { */ export const getConfigFilePath = (configDefault = './conf.yml') => { const configPath = process.env.VUE_APP_CONFIG_PATH || configDefault; - + // If it's already a full URL, return as-is if (/^https?:\/\//.test(configPath)) { return configPath; } - + // Get BASE_URL and ensure it's valid - let baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, ''); - + const baseUrl = (process.env.BASE_URL || '/').replace(/\/$/, ''); + // If BASE_URL is incomplete (just protocol or empty), fall back to relative path if (!baseUrl || /^https?:$/.test(baseUrl)) { return formatConfigPath(configPath); } - + // Combine baseUrl with the formatted config path const normalizedPath = formatConfigPath(configPath); - - const rawBase = process.env.BASE_URL || '/'; - if (rawBase.startsWith('./') || rawBase.startsWith('/')) { - // Join and clean: - // 1. Replaces /./ with / - // 2. Replaces // with / - // 3. Removes leading . if the path starts with ./ - return (baseUrl + '/' + normalizedPath) - .replace(/\/\.\//g, '/') - .replace(/\/+/g, '/'); - } - - return normalizedPath; + return `${baseUrl}${normalizedPath}`; }; /**