diff --git a/.dockerignore b/.dockerignore index 5662588360..083b416dd5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,7 @@ # Files specified here are not required for Docker # so ignoring them helps to reduce the container size # The Docker container MUST have the following files: -# package.json yarn.lock server.js vue.config.js src/ services/ +# package.json yarn.lock server.js vite.config.mjs src/ services/ node_modules docs diff --git a/.env b/.env index 87202c329b..867b40cd7b 100644 --- a/.env +++ b/.env @@ -37,23 +37,20 @@ # If using BASIC_AUTH above, set these to the same values to skip the browser auth prompt # Requires a rebuild to take effect - only use on trusted networks -# VUE_APP_BASIC_AUTH_USERNAME= -# VUE_APP_BASIC_AUTH_PASSWORD= +# VITE_APP_BASIC_AUTH_USERNAME= +# VITE_APP_BASIC_AUTH_PASSWORD= # Override where the path to the configuration file is, can be a remote URL -# VUE_APP_CONFIG_PATH=/conf.yml +# VITE_APP_CONFIG_PATH=/conf.yml # Usually the same as BASE_URL, but accessible in frontend -# VUE_APP_DOMAIN=https://dashy.to +# VITE_APP_DOMAIN=https://dashy.to # Override the page title for the frontend app -# VUE_APP_TITLE='' - -# Set the default view to load on startup (can be `minimal`, `workspace` or `home`) -# VUE_APP_STARTING_VIEW=home +# VITE_APP_TITLE='' # Set the Vue app routing mode (can be 'hash', 'history' or 'abstract') -# VUE_APP_ROUTING_MODE=history +# VITE_APP_ROUTING_MODE=history # Should enable SRI for build script and link resources # INTEGRITY=true @@ -62,11 +59,11 @@ # IS_DOCKER=true # Again, set automatically using package.json during build time -# VUE_APP_VERSION=2.0.0 +# VITE_APP_VERSION=2.0.0 # Directory for conf.yml backups # BACKUP_DIR=./user-data/config-backups -# Setup any other user defined vars by prepending VUE_APP_ to the var name -# VUE_APP_pihole_ip=http://your.pihole.ip -# VUE_APP_pihole_key=your_pihole_secret_key +# Setup any other user defined vars by prepending VITE_APP_ to the var name +# VITE_APP_pihole_ip=http://your.pihole.ip +# VITE_APP_pihole_key=your_pihole_secret_key diff --git a/.github/pr-auto-comments.yml b/.github/pr-auto-comments.yml new file mode 100644 index 0000000000..b4a62ab1a2 --- /dev/null +++ b/.github/pr-auto-comments.yml @@ -0,0 +1,135 @@ +comment: + on-update: edit + header: | + Hi {{ prAuthor }}! Thank you for contributing to Dashy! ✨ + footer: | + --- + > I'm a bot, and this is an automated comment 🤖 + snippets: + - id: docs-changes + files: + - docs/**.md + body: | + When making changes to the documentation, be sure to double check that: + - Link and images URLs properly resolve + - Your spelling and grammar is correct + - Any markdown formatting is valid + + - id: vite-config + files: + - vite.config.mjs + body: > + You're making changes to the main Vite build config. Please test the app thoroughly, + as any misconfigurations here may cause the app to stop functioning. + + - id: server-entry + files: + - server.js + body: > + You're making changes to the main server entry point. Please test the app thoroughly, + as any misconfigurations here may cause the app to stop functioning. + + - id: dependency-changes + files: + - yarn.lock + body: > + When updating dependencies, take a moment to verify that there are not security + issues associated with any added or modified packages. If adding a new dependency, + ensure that it is totally necessary, and check the packages size is not too large, + as this will increase overall bundle size. + + - id: environmental-vars + files: [ '.env', '*.env', '.env*' ] + body: > + You're making changes to the main server entry point. Please test the app thoroughly, + as any misconfigurations here may cause the app to stop functioning. + + - id: license + files: [ 'LICENSE', '**/**/LICENSE*' ] + body: > + Dashy is licensed under MIT. Your modifying the license file, which shouldn't usually + need to be changed. Please ensure that you intended to make this update before continuing. + + - id: cname-file + files: + - CNAME + body: > + Are you sure you want to modify the CNAME file? This may stop the documentation + website hosted on GitHub pages from working. + + - id: git-ignore + files: + - .gitignore + body: > + When modifying the .gitignore, please do not remove any of the existing paths, + as this may cause files and directories to be unintentionally committed to git + + - id: netlify-file + files: + - netlify.toml + body: > + Please ensure you've tested the app on Netlify, so that the 1-Click deployment + does not break, before merging these changes + + - id: heroku-ignore + files: + - Procfile + body: > + Please ensure you've tested the app on Heroku, so that the 1-Click deployment + does not break, before merging these changes + + - id: ignored-dist + files: + - dist/**/* + body: > + Please do not commit the built application to git. The contents of the dist + directory will be generated after the app is compiled + + - id: ignored-dependencies + files: + - node_modules/**/* + body: > + Please do not commit dependencies to git. Node modules will be pulled down + when yarn is run, prior to building the app + + - id: user-themes + files: + - src/styles/user-defined-themes.scss + body: > + Please do not commit changes to this file, as it is intended to be overridden with Docker. + You can instead add your styles to the color-themes file, or for element-specific styles + put it within the appropriate component. Thank you + + - id: code-owners + files: + - .github/CODEOWNERS + body: > + Are you adding yourself as a code owner? Please specify the file path as specific + as possible, and only assign yourself to files that you created and wish to help + maintain (such as a language file, specific feature or widget). + If the above is not met, your PR will be declined or modified. + + - id: config-schema + files: + - src/utils/ConfigSchema.json + body: > + Don't forget to verify they the config validator script responds correctly to + your new attribute. + + - id: showcase + files: + - docs/showcase.md + body: > + Thank you for adding your dashboard to the showcase! 🌟 + + - id: translations + files: + - src/assets/locales/**.json + body: > + Thank you for contributing to Dashy's translations 💖 + + - id: themes + files: + - src/styles/color-themes.scss + body: > + Thank you for contributing to Dashy's themes 🎨 diff --git a/.github/workflows/pr-quality-check.yml b/.github/workflows/pr-quality-check.yml index 18b3ed0009..9acfb2aa53 100644 --- a/.github/workflows/pr-quality-check.yml +++ b/.github/workflows/pr-quality-check.yml @@ -67,8 +67,6 @@ jobs: - name: 🏗️ Build Project run: yarn build - env: - NODE_OPTIONS: --openssl-legacy-provider - name: ✅ Verify Build Output run: | diff --git a/.github/workflows/update-docs-site.yml b/.github/workflows/update-docs-site.yml index 53faf44b20..de1f627c43 100644 --- a/.github/workflows/update-docs-site.yml +++ b/.github/workflows/update-docs-site.yml @@ -55,8 +55,6 @@ jobs: - name: Run script to update documentation 🪄 working-directory: website-docs - env: - NODE_OPTIONS: '--openssl-legacy-provider' run: | cp -r ../master-docs/docs ./ python ./do-doc-updaty-magic.py diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..177df74072 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "msedge", + "request": "launch", + "name": "dashy: edge", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}/src", + "preLaunchTask": "dashy start" + }, + { + "type": "chrome", + "request": "launch", + "name": "dashy: chrome", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}/src", + "preLaunchTask": "dashy start" + }, + { + "type": "firefox", + "request": "launch", + "name": "dashy: firefox", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}/src", + "preLaunchTask": "dashy start" + } + ] +} diff --git a/Dockerfile b/Dockerfile index 30e4131488..9aa6e557dd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18.19.1-alpine AS build +FROM node:20-alpine AS build # Set the platform to build image for ARG TARGETPLATFORM @@ -22,10 +22,10 @@ RUN yarn install --ignore-engines --immutable --no-cache --network-timeout 30000 COPY . ./ # Build initial app for production -RUN yarn build --mode production --no-clean +RUN yarn build # Production stage -FROM node:20.11.1-alpine3.19 +FROM node:20-alpine # Define some ENV Vars ENV PORT=8080 \ diff --git a/docs/authentication.md b/docs/authentication.md index b2bce79810..437a3a745f 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -122,7 +122,7 @@ To disable all UI config features, including View Config, set `disableConfigurat If you don't want to hash your password, you can instead leave out the `hash` attribute, and replace it with `password` which should have the value of an environmental variable name you wish to use. -Note that env var must begin with `VUE_APP_`, and you must set this variable before building the app. +Note that env var must begin with `VITE_APP_`, and you must set this variable before building the app. For example: @@ -130,10 +130,10 @@ For example: auth: users: - user: bob - password: VUE_APP_BOB + password: VITE_APP_BOB ``` -Just be sure to set `VUE_APP_BOB='my super secret password'` before build-time. +Just be sure to set `VITE_APP_BOB='my super secret password'` before build-time. ### Adding HTTP Auth to Configuration @@ -184,7 +184,7 @@ If you don't have users in your `conf.yml` (e.g. you handle user management exte With this approach, there is no Dashy login page. When the browser first requests the config file, the server responds with a `401` and the browser shows its native HTTP auth prompt. Once the user enters the correct credentials, the browser caches them for the session and all subsequent requests work. -To skip the browser prompt and have the frontend authenticate automatically, also set `VUE_APP_BASIC_AUTH_USERNAME` and `VUE_APP_BASIC_AUTH_PASSWORD` to the same values. These are baked in at build time, so a rebuild is required, and you should only do this on a trusted network. +To skip the browser prompt and have the frontend authenticate automatically, also set `VITE_APP_BASIC_AUTH_USERNAME` and `VITE_APP_BASIC_AUTH_PASSWORD` to the same values. These are baked in at build time, so a rebuild is required, and you should only do this on a trusted network. > [!WARNING] > Do not combine `BASIC_AUTH_USERNAME`/`BASIC_AUTH_PASSWORD` with conf.yml users. If both are present, the server will log a warning at startup. With `ENABLE_HTTP_AUTH` set, config-file users take priority and the static credentials are ignored. Without it, the static credentials protect the server but the Dashy login page will use conf.yml credentials, and the frontend will send the wrong credentials to server endpoints. Pick one approach or the other. @@ -565,7 +565,6 @@ sections: - name: Authentication displayData: sortBy: default - rows: 2 cols: 1 collapsed: false hideForGuests: false diff --git a/docs/configuring.md b/docs/configuring.md index 9558eadf73..c23e119fc8 100644 --- a/docs/configuring.md +++ b/docs/configuring.md @@ -73,8 +73,10 @@ The following file provides a reference of all supported configuration options. **`title`** | `string` | Required | Your dashboard title, displayed in the header and browser tab **`description`** | `string` | _Optional_ | Description of your dashboard, also displayed as a subtitle **`navLinks`** | `array` | _Optional_ | Optional list of a maximum of 6 links, which will be displayed in the navigation bar. See [`navLinks`](#pageinfonavlinks-optional) -**`footerText`** | `string` | _Optional_ | Text to display in the footer (note that this will override the default footer content). This can also include HTML and inline CSS +**`footer`** | `string` | _Optional_ | Text to display in the footer. When omitted, no footer is rendered. Supports inline HTML (sanitized before render) **`logo`** | `string` | _Optional_ | The path to an image to display in the header (to the right of the title). This can be either local, where `/` is the root of `./public`, or any remote image, such as `https://i.ibb.co/yhbt6CY/dashy.png`. It's recommended to scale your image down, so that it doesn't impact load times +**`favicon`** | `string` | _Optional_ | URL or path to a custom favicon shown in the browser tab. Can be absolute (`https://...`), root-relative (`/icons/x.png`), or a `data:` URI +**`color`** | `string` | _Optional_ | Theme colour applied to the browser chrome (mobile address bar). Any valid CSS color (e.g. `#ff00a7`) is accepted **[⬆️ Back to Top](#configuring)** @@ -104,7 +106,7 @@ For more info, see the[Multi-Page docs](/docs/pages-and-sections.md#multi-page-s **Field** | **Type** | **Required**| **Description** --- | --- | --- | --- **`language`** | `string` | _Optional_ | The 2 (or 4-digit) [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, e.g. `en` or `en-GB`. This must be a language that the app has already been [translated](https://github.com/Lissy93/dashy/tree/master/src/assets/locales) into. If your language is unavailable, Dashy will fallback to English. By default Dashy will attempt to auto-detect your language, although this may not work on some privacy browsers. -~~**`startingView`**~~ | `enum` | _Optional_ | Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI. Can be either `default`, `minimal` or `workspace`. Defaults to `default`. NOTE: This has been replaced by an environmental variable: `VUE_APP_STARTING_VIEW` in V3 onwards +**`startingView`** | `enum` | _Optional_ | Which view to land on when visiting `/`. One of `home`, `minimal` or `workspace`. Defaults to `home`. Applied at runtime, so no rebuild is needed. You can always switch views from the UI. (Legacy value `default` is accepted as an alias for `home`.) **`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Defaults to `newtab` **`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping each of your services and display their status as a dot next to each item. This can be overridden by setting `statusCheck` under each item. Defaults to `false` **`statusCheckInterval`** | `number` | _Optional_ | The number of seconds between checks. If set to `0` then service will only be checked on initial page load, which is usually the desired functionality. If value is less than `10` you may experience a hit in performance. Defaults to `0` @@ -117,7 +119,7 @@ For more info, see the[Multi-Page docs](/docs/pages-and-sections.md#multi-page-s **`faviconApi`** | `enum` | _Optional_ | Only applicable if you are using favicons for item icons. Specifies which service to use to resolve favicons. Set to `local` to do this locally, without using an API. Services running locally will use this option always. Available options are: `local`, `allesedv`, `iconhorse`, `faviconkit`, `duckduckgo`, `yandex`, `google`, `besticon`, `webmasterapi` and `mcapi`. Defaults to `allesedv`. See [Icons](/docs/icons.md#favicons) for more info **`auth`** | `object` | _Optional_ | All settings relating to user authentication. See [`auth`](#appconfigauth-optional) **`defaultIcon`** | `string` | _Optional_ | An icon to be applied to any items, which don't already have an icon set. See [Icon Docs](/docs/icons.md#default-icon) for more info -**`layout`** | `enum` | _Optional_ | Layout for homepage, either `horizontal`, `vertical` or `auto`. Defaults to `auto`. This specifies the layout and direction of how sections are positioned on the home screen. This can also be modified and overridden from the UI. +**`layout`** | `enum` | _Optional_ | Layout for homepage, either `horizontal`, `vertical` or `auto`. Defaults to `auto`. This specifies the layout and direction of how sections are positioned on the home screen. `auto` uses a responsive masonry grid: sections flow into the next available slot so shorter ones fill the gaps left by taller neighbours; `section.displayData.cols` still controls width, but `rows` is ignored (heights are driven by content). This can also be modified and overridden from the UI. **`iconSize`** | `enum` | _Optional_ | The size of link items / icons. Can be either `small`, `medium,` or `large`. Defaults to `medium`. This can also be set directly from the UI. **`colCount`** | `number` | _Optional_ | The number of columns of sections displayed on the homepage, using the default view. Should be in integer between `1` and `8`. Note that by default this is applied responsively, based on current screen size, and specifying a value here will override this behavior, which may not be desirable. **`contentMaxWidth`** | `string` or `number` | _Optional_ | Sets the max width of the main sections area on the homepage, overriding the responsive default. Can be a percentage, or any CSS unit @@ -128,7 +130,7 @@ For more info, see the[Multi-Page docs](/docs/pages-and-sections.md#multi-page-s **`customColors`** | `object`| _Optional_ | Enables you to apply a custom color palette to any given theme. Use the theme name (lowercase) as the key, for an object including key-value-pairs, with the color variable name as keys, and 6-digit hex code as value. See [Theming](/docs/theming.md#modifying-theme-colors) for more info **`externalStyleSheet`** | `string` or `string[]` | _Optional_ | Either a URL to an external stylesheet or an array or URLs, which can be applied as themes within the UI **`customCss`** | `string` | _Optional_ | Raw CSS that will be applied to the page. This can also be set from the UI. Please minify it first. -**`hideComponents`** | `object` | _Optional_ | A list of key page components (header, footer, search, settings, etc) that are present by default, but can be removed using this option. See [`appConfig.hideComponents`](#appconfighideComponents-optional) +**`hideComponents`** | `object` | _Optional_ | A list of key page components (header, nav, search, settings) that are present by default, but can be removed using this option. See [`appConfig.hideComponents`](#appconfighideComponents-optional) **`enableMultiTasking`** | `boolean` | _Optional_ | If set to true, will keep apps open in the background when in the workspace view. Useful for quickly switching between multiple sites, and preserving their state, but comes at the cost of performance. **`workspaceLandingUrl`** | `string` | _Optional_ | The URL or an app, service or website to launch when the workspace view is opened, before another service has been launched **`preventWriteToDisk`** | `boolean` | _Optional_ | If set to `true`, users will be prevented from saving config changes to disk through the UI @@ -235,7 +237,6 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)** **`hideNav`** | `boolean` | _Optional_ | If set to `true`, the navigation menu will not be visible. Defaults to `false` **`hideSearch`** | `boolean` | _Optional_ | If set to `true`, the search bar will not be visible. Defaults to `false` **`hideSettings`** | `boolean` | _Optional_ | If set to `true`, the settings menu will be initially collapsed. Defaults to `false` -**`hideFooter`** | `boolean` | _Optional_ | If set to `true`, the footer will not be visible. Defaults to `false` **[⬆️ Back to Top](#configuring)** @@ -311,14 +312,14 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)** **`sortBy`** | `string` | _Optional_ | The sort order for items within the current section. By default items are displayed in the order in which they are listed in within the config. The following sort options are supported: `most-used` (most opened apps first), `last-used` (the most recently used apps), `alphabetical`, `reverse-alphabetical`, `random` and `default` **`collapsed`** | `boolean` | _Optional_ | If true, the section will be collapsed initially, and will need to be clicked to open. Useful for less regularly used, or very long sections. Defaults to `false` **`cutToHeight`** | `boolean` | _Optional_ | By default, sections will fill available space. Set this option to true to match section height with content height -**`rows`** | `number` | _Optional_ | Height of the section, specified as the number of rows it should span vertically, e.g. `2`. Defaults to `1`. Max is `5`. +**`rows`** | `number` | _Optional_ | _Deprecated._ Previously set a section's vertical row-span. The `auto` layout now uses masonry (heights follow content) and `horizontal`/`vertical` are flex-based, so this value is accepted for config compatibility but no longer applied. **`cols`** | `number` | _Optional_ | Width of the section, specified as the number of columns the section should span horizontally, e.g. `2`. Defaults to `1`. Max is `5`. Will be clamped to the page's active column count so that a section never exceeds the available grid width. **`itemSize`** | `string` | _Optional_ | Specify the size for items within this group, either `small`, `medium` or `large`. Note that this will override any settings specified through the UI **`color`** | `string` | _Optional_ | A custom accent color for the section, as a hex code or HTML color (e.g. `#fff`) **`customStyles`** | `string` | _Optional_ | Custom CSS properties that should be applied to that section, e.g. `border: 2px dashed #ff0000;` -**`sectionLayout`** | `string` | _Optional_ | Specify which CSS layout will be used to responsively place items. Can be either `auto` (which uses flex layout), or `grid`. If `grid` is selected, then `itemCountX` and `itemCountY` may also be set. Defaults to `auto` -**`itemCountX`** | `number` | _Optional_ | The number of items to display per row / horizontally. If not set, it will be calculated automatically based on available space. Can only be set if `sectionLayout` is set to `grid`. Must be a whole number between `1` and `12` -**`itemCountY`** | `number` | _Optional_ | The number of items to display per column / vertically. If not set, it will be calculated automatically based on available space. If `itemCountX` is set, then `itemCountY` can be calculated automatically. Can only be set if `sectionLayout` is set to `grid`. Must be a whole number between `1` and `12` +**`sectionLayout`** | `string` | _Optional_ | Specify which CSS layout will be used to responsively place items. Can be either `auto` (which uses flex layout), or `grid`. Defaults to `auto`. Setting `itemCountX` or `itemCountY` below will also switch the section to grid layout automatically +**`itemCountX`** | `number` | _Optional_ | Number of items per row / horizontally. If not set, it will be calculated automatically based on available space. Setting this switches the section to grid layout. Must be a whole number between `1` and `12`; values above `8` rely on the grid's responsive column sizing (no explicit minimum-width rule) +**`itemCountY`** | `number` | _Optional_ | Number of explicit rows before items flow into implicit rows. Setting this switches the section to grid layout. Must be a whole number between `1` and `12`. Row heights size to their content (section heights follow content in the masonry layout) **`hideForUsers`** | `string[]` | _Optional_ | Current section will be visible to all users, except for those specified in this list **`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list **`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false` diff --git a/docs/credits.md b/docs/credits.md index 3d50547756..ae2712b640 100644 --- a/docs/credits.md +++ b/docs/credits.md @@ -41,7 +41,6 @@ At it's core, the application uses [**Vue.js**](https://github.com/vuejs/vue), a - [`vue-material-tabs`](https://github.com/jairoblatt/vue-material-tabs) - Tab view component by @jairoblatt `MIT` - [`VJsoneditor`](https://github.com/yansenlei/VJsoneditor) - Interactive JSON editor component by @yansenlei `MIT` - Forked from [`JsonEditor`](https://github.com/josdejong/jsoneditor) by @josdejong `Apache-2.0 License` -- [`vue-toasted`](https://github.com/shakee93/vue-toasted) - Toast notification component by @shakee93 `MIT` - [`vue-swatches`](https://github.com/saintplay/vue-swatches) - Color palete picker by @saintplay `MIT` diff --git a/docs/developing.md b/docs/developing.md index 85a414f231..2e6e9a6a19 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -51,7 +51,7 @@ Dashy should now be being served on . Hot reload is enab #### Utils and Checks -- **`yarn validate-config`** - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with `yarn validate-config` or `docker exec -it [container-id] yarn validate-config`. Your config file needs to be in `/user-data/conf.yml` (or within your Docker container at `/app/user-data/conf.yml`). This will first check that your YAML is valid, and then validates it against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json). +- **`yarn validate-config`** - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with `yarn validate-config` or `docker exec -it [container-id] yarn validate-config`. Your config file needs to be in `/user-data/conf.yml` (or within your Docker container at `/app/user-data/conf.yml`). This will first check that your YAML is valid, and then validates it against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/config/ConfigSchema.json). - **`yarn health-check`** - Checks that the application is up and running on it's specified port, and outputs current status and response times. Useful for integrating into your monitoring service, if you need to maintain high system availability #### Alternate Start Commands @@ -76,10 +76,10 @@ You can set variables either in your environment, or using the [`.env`](https:// - `PORT` - The port to expose the running application on - `HOST` - The host that Dashy is running on, domain or IP - `BASE_URL` - The default base path for serving up static assets -- `VUE_APP_DOMAIN` - Usually the same as BASE_URL, but accessible in frontend +- `VITE_APP_DOMAIN` - Usually the same as BASE_URL, but accessible in frontend - `INTEGRITY` - Should enable SRI for build script and link resources - `IS_DOCKER` - Computed automatically on build. Indicates if running in container -- `VUE_APP_VERSION` - Again, set automatically using package.json during build time +- `VITE_APP_VERSION` - Again, set automatically using package.json during build time - `BACKUP_DIR` - Directory for conf.yml backups ### Environment Modes diff --git a/docs/development-guides.md b/docs/development-guides.md index e7e2059edc..7aa7f3be4c 100644 --- a/docs/development-guides.md +++ b/docs/development-guides.md @@ -20,7 +20,7 @@ Adding a new theme is really easy. There're two things you need to do: Pass the ### 1. Add Theme Name -Choose a snappy name for your theme, and add it to the `builtInThemes` array inside [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L27). +Choose a snappy name for your theme, and add it to the `builtInThemes` array inside [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js#L27). ### 2. Write some Styles @@ -127,9 +127,9 @@ computed: { Then, where you want to get the users value within your component, use something like: `this.appConfig.myProperty`. If the user hasn't specified the value, Don't forget to have a fallback or default for it. -If you have a default fallback value, then this would typically be specified in the [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js) file. +If you have a default fallback value, then this would typically be specified in the [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js) file. -You will now need to add the definition of your new attribute into the [ConfigSchema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json). This will make it available in the UI config editor, and also ensure that the config validation check doesn't fail. +You will now need to add the definition of your new attribute into the [ConfigSchema](https://github.com/Lissy93/dashy/blob/master/src/utils/config/ConfigSchema.json). This will make it available in the UI config editor, and also ensure that the config validation check doesn't fail. For example: ```json @@ -156,8 +156,8 @@ Finally, add your new property to the [`configuring.md`](./configuring.md) API d Checklist: - [ ] Ensure the new attribute is actually necessary, and nothing similar already exists -- [ ] Update the [Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json) with the parameters for your new option -- [ ] If required, set a default or fallback value (usually in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js)) +- [ ] Update the [Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/config/ConfigSchema.json) with the parameters for your new option +- [ ] If required, set a default or fallback value (usually in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js)) - [ ] Document the new value in [`configuring.md`](./configuring.md), and if required under the relevant section in the docs - [ ] Ensure your changes are backwards compatible, and that nothing breaks if the attribute isn't specified @@ -210,14 +210,14 @@ For some pages (such as the login page, the minimal start page, etc) the basic p ### 1. Add the route name to the should hide array -In [`./src/utils/defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js), there's an array called `hideFurnitureOn`. Append the name of the route (the same as it appears in [`router.js`](https://github.com/Lissy93/dashy/blob/master/src/router.js)) here. +In [`./src/utils/config/defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js), there's an array called `hideFurnitureOn`. Append the name of the route (the same as it appears in [`router.js`](https://github.com/Lissy93/dashy/blob/master/src/router.js)) here. ### 2. Add the conditional to the structural component to hide First, import the helper function: ```javascript -import { shouldBeVisible } from '@/utils/SectionHelpers'; +import { shouldBeVisible } from '@/utils/config/SectionHelpers'; ``` Then you can create a computed value, that calls this function, passing in the route name: @@ -250,9 +250,9 @@ All environmental variables are optional. Currently there are not many environme You can set variables either in your environment, or using the [`.env`](https://github.com/Lissy93/dashy/blob/master/.env) file. -Any environmental variables used by the frontend are preceded with `VUE_APP_`. Vue will merge the contents of your `.env` file into the app in a similar way to the ['dotenv'](https://github.com/motdotla/dotenv) package, where any variables that you set on your system will always take preference over the contents of any `.env` file. +Any environmental variables used by the frontend are preceded with `VITE_APP_`. Vite will merge the contents of your `.env` file into the app in a similar way to the ['dotenv'](https://github.com/motdotla/dotenv) package, where any variables that you set on your system will always take preference over the contents of any `.env` file. -If add any new variables, ensure that there is always a fallback (define it in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js)), so as to not cause breaking changes. Don't commit the contents of your `.env` file to git, but instead take a few moments to document what you've added under the appropriate section. Try and follow the concepts outlined in the [12 factor app](https://12factor.net/config). +If add any new variables, ensure that there is always a fallback (define it in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js)), so as to not cause breaking changes. Don't commit the contents of your `.env` file to git, but instead take a few moments to document what you've added under the appropriate section. Try and follow the concepts outlined in the [12 factor app](https://12factor.net/config). --- @@ -280,7 +280,7 @@ Firstly, create a new `.vue` file under [`./src/components/Widgets`](https://git import axios from 'axios'; import WidgetMixin from '@/mixins/WidgetMixin'; -import { widgetApiEndpoints } from '@/utils/defaults'; +import { widgetApiEndpoints } from '@/utils/config/defaults'; export default { mixins: [WidgetMixin], @@ -341,7 +341,7 @@ computed: { #### **Adding an API Endpoint** -If your widget makes a data request, then add the URL for the API endpoint to the `widgetApiEndpoints` array in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L207) +If your widget makes a data request, then add the URL for the API endpoint to the `widgetApiEndpoints` array in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/config/defaults.js#L207) ```javascript widgetApiEndpoints: { @@ -353,7 +353,7 @@ widgetApiEndpoints: { Then in your widget file: ```javascript -import { widgetApiEndpoints } from '@/utils/defaults'; +import { widgetApiEndpoints } from '@/utils/config/defaults'; ``` For GET requests, you may need to add some parameters onto the end of the URL. We can use another computed property for this, for example: diff --git a/docs/management.md b/docs/management.md index e2ab9bd0bf..b63f9b1355 100644 --- a/docs/management.md +++ b/docs/management.md @@ -806,7 +806,7 @@ server { } ``` -To use HTML5 history mode (the default - controlled via the `VUE_APP_ROUTING_MODE` build-time env var), replace the inside of the location block with: `try_files $uri $uri/ /index.html;`. +To use HTML5 history mode (the default - controlled via the `VITE_APP_ROUTING_MODE` build-time env var), replace the inside of the location block with: `try_files $uri $uri/ /index.html;`. Then upload the build contents of Dashy's dist directory to that location. For example: `scp -r ./dist/* [username]@[server_ip]:/var/www/dashy/html` diff --git a/docs/pages-and-sections.md b/docs/pages-and-sections.md index 38f4b2e24d..32b75587b5 100644 --- a/docs/pages-and-sections.md +++ b/docs/pages-and-sections.md @@ -1,5 +1,25 @@ # Pages and Sections +## Page Metadata + +Set your dashboard's branding under `pageInfo` + +```yaml +pageInfo: + title: My Dashboard # Used for main h1 title, and browser tab text + description: Home server links + logo: /web-icons/my-logo.png # path/URL to optional logo to display next to title + favicon: 'https://example.com/path/to/icon' # path/URL to a favicon (shows in browser tab) + color: '#2a7cf0' # Hex color, to set the browser/address bar color on mobile (supported browsers only) + footer: '© 2026 Me' # Optional text or HTML content, to display in the pages footer +``` + +If you have multiple configs/pages, then these values swap automatically as you navigate between sub-pages. + +The only caveat being, if you install Dashy as a PWA, the installed app's name, icon, and splash-screen colour come from the bundled `manifest.webmanifest` (baked at build time) rather than `pageInfo`. Runtime values only apply when browsing in a regular tab or browser. + +--- + ## Multi-Page Support You can have additional pages within your dashboard, with each having it's own config file. The config files for sub-pages can either be stored locally, or hosted separately. A link to each additional page will be displayed in the navigation bar. @@ -65,9 +85,71 @@ The following example shows creating a config, publishing it as a [Gist](https:/ Only top-level fields supported by sub-pages are `pageInfo` and `sections`. The `appConfig` and `pages` will always be inherited from your main `conf.yml` file. Other than that, sub-pages behave exactly the same as your default view, and can contain sections, items, widgets and page info like nav links, title and logo. -Note that since page paths are required by the router, they are set at build-time, not run-time, and so a rebuild (happens automatically) is required for changes to page paths to take effect (this only applies to changes to the `pages` array, rebuild isn't required for editing page content). +### URL Structure + +Every view in Dashy shares the same URL shape, so any config can be reached from any view: + +``` +/ Landing — whichever view you set as the default +/ Root config in +// Sub-config in +///
Single section of in +//main/
Single section of the root config (main is a reserved page id) +``` + +`` is one of `home`, `minimal`, or `workspace`. `` is the sub-config id — the sub-page's `name` (from the `pages` array) converted to lowercase-and-dashes (emoji and other non-word characters stripped). `
` follows the same slugging rules. Workspace has no single-section URL; it uses its sidebar instead. + +Examples: + +``` +/home Home view, main config +/home/homelab Home view, "Homelab" sub-config +/home/homelab/media Home view, "Homelab" sub-config, "Media" section only +/home/main/getting-started Home view, main config, "Getting Started" section only +/minimal/homelab Minimal view, "Homelab" sub-config +/minimal/homelab/media Minimal view, "Homelab" sub-config, "Media" section pre-selected +/workspace/homelab Workspace view, "Homelab" sub-config +``` + +The view switcher, sub-page nav links, and section deep-links all preserve your current view and sub-page — so clicking through a single-section view and then hitting "back to all" returns you to the same sub-page you came from. + +--- + +## Layout + +`appConfig.layout` controls how your sections sit on the page: + +- `auto` (default): masonry grid, shorter sections fill the gaps under taller ones +- `horizontal`: sections stacked top to bottom, each full width +- `vertical`: sections side by side in columns + +You can also switch between these from the settings menu. Add `appConfig.colCount` to force a specific number of columns. + +### Making a section wider + +Use `displayData.cols` (1 to 5) to make a section span extra columns: + +```yaml +- name: Important Links + displayData: + cols: 2 + collapsed: false + items: [...] +``` + +Section heights follow their content, so there's no `rows` option. + +### Items inside a section + +Items wrap responsively by default. The useful knobs on `displayData`: + +- `itemSize`: `small`, `medium` (default), or `large` (large tiles also show a description) +- `sortBy`: `alphabetical`, `reverse-alphabetical`, `most-used`, `last-used`, `random` +- `sectionLayout: grid` plus `itemCountX` and/or `itemCountY` if you want a fixed grid instead of auto wrapping + +See [configuring.md](./configuring.md#sectiondisplaydata-optional) for the full list of options. -## Sub-Items +### Sub-Items A normal section will contain zero or more items, for example: diff --git a/docs/theming.md b/docs/theming.md index e538a91efa..2f300b0f4c 100644 --- a/docs/theming.md +++ b/docs/theming.md @@ -12,25 +12,57 @@ The following content requires that you have a basic understanding of CSS. If yo ## How Theme-Switching Works -The theme switching is done by simply changing the `data-theme` attribute on the root DOM element, which can then be targeted by CSS. First off, in order for the theme to show up in the theme switcher, it needs to be added to the config file, under `appConfig.cssThemes`, either as a string, or an array of strings for multiple themes. For example: +The theme switching is done by simply changing the `data-theme` attribute on the root DOM element, which can then be targeted by CSS. All colors and styles are managed with CSS variables. + +The theme switcher in the UI will list all themes defined in [here](github.com/Lissy93/dashy/blob/3.3.1/src/utils/defaults.js#L50), as well as any extras that you add yourself under `appConfig.cssThemes`. Then, when a theme is selected, any CSS within `html[data-theme='my-theme']{}` will be applied. + +To apply a default theme to your instance, set `appConfig.theme` (or, use `dayTheme` and `nightTheme` to adjust according to your OS light/dark preferences). + +## Adding Your Own Theme + +### Option 1: Colors-only, in `conf.yml` + +Quickest path when you just want to change colors. Name the theme under `cssThemes` so it shows in the dropdown, then list your colors under `customColors`: ```yaml appConfig: - cssThemes: ['tiger', 'another-theme'] + theme: mytheme + cssThemes: [mytheme] + customColors: + mytheme: + primary: '#ff6b6b' + background: '#1a1a2e' + background-darker: '#0f0f1e' ``` -You can now create a block to target you're theme with `html[data-theme='my-theme']{}` and set some styles. The easiest method is by setting CSS variables, but you can also directly override elements by their selector. As an example, see the [built-in CSS themes](https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss). +Reload Dashy and `mytheme` appears in the dropdown. Any of the [CSS variables](#css-variables) can go here. + +### Option 2: Full CSS file + +Use this when you want more than colors (fonts, backgrounds, layout tweaks), or a portable file you can share between instances. + +Drop a CSS file into the directory you mount for `conf.yml` (usually `./user-data/`). Dashy serves that directory as static files at the site root, so the stylesheet is fetchable at `/mytheme.css`: ```css -html[data-theme='tiger'] { - --primary: #f58233; - --background: #0b1021; +/* user-data/mytheme.css */ +html[data-theme='mytheme'] { + --primary: #ff6b6b; + --background: #1a1a2e; + --background-darker: #0f0f1e; + /* anything inside this block only applies when mytheme is active */ } ``` -Finally, from the UI use the theme dropdown menu to select your new theme, and your styles will be applied. +Then wire it up: -You can also set `appConfig.theme` to pre-select a default theme, which will be applied immediately after deployment. +```yaml +appConfig: + theme: mytheme + cssThemes: [mytheme] + externalStyleSheet: /mytheme.css +``` + +`externalStyleSheet` also takes a full `https://` URL if you'd rather host the file on a CDN or a repo, and it accepts an array to load several at once. See [Loading External Stylesheets](#loading-external-stylesheets) for more. ## Modifying Theme Colors @@ -44,7 +76,7 @@ Themes can be modified either through the UI, using the color picker menu (to th By default, any color modifications made to the current theme through the UI will only be applied locally. If you need these settings to be set globally, then click the 'Export' button, to get the color codes and variable names, which can then be backed up, or saved in your config file. -Custom colors are saved relative the the base theme selected. So if you switch themes after setting custom colors, then you're settings will no longer be applied. You're changes are not lost though, and switching back to the original theme will see your styles reapplied. +Custom colors are saved relative to the base theme selected. So if you switch themes after setting custom colors, then your settings will no longer be applied. Your changes aren't lost though, and switching back to the original theme will see your styles reapplied. If these values are specified in your `conf.yml` file, then it will look something like the below example. Note that in YAML, values or keys which contain special characters, must be wrapped in quotes. @@ -58,15 +90,11 @@ appConfig: primary: '#8be9fd' ``` -## Adding your own Theme - -User-defined styles and custom themes should be defined in `./src/styles/user-defined-themes.scss`. If you're using Docker, you can pass your own stylesheet in using the `--volume` flag. E.g. `v ./my-themes.scss:/app/src/styles/user-defined-themes.scss`. Don't forget to pass your theme name into `appConfig.cssThemes` so that it shows up on the theme-switcher dropdown. - ## Setting Custom CSS in the UI Custom CSS can be developed, tested and applied directly through the UI. Although you will need to make note of your changes to apply them across instances. -This can be done from the Config menu (spanner icon in the top-right), under the Custom Styles tab. This is then associated with `appConfig.customCss` in local storage. Styles can also be directly applied to this attribute in the config file, but this may get messy very quickly if you have a lot of CSS. +This can be done from the Config menu (spanner icon, inside the options panel in the header), under the Custom Styles tab. This is then associated with `appConfig.customCss` in local storage. Styles can also be directly applied to this attribute in the config file, but this may get messy very quickly if you have a lot of CSS. ## Page-Specific Styles @@ -111,13 +139,17 @@ Fonts which are not being used by the current theme are **not** fetched on page Full credit to the typographers behind each of the included fonts. Specifically: Matt McInerney, Christian Robertson, Haley Fiege, Peter Hull, Cyreal and the legendary Vernon Adams +## Changing browser address bar / tab color + +Some browsers support setting a color, which will apply a tint to the address bar, and task switcher card title bar. To enable this, set `pageInfo.color` to any valid CSS color (e.g. `#ff00a7`, `rebeccapurple`, `rgb(40, 60, 120)`). Note that browser support for this is still limited (Android Chrome, Safari iOS 15+ and some recent mobile Chromium browsers). This does not apply if you've installed the PWA. For more page-specific browser and UI options, see [Pages and Sections](/docs/pages-and-sections.md). + ## CSS Variables All colors as well as other variable values (such as borders, border-radius, shadows) are specified as CSS variables. This makes theming the application easy, as you only need to change a given color or value in one place. You can find all variables in [`color-palette.scss`](https://github.com/Lissy93/dashy/blob/master/src/styles/color-palette.scss) and the themes which make use of these color variables are specified in [`color-themes.scss`](https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss) CSS variables are simple to use. You define them like: `--background: #fff;` and use them like: `body { background-color: var(--background); }`. For more information, see this guide on using [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties). -You can determine the variable used by any given element, and visualize changes using the browser developer tools (Usually opened with `F12`, or Options --> More --> Developer Tools). Under the elements tab, click the Element Selector icon (usually top-left corner), you will then be able to select any DOM element on the page by hovering and clicking it. In the CSS panel you will see all styles assigned to that given element, including CSS variables. Click a variable to see it's parent value, and for color attributes, click the color square to modify the color. For more information, see this [getting started guide](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), and these articles on [selecting elements](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Select_an_element) and [inspecting and modifying colors](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Inspect_and_select_colors). +You can determine the variable used by any given element, and visualize changes using the browser developer tools (Usually opened with `F12`, or Options --> More --> Developer Tools). Under the elements tab, click the Element Selector icon (usually top-left corner), you will then be able to select any DOM element on the page by hovering and clicking it. In the CSS panel you will see all styles assigned to that given element, including CSS variables. Click a variable to see its parent value, and for color attributes, click the color square to modify the color. For more information, see this [getting started guide](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), and these articles on [selecting elements](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Select_an_element) and [inspecting and modifying colors](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Inspect_and_select_colors). ### Top-Level Variables @@ -149,16 +181,16 @@ You can target specific elements on the UI with these variables. All are optiona - `--item-text-color` - The text and icon color for items. Defaults to `--primary` - `--item-group-outer-background` - The background color for the outer part of a section (including section head). Defaults to `--primary` - `--item-group-background` - The background color for the inner part of item groups. Defaults to `#0b1021cc` (semi-transparent black) -- `--item-group-heading-text-color` - The text color for section headings. Defaults to `--item-group-background`; +- `--item-group-heading-text-color` - The text color for section headings. Defaults to `--item-group-background` - `--item-group-heading-text-color-hover` - The text color for section headings, when hovered. Defaults to `--background` - `--config-code-background` - Background color for the JSON editor in the config menu. Defaults to `#fff` (white) - `--config-code-color` - Text color for the non-highlighted code within the JSON editor. Defaults to `--background` - `--config-settings-color` - The background for the config/ settings pop-up modal. Defaults to `--primary` - `--config-settings-background` - The text color for text within the settings container. Defaults to `--background-darker` - `--scroll-bar-color` - Color of the scroll bar thumb. Defaults to `--primary` -- `--scroll-bar-background` Color of the scroll bar blank space. Defaults to `--background-darker` -- `--highlight-background` Fill color for text highlighting. Defaults to `--primary` -- `--highlight-color` Text color for selected/ highlighted text. Defaults to `--background` +- `--scroll-bar-background` - Color of the scroll bar blank space. Defaults to `--background-darker` +- `--highlight-background` - Fill color for text highlighting. Defaults to `--primary` +- `--highlight-color` - Text color for selected/ highlighted text. Defaults to `--background` - `--toast-background` - Background color for the toast info popup. Defaults to `--primary` - `--toast-color` - Text, icon and border color in the toast info popup. Defaults to `--background` - `--welcome-popup-background` - Background for the info pop-up shown on first load. Defaults to `--background-darker` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index ae0513ad0a..4e58733e3e 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -13,6 +13,10 @@ - [404 On Static Hosting](#404-on-static-hosting) - [404 from Mobile Home Screen](#404-after-launch-from-mobile-home-screen) - [404 On Multi-Page Apps](#404-on-multi-page-apps) +- [Dashy hosted at a sub-path](#dashy-hosted-at-a-sub-path-eg-examplecomdashy) +- [Sub-page shows "Unable to find config for ..."](#sub-page-shows-unable-to-find-config-for-) +- [Sub-page missing from nav, or won't open when clicked](#sub-page-missing-from-nav-or-wont-open-when-clicked) +- [Sub-page ignores its theme, layout or appConfig](#sub-page-ignores-its-theme-layout-or-appconfig) - [Yarn Build or Run Error](#yarn-error) - [Remote Config Not Loading](#remote-config-not-loading) - [High CPU or RAM Usage on Startup](#high-cpu-or-ram-usage-on-startup) @@ -149,16 +153,16 @@ Content-Security-Policy: frame-ancestors 'self' https://[dashy-location]/ If you're seeing Dashy's 404 page on initial load/ refresh, and then the main app when you go back to Home, then this is likely caused by the Vue router, and if so can be fixed in one of two ways. -The first solution is to switch the routing mode, from HTML5 `history` mode to `hash` mode, by rebuilding Dashy with the `VUE_APP_ROUTING_MODE=hash` build-time environment variable set. +The first solution is to switch the routing mode, from HTML5 `history` mode to `hash` mode, by rebuilding Dashy with the `VITE_APP_ROUTING_MODE=hash` build-time environment variable set. -If this works, but you wish to continue using HTML5 history mode, then a bit of extra [server configuration](/docs/management.md#web-server-configuration) is required. This is explained in more detaail in the [Vue Docs](https://router.vuejs.org/guide/essentials/history-mode.html). Once completed, you can then use `VUE_APP_ROUTING_MODE=history` (the default) again, for neater URLs. +If this works, but you wish to continue using HTML5 history mode, then a bit of extra [server configuration](/docs/management.md#web-server-configuration) is required. This is explained in more detaail in the [Vue Docs](https://router.vuejs.org/guide/essentials/history-mode.html). Once completed, you can then use `VITE_APP_ROUTING_MODE=history` (the default) again, for neater URLs. --- ## 404 after Launch from Mobile Home Screen Similar to the above issue, if you get a 404 after using iOS and Android's "Add to Home Screen" feature, then this is caused by Vue router. -It can be fixed by rebuilding Dashy with the `VUE_APP_ROUTING_MODE=hash` build-time environment variable set. +It can be fixed by rebuilding Dashy with the `VITE_APP_ROUTING_MODE=hash` build-time environment variable set. See also: [#628](https://github.com/Lissy93/dashy/issues/628), [#762](https://github.com/Lissy93/dashy/issues/762) @@ -166,12 +170,60 @@ See also: [#628](https://github.com/Lissy93/dashy/issues/628), [#762](https://gi ## 404 On Multi-Page Apps -Similar to above, if you get a 404 error when visiting a page directly on multi-page apps, then this can be fixed by rebuilding Dashy with the `VUE_APP_ROUTING_MODE=hash` build-time environment variable set, then refreshing the page. +Similar to above, if you get a 404 error when visiting a page directly on multi-page apps, then this can be fixed by rebuilding Dashy with the `VITE_APP_ROUTING_MODE=hash` build-time environment variable set, then refreshing the page. See also: [#670](https://github.com/Lissy93/dashy/issues/670), [#763](https://github.com/Lissy93/dashy/issues/763) --- +## Dashy hosted at a sub-path (e.g. `example.com/dashy`) + +If the homepage works but sub-page links 404, or assets fail to load, it's almost always the base path. +Rebuild with `BASE_URL` set to the sub-path - leading slash, no trailing slash: + +Vue Router uses this to prefix every route. Without it, links resolve to `/home/...` instead of `/dashy/home/...` and skip your reverse proxy altogether. More detail in [web-server configuration](/docs/management.md#web-server-configuration). + +--- + +## Sub-page shows "Unable to find config for ..." + +This means Dashy couldn't match the URL segment to any entry in your `pages:` list. A few causes: + +### Old bookmark from before an upgrade +Slugs are now trimmed more aggressively (e.g. `🌐 Command Center` used to give `-command-center`, now gives `command-center`). Re-bookmark from the nav, or update the URL by hand. + +### The page was renamed or removed +The URL no longer resolves to anything. Check the `pages:` array in `conf.yml` and confirm the sub-page still exists. + +### The path points at an unreachable file +If the sub-config YAML can't be fetched (404, CORS, auth), you'll see "Unable to load config from ..." instead. Verify the `path:` is correct, reachable from the browser, and CORS-open if remote. + +### Page name literally "Main" +`main` is reserved in the URL scheme to mean "the root config". A page named "Main" becomes reachable at `/home/main-page` (not `/home/main`). Rename the page if that's confusing. + +### Service worker is serving a stale app +Hard-refresh (Ctrl + F5) after a major upgrade. The PWA cache may still be pointing at old routes. Also see [Styles and Assets not Updating](#styles-and-assets-not-updating). + +--- + +## Sub-page missing from nav, or won't open when clicked + +If page defined in `pages:` is nowhere in the nav bar, or its link goes to a different page, then there's probably something wrong with the name you chose. Note that Dashy strips out any non-alphanumeric characters. +- Ensure each page does have a valid `name` and `path` field +- Check two pages don't have the same/similar name +- Check each page has a name which has at least some alpha-numeric characters +- Very long names could be being stripped/truncated + +--- + +## Sub-page ignores its theme, layout or appConfig + +This is by design. Only the `appConfig` from your root `conf.yml` is used - theme, layout, iconSize, statusCheck, etc. are inherited globally so behaviour stays consistent across pages. + +If you put `appConfig` inside a sub-page YAML, it's silently dropped on load. Move the values to the root config. See [Restrictions](/docs/pages-and-sections.md#restrictions). + +--- + ## Yarn Error For more info, see [Issue #1](https://github.com/Lissy93/dashy/issues/1) @@ -213,7 +265,7 @@ When the Dashy container first starts, it runs a Vue production build in paralle **To work around it:** -1. **Allocate at least 1 GB of RAM to the container** — 2 GB is recommended on Raspberry Pi or low-powered VMs. Anything below 512 MB is unlikely to complete the first build. +1. **Allocate at least 1 GB of RAM to the container** - 2 GB is recommended on Raspberry Pi or low-powered VMs. Anything below 512 MB is unlikely to complete the first build. 2. **Set explicit Docker resource limits** so the build can't starve other services on the same host: ```yaml services: @@ -225,8 +277,8 @@ When the Dashy container first starts, it runs a Vue production build in paralle memory: 2g cpus: '1.5' ``` -3. **Wait it out** — once the build completes, idle CPU drops to near zero and idle RAM is typically under 100 MB. If you watch `docker stats`, you'll see the spike taper off. -4. If the spike never tapers (i.e., Dashy stays at 100% CPU forever and never serves the page), see [Heap limit Allocation failed](#ineffective-mark-compacts-near-heap-limit-allocation-failed) below — that usually means the build was killed mid-way and is being retried. +3. **Wait it out** - once the build completes, idle CPU drops to near zero and idle RAM is typically under 100 MB. If you watch `docker stats`, you'll see the spike taper off. +4. If the spike never tapers (i.e., Dashy stays at 100% CPU forever and never serves the page), see [Heap limit Allocation failed](#ineffective-mark-compacts-near-heap-limit-allocation-failed) below - that usually means the build was killed mid-way and is being retried. See also: [#1585](https://github.com/Lissy93/dashy/issues/1585), [#969](https://github.com/Lissy93/dashy/issues/969), [#1500](https://github.com/Lissy93/dashy/issues/1500), [#877](https://github.com/Lissy93/dashy/issues/877) @@ -262,7 +314,7 @@ See also [#624](https://github.com/Lissy93/dashy/issues/624) ## Container Crashes or Restart Loop After Saving Config -If your Dashy container crashes or enters a restart loop the moment you click **Save to Disk** in the editor — particularly with logs that include something like: +If your Dashy container crashes or enters a restart loop the moment you click **Save to Disk** in the editor - particularly with logs that include something like: ```text node:_http_outgoing:652 @@ -358,7 +410,7 @@ See also: #479, #409, #507, #491, #341, #520 If your IdP rejects the login with an *"invalid client"* / *"client not found"* error, and your `clientId` is a long numeric value, the cause is almost certainly YAML number parsing. -YAML parses unquoted numeric tokens as Numbers, and JavaScript can't represent integers larger than 2^53 (~16 digits) without losing precision. So an unquoted numeric `clientId` will be silently truncated (e.g. `918756876419824312` → `918756876419824300`), or — for very large values — converted to scientific notation (e.g. `9.187568764198242e+37`), and the IdP will reject it. +YAML parses unquoted numeric tokens as Numbers, and JavaScript can't represent integers larger than 2^53 (~16 digits) without losing precision. So an unquoted numeric `clientId` will be silently truncated (e.g. `918756876419824312` → `918756876419824300`), or - for very large values - converted to scientific notation (e.g. `9.187568764198242e+37`), and the IdP will reject it. The fix is to wrap the `clientId` in quotes in your `conf.yml` so it gets parsed as a string: @@ -454,9 +506,9 @@ You can [check your rate limit status](https://www.docker.com/blog/checking-your ## Config Validation Errors -The configuration file is validated against [Dashy's Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json) using AJV. +The configuration file is validated against [Dashy's Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/config/ConfigSchema.json) using AJV. -First, check that your syntax is valid, using [YAML Validator](https://codebeautify.org/yaml-validator/) or [JSON Validator](https://codebeautify.org/jsonvalidator). If the issue persists, then take a look at the [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json), and verify that the field you are trying to add/ modify matches the required format. You can also use [this tool](https://www.jsonschemavalidator.net/s/JFUj7X9J) to validate your JSON config against the schema, or run `yarn validate-config`. +First, check that your syntax is valid, using [YAML Validator](https://codebeautify.org/yaml-validator/) or [JSON Validator](https://codebeautify.org/jsonvalidator). If the issue persists, then take a look at the [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/config/ConfigSchema.json), and verify that the field you are trying to add/ modify matches the required format. You can also use [this tool](https://www.jsonschemavalidator.net/s/JFUj7X9J) to validate your JSON config against the schema, or run `yarn validate-config`. If you're trying to use a recently released feature, and are getting a warning, this is likely because you've not yet updated the the current latest version of Dashy. @@ -551,7 +603,7 @@ If you've set `PORT` to override the default 8080, the healthcheck honors the sa ### Slow startup on weak hardware -The healthcheck has a `--start-period=30s` grace period before failures count against the container. If your host takes longer than 30 seconds for the initial Vue build to complete (common on Pi 3 or similar), the first few healthchecks will fail and you may briefly see `unhealthy`. After the build finishes, subsequent checks should pass — see [High CPU or RAM Usage on Startup](#high-cpu-or-ram-usage-on-startup) below. +The healthcheck has a `--start-period=30s` grace period before failures count against the container. If your host takes longer than 30 seconds for the initial Vue build to complete (common on Pi 3 or similar), the first few healthchecks will fail and you may briefly see `unhealthy`. After the build finishes, subsequent checks should pass - see [High CPU or RAM Usage on Startup](#high-cpu-or-ram-usage-on-startup) below. See also: [#1410](https://github.com/Lissy93/dashy/issues/1410) @@ -622,7 +674,7 @@ For testing purposes, you can use an addon, which will disable the CORS checks. ## CORS Proxy `connect ECONNREFUSED ...` or `getaddrinfo ENOTFOUND ...` -The target host is unreachable from the Dashy container. If the target is on the same host as Dashy, **don't use `localhost`** — inside a Docker container that resolves to the container itself, not the host. Use the host's LAN IP, the Docker bridge gateway, or `host.docker.internal` (on Docker Desktop). If the target is on a different Docker network, attach Dashy to that network too. +The target host is unreachable from the Dashy container. If the target is on the same host as Dashy, **don't use `localhost`** - inside a Docker container that resolves to the container itself, not the host. Use the host's LAN IP, the Docker bridge gateway, or `host.docker.internal` (on Docker Desktop). If the target is on a different Docker network, attach Dashy to that network too. --- @@ -630,8 +682,8 @@ The target host is unreachable from the Dashy container. If the target is on the To prevent the CORS proxy from being abused as a Server-Side Request Forgery vector, Dashy refuses to proxy a small number of host/scheme combinations by default: -- **Cloud instance metadata services** — `169.254.169.254`, `metadata.google.internal`, and the matching IPv6 forms. These are reserved magic addresses on AWS, Azure, GCP, DigitalOcean, Hetzner, Oracle Cloud and most other providers. A widget that successfully fetches them on a cloud-hosted Dashy can leak the host's IAM credentials, so they're blocked unconditionally. -- **Non-HTTP(S) schemes** — `file://`, `ftp://`, `gopher://`, `javascript:`, `data:`, and similar. The proxy is meant for HTTP APIs only. +- **Cloud instance metadata services** - `169.254.169.254`, `metadata.google.internal`, and the matching IPv6 forms. These are reserved magic addresses on AWS, Azure, GCP, DigitalOcean, Hetzner, Oracle Cloud and most other providers. A widget that successfully fetches them on a cloud-hosted Dashy can leak the host's IAM credentials, so they're blocked unconditionally. +- **Non-HTTP(S) schemes** - `file://`, `ftp://`, `gopher://`, `javascript:`, `data:`, and similar. The proxy is meant for HTTP APIs only. If you're running Dashy in a fully isolated/private environment and you've deliberately decided you want to allow these (for example, you genuinely need to query your cloud provider's metadata API from a widget), you can opt out of all proxy restrictions by setting the environment variable: @@ -639,7 +691,7 @@ If you're running Dashy in a fully isolated/private environment and you've delib DANGEROUSLY_DISABLE_PROXY_RESTRICTIONS=true ``` -The variable is named so loudly because flipping it on a Dashy instance that's exposed to anything other than fully trusted users re-opens the SSRF surface — anyone who can hit `/cors-proxy` can then use Dashy as a relay to reach internal services. **Don't set it on cloud-hosted or internet-exposed deployments.** +The variable is named so loudly because flipping it on a Dashy instance that's exposed to anything other than fully trusted users re-opens the SSRF surface - anyone who can hit `/cors-proxy` can then use Dashy as a relay to reach internal services. **Don't set it on cloud-hosted or internet-exposed deployments.** Note that this is an all-or-nothing escape hatch, not a per-host allowlist. If you only need to reach one specific host that's currently blocked, please open a feature request describing the use case. @@ -726,6 +778,8 @@ export NODE_OPTIONS=--openssl-legacy-provider This will be fixed once [webpack/webpack#17659](https://github.com/webpack/webpack/pull/17659) is merged. +**Update:** This should be fully resolved. Raise a ticket if you're still needing to use those NODE_OPTIONS after upgrade. + --- ## How to Reset Local Settings diff --git a/docs/widgets.md b/docs/widgets.md index d81846f17f..5c98cc5b92 100644 --- a/docs/widgets.md +++ b/docs/widgets.md @@ -1809,13 +1809,13 @@ Displays the number of queries blocked by [Pi-Hole](https://pi-hole.net/). ``` > [!TIP] -> In order to avoid leaking secret data, both `hostname` and `apiKey` can leverage environment variables. Simply pass the name of the variable, which MUST start with `VUE_APP_`. +> In order to avoid leaking secret data, both `hostname` and `apiKey` can leverage environment variables. Simply pass the name of the variable, which MUST start with `VITE_APP_`. ```yaml - type: pi-hole-stats options: - hostname: VUE_APP_pihole_ip - apiKey: VUE_APP_pihole_key + hostname: VITE_APP_pihole_ip + apiKey: VITE_APP_pihole_key ``` > [!IMPORTANT] @@ -1855,13 +1855,13 @@ Displays the number of queries blocked by [Pi-Hole](https://pi-hole.net/). Use t ``` > [!TIP] -> In order to avoid leaking secret data, both `hostname` and `apiKey` can leverage environment variables. Simply pass the name of the variable, which MUST start with `VUE_APP_`. +> In order to avoid leaking secret data, both `hostname` and `apiKey` can leverage environment variables. Simply pass the name of the variable, which MUST start with `VITE_APP_`. ```yaml - type: pi-hole-stats-v6 options: - hostname: VUE_APP_pihole_ip - apiKey: VUE_APP_pihole_key + hostname: VITE_APP_pihole_ip + apiKey: VITE_APP_pihole_key ``` > [!IMPORTANT] @@ -2662,7 +2662,7 @@ Displays storage statistics and file listings from a [Filebrowser Quantum](https useProxy: true options: hostname: http://filebrowser.local:8080 - apiKey: VUE_APP_FILEBROWSER_KEY + apiKey: VITE_APP_FILEBROWSER_KEY source: Documents path: / showRecent: 5 @@ -2678,7 +2678,7 @@ Displays storage statistics and file listings from a [Filebrowser Quantum](https useProxy: true options: hostname: http://filebrowser.local:8080 - apiKey: VUE_APP_FILEBROWSER_KEY + apiKey: VITE_APP_FILEBROWSER_KEY source: Downloads showDetailedStats: true showRecent: 10 @@ -3412,7 +3412,7 @@ Instead, for secrets you should use environmental vairables. You can do this, by setting the environmental variable name as the value, instead of the actual key, and then setting that env var in your container or local environment. -The key can be named whatever you like, but it must start with `VUE_APP_` (to be picked up by Vue). If you need to update any of these values, a rebuild is required (this can be done under the Config menu in the UI, or by running `yarn build` then restarting the container). +The key can be named whatever you like, but it must start with `VITE_APP_` (to be picked up by Vite). If you need to update any of these values, a rebuild is required (this can be done under the Config menu in the UI, or by running `yarn build` then restarting the container). For more infomation about setting and managing your environmental variables, see [Management Docs --> Environmental Variables](/docs/management.md#passing-in-environmental-variables). @@ -3421,13 +3421,13 @@ For example: ```yaml - type: weather options: - apiKey: VUE_APP_WEATHER_TOKEN + apiKey: VITE_APP_WEATHER_TOKEN city: London units: metric hideDetails: true ``` -Then, set `VUE_APP_WEATHER_TOKEN='xxx'` +Then, set `VITE_APP_WEATHER_TOKEN='xxx'` --- diff --git a/index.html b/index.html new file mode 100644 index 0000000000..5d7371534e --- /dev/null +++ b/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + Dashy + + + + +
+ +
+

Dashy

+

Loading...

+ + +
+
+ + + + + + + + + + diff --git a/netlify.toml b/netlify.toml index 9da589bd0c..f40d052f5f 100644 --- a/netlify.toml +++ b/netlify.toml @@ -12,7 +12,7 @@ # Environmental variables for build command [build.environment] NODE_VERSION = "20.11.1" - NODE_OPTIONS = "--openssl-legacy-provider" + YARN_FLAGS = "--ignore-engines" # Redirect the Node endpoints to serverless functions diff --git a/package.json b/package.json index 62aab0b83d..e4a8099a89 100644 --- a/package.json +++ b/package.json @@ -6,29 +6,42 @@ "author": "Alicia Sykes (https://aliciasykes.com)", "scripts": { "start": "node server", - "dev": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve", - "build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build", - "lint": "vue-cli-service lint", + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint src/", "test": "vitest run", "test:watch": "vitest", "test:ui": "vitest --ui", "test:coverage": "vitest run --coverage", "pm2-start": "npx pm2 start server.js", - "build-watch": "vue-cli-service build --watch --mode production", - "build-and-start": "NODE_OPTIONS=--openssl-legacy-provider npm-run-all --parallel build start", + "build-and-start": "npm-run-all --sequential build start", "validate-config": "node services/config-validator", "health-check": "node services/healthcheck", "dependency-audit": "npx improved-yarn-audit --ignore-dev-deps" }, "dependencies": { - "@babel/core": "^7.26.0", - "@formschema/native": "^2.0.0-beta.6", + "@codemirror/autocomplete": "^6.20.1", + "@codemirror/commands": "^6.10.3", + "@codemirror/lang-yaml": "^6.1.3", + "@codemirror/language": "^6.12.3", + "@codemirror/lint": "^6.9.5", + "@codemirror/search": "^6.7.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.41.1", + "@febe95/vue-js-modal": "^3.2.0", + "@jsonforms/core": "^3.7.0", + "@jsonforms/vue": "^3.7.0", + "@jsonforms/vue-vanilla": "^3.7.0", + "@lezer/highlight": "^1.2.3", "@sentry/tracing": "^7.102.1", "@sentry/vue": "^7.102.1", "ajv": "^8.10.0", + "ajv-formats": "^3.0.1", "connect-history-api-fallback": "^1.6.0", "crypto-js": "^4.2.0", "dompurify": "^3.0.8", + "entities": "^7.0.1", "express": "^4.21.0", "express-basic-auth": "^1.2.1", "frappe-charts": "^1.6.2", @@ -40,89 +53,78 @@ "rss-parser": "3.13.0", "rsup-progress": "^3.2.0", "simple-icons": "^16.6.0", - "v-jsoneditor": "^1.4.5", - "v-tooltip": "^2.1.3", - "vue": "^2.7.0", - "vue-i18n": "^8.27.2", - "vue-js-modal": "^2.0.1", - "vue-json-tree-view": "^2.1.6", - "vue-material-tabs": "0.1.5", - "vue-router": "^3.5.3", - "vue-select": "^3.20.2", - "vue-swatches": "^2.1.1", - "vue-toasted": "^1.1.28", - "vuex": "^3.6.2" + "vue": "^3.5.0", + "vue-i18n": "^9.14.0", + "vue-router": "^4.4.0", + "vue-select": "4.0.0-beta.6", + "vue3-json-viewer": "^2.4.1", + "vuex": "^4.1.0", + "yaml": "^2.8.3" }, "devDependencies": { - "@babel/eslint-parser": "^7.25.0", - "@babel/preset-env": "^7.26.0", - "@vitest/ui": "^1.6.0", - "@vue/cli-plugin-babel": "^5.0.8", - "@vue/cli-plugin-eslint": "^5.0.8", - "@vue/cli-plugin-pwa": "^5.0.8", - "@vue/cli-plugin-typescript": "^5.0.8", - "@vue/cli-service": "^5.0.8", - "@vue/eslint-config-standard": "^4.0.0", - "@vue/test-utils": "^1.3.6", - "copy-webpack-plugin": "6.4.0", - "eslint": "^7.32.0", - "eslint-config-airbnb": "^18.0.1", - "eslint-plugin-vue": "^7.9.0", + "@vitejs/plugin-vue": "^5.0.0", + "@vitest/ui": "^4.0.18", + "@vue/compiler-sfc": "^3.5.0", + "@vue/test-utils": "^2.4.0", + "autoprefixer": "^10.4.27", + "eslint": "^8.57.0", + "eslint-plugin-vue": "^9.28.0", "happy-dom": "^20.8.9", "npm-run-all": "^4.1.5", "sass": "^1.77.0", - "sass-loader": "^12.0.0", "supertest": "^7.2.2", - "typescript": "^5.4.4", - "vite-plugin-vue2": "^2.0.3", - "vitest": "^1.6.0", - "vue-cli-plugin-yaml": "^1.0.2", - "vue-svg-loader": "^0.16.0", - "vue-template-compiler": "^2.7.0" + "vite": "^6.2.0", + "vite-plugin-pwa": "^1.0.0", + "vite-svg-loader": "^5.1.0", + "vitest": "^4.0.18" }, "engines": { - "node": ">=16.0.0 <21.6.2" + "node": ">=18.0.0" }, "eslintConfig": { "root": true, "env": { - "node": true + "node": true, + "es2022": true }, "extends": [ - "plugin:vue/essential", - "@vue/standard", - "airbnb-base" + "plugin:vue/vue3-essential", + "eslint:recommended" ], "rules": { "import/no-unresolved": "off", "import/extensions": "off", "arrow-parens": 0, - "no-else-return": 0 + "no-else-return": 0, + "no-console": "off", + "no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_" + } + ], + "vue/multi-word-component-names": "off", + "vue/no-reserved-component-names": "off" }, "parserOptions": { - "parser": "@babel/eslint-parser" + "ecmaVersion": 2022, + "sourceType": "module" }, "overrides": [ { "files": [ "tests/**", - "vitest.config.js" + "vitest.config.mjs", + "vite.config.mjs" ], "rules": { "import/no-extraneous-dependencies": "off", "no-undef": "off", - "global-require": "off", "no-unused-vars": "off" } } ] }, - "babel": { - "presets": [ - "@vue/cli-plugin-babel/preset", - "@babel/preset-env" - ] - }, "postcss": { "plugins": { "autoprefixer": {} @@ -133,17 +135,11 @@ "last 2 versions" ], "resolutions": { - "ejs": "^3.1.10", - "loader-utils": "^2.0.4", - "minimatch": "^3.1.2", "braces": "^3.0.3", "micromatch": "^4.0.8", - "serialize-javascript": "^6.0.2", - "node-forge": "^1.3.1", - "nth-check": "^2.1.1", - "ip": "^2.0.1", "postcss": "^8.4.31", - "tar": "^6.2.1" + "serialize-javascript": "^7.0.3", + "vite": "^6.2.0" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/services/app.js b/services/app.js index 5ccee70238..90bc0b3c85 100644 --- a/services/app.js +++ b/services/app.js @@ -33,8 +33,16 @@ const sslServer = require('./ssl-server'); // TLS-enabled web server const corsProxy = require('./cors-proxy'); // Enables API requests to CORS-blocked services const getUser = require('./get-user'); // Enables server side user lookup -/* Helper functions, and default config */ -const ENDPOINTS = require('../src/utils/defaults').serviceEndpoints; // API endpoint URL paths +/* Service endpoint URL paths (see also serviceEndpoints in src/utils/config/defaults.js) */ +const ENDPOINTS = { + statusPing: '/status-ping', + statusCheck: '/status-check', + save: '/config-manager/save', + rebuild: '/config-manager/rebuild', + systemInfo: '/system-info', + corsProxy: '/cors-proxy', + getUser: '/get-user', +}; /* Indicates for the webpack config, that running as a server */ process.env.IS_SERVER = 'True'; diff --git a/services/config-validator.js b/services/config-validator.js index 372f432aff..6dabe63b1b 100644 --- a/services/config-validator.js +++ b/services/config-validator.js @@ -7,7 +7,7 @@ const fs = require('fs'); // For opening + reading files const yaml = require('js-yaml'); // For parsing YAML const Ajv = require('ajv'); // For validating with schema -const schema = require('../src/utils/ConfigSchema.json'); +const schema = require('../src/utils/config/ConfigSchema.json'); /* Tell AJV to use strict mode, and report all errors */ const validatorOptions = { diff --git a/services/rebuild-app.js b/services/rebuild-app.js index 2b748c2d22..8a335f70b5 100644 --- a/services/rebuild-app.js +++ b/services/rebuild-app.js @@ -5,7 +5,7 @@ const { exec } = require('child_process'); module.exports = () => new Promise((resolve, reject) => { - const buildProcess = exec('NODE_OPTIONS="--max-old-space-size=512" npm run build'); // Trigger the build command + const buildProcess = exec('yarn build'); // Trigger the build command let output = ''; // Will store console output @@ -17,11 +17,7 @@ module.exports = () => new Promise((resolve, reject) => { // Handle errors, by sending the reject buildProcess.on('error', (error) => { - reject(Error({ - success: false, - error, - output, - })); + reject({ success: false, error, output }); }); // When finished, check success, make message and resolve response diff --git a/src/App.vue b/src/App.vue index 9ed5f0be7e..415d45771c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,7 +5,7 @@
-