dashy/docs/development-guides/index.html
2026-03-15 15:43:58 +00:00

211 lines
No EOL
105 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-development-guides" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.9.2">
<title data-rh="true">Development Guides | Dashy</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="dashy, dashboard, homelab, self-hosted, docker, homepage"><meta data-rh="true" property="og:type" content="website"><meta data-rh="true" property="og:url" content="https://dashy.to"><meta data-rh="true" property="og:image" content="https://dashy.to/img/dashy.png"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" name="twitter:title" content="Dashy — The Ultimate Homepage for your Homelab"><meta data-rh="true" name="twitter:description" content="Dashy is a self-hosted dashboard app for your homelab. Manage all your services, with status checks, widgets, themes and more."><meta data-rh="true" name="twitter:image" content="https://dashy.to/img/dashy.png"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Development Guides | Dashy"><meta data-rh="true" name="description" content="A series of short tutorials, to guide you through the most common development tasks."><meta data-rh="true" property="og:description" content="A series of short tutorials, to guide you through the most common development tasks."><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://dashy.to/docs/development-guides"><link data-rh="true" rel="alternate" href="https://dashy.to/docs/development-guides" hreflang="en"><link data-rh="true" rel="alternate" href="https://dashy.to/docs/development-guides" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Development Guides","item":"https://dashy.to/docs/development-guides"}]}</script><link rel="preconnect" href="https://pixelflare.cc">
<link rel="preconnect" href="https://cdn.as93.net">
<link rel="dns-prefetch" href="https://api.github.com">
<link rel="dns-prefetch" href="https://no-track.as93.net">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"Dashy","url":"https://dashy.to","description":"The Ultimate Homepage for your Homelab","publisher":{"@type":"Person","name":"Alicia Sykes","url":"https://aliciasykes.com"}}</script>
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#54bff7">
<script src="https://no-track.as93.net/js/script.js" defer="defer" data-domain="dashy.to"></script><link rel="stylesheet" href="/assets/css/styles.2ec658c5.css">
<script src="/assets/js/runtime~main.1a1620af.js" defer="defer"></script>
<script src="/assets/js/main.371f9848.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||"dark"),document.documentElement.setAttribute("data-theme-choice",t||"dark")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div class="banner_woPo"><a class="link_ecgS" title="View the changelog, to see what&#x27;s new!" href="/updates">Dashy <!-- -->V3.1.11<!-- --> is now live 🚀</a><a class="link2_y3x6" title="View the changelog, to see what&#x27;s new!" href="/updates">See what&#x27;s new…</a><button class="closeBtn_fC0A" title="Dismiss update, and don&#x27;t show again" aria-label="Dismiss update, and don&#x27;t show again">×</button></div><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/img/dashy.png" alt="Dashy Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/img/dashy.png" alt="Dashy Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Dashy</b></a><a href="https://github.com/lissy93/dashy" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><a href="https://demo.dashy.to" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Live Demo<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><a class="navbar__item navbar__link" href="/docs/quick-start">Quick Start</a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs">Documentation</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><div class="navbar__search searchBarContainer_NW3z" dir="ltr"><input placeholder="Search" aria-label="Search" class="navbar__search-input searchInput_YFbd" value=""><div class="loadingRing_RJI3 searchBarLoadingRing_YnHq"><div></div><div></div><div></div><div></div></div></div></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_z2l0"><div class="docsWrapper_hBAB"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docRoot_UBD9"><aside class="theme-doc-sidebar-container docSidebarContainer_YfHR"><div class="sidebarViewport_aRkj"><div class="sidebar_njMd"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/docs/quick-start"><span title="Running Dashy" class="categoryLinkLabel_W154">Running Dashy</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/docs/icons"><span title="Feature Docs" class="categoryLinkLabel_W154">Feature Docs</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role="button" aria-expanded="true" href="/docs/showcase"><span title="Community" class="categoryLinkLabel_W154">Community</span></a></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/docs/showcase"><span title="*Dashy Showcase* 🌟" class="linkLabel_WmDU">*Dashy Showcase* 🌟</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/docs/contributing"><span title="Contributing" class="linkLabel_WmDU">Contributing</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/docs/developing"><span title="Developing" class="linkLabel_WmDU">Developing</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/docs/development-guides"><span title="Development Guides" class="linkLabel_WmDU">Development Guides</span></a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/docs/privacy"><span title="Misc" class="categoryLinkLabel_W154">Misc</span></a></div></li></ul></nav></div><div class="sidebar-ad"><script async="" src="//cdn.carbonads.com/carbon.js?serve=CWYIC53L&amp;placement=dashyto" id="_carbonads_js"></script></div></div></aside><main class="docMainContainer_TBSr"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_VOVn"><div class="docItemContainer_Djhp"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_YNFT"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><span class="breadcrumbs__link">Community</span></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">Development Guides</span></li></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Development Guides</h1></header>
<p>A series of short tutorials, to guide you through the most common development tasks.</p>
<p>Sections:</p>
<ul>
<li class=""><a href="#creating-a-new-theme" class="">Creating a new theme</a></li>
<li class=""><a href="#writing-translations" class="">Writing Translations</a></li>
<li class=""><a href="#adding-a-new-option-in-the-config-file" class="">Adding a new option in the config file</a></li>
<li class=""><a href="#updating-dependencies" class="">Updating Dependencies</a></li>
<li class=""><a href="#developing-netlify-cloud-functions" class="">Writing Netlify Cloud Functions</a></li>
<li class=""><a href="#hiding-page-furniture-on-certain-routes" class="">Hiding Page Furniture</a></li>
<li class=""><a href="#adding--using-environmental-variables" class="">Adding / Using Environmental Variables</a></li>
<li class=""><a href="#building-a-widget" class="">Building a Widget</a></li>
<li class=""><a href="#respecting-config-permissions" class="">Respecting Config Permissions</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="creating-a-new-theme">Creating a new theme<a href="#creating-a-new-theme" class="hash-link" aria-label="Direct link to Creating a new theme" title="Direct link to Creating a new theme" translate="no"></a></h2>
<p>Adding a new theme is really easy. There&#x27;re two things you need to do: Pass the theme name to Dashy, so that it can be added to the theme selector dropdown menu, and then write some styles!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-add-theme-name">1. Add Theme Name<a href="#1-add-theme-name" class="hash-link" aria-label="Direct link to 1. Add Theme Name" title="Direct link to 1. Add Theme Name" translate="no"></a></h3>
<p>Choose a snappy name for your theme, and add it to the <code>builtInThemes</code> array inside <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L27" target="_blank" rel="noopener noreferrer" class=""><code>defaults.js</code></a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-write-some-styles">2. Write some Styles<a href="#2-write-some-styles" class="hash-link" aria-label="Direct link to 2. Write some Styles" title="Direct link to 2. Write some Styles" translate="no"></a></h3>
<p>Put your theme styles inside <a href="https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss" target="_blank" rel="noopener noreferrer" class=""><code>color-themes.scss</code></a>.
Create a new block, and make sure that <code>data-theme</code> matches the theme name you chose above. For example:</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token selector" style="color:rgb(255, 121, 198)">html</span><span class="token selector attribute punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token selector attribute attr-name" style="color:rgb(241, 250, 140)">data-theme</span><span class="token selector attribute operator" style="color:rgb(255, 121, 198)">=</span><span class="token selector attribute attr-value" style="color:rgb(255, 121, 198)">&#x27;tiger&#x27;</span><span class="token selector attribute punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--primary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token hexcode color">#f58233</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">--background</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token hexcode color">#0b1021</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Then you can go ahead and write your own custom CSS. Although all CSS is supported here, the best way to define your theme is by setting the CSS variables. You can find a <a class="" href="/docs/theming#css-variables">list of all CSS variables, here</a>.</p>
<p>For a full guide on styling, see <a class="" href="/docs/theming">Theming Docs</a>.</p>
<p>Note that if your theme is just for yourself, and you&#x27;re not submitting a PR, then you can instead just pass it under <code>appConfig.cssThemes</code> inside your config file. And then put your theme in your own stylesheet, and pass it into the Docker container - <a class="" href="/docs/theming#adding-your-own-theme">see how</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="writing-translations">Writing Translations<a href="#writing-translations" class="hash-link" aria-label="Direct link to Writing Translations" title="Direct link to Writing Translations" translate="no"></a></h2>
<p>For full docs about Dashy&#x27;s multi-language support, see <a class="" href="/docs/multi-language-support">Multi-Language Support</a></p>
<p>Dashy is using <a href="https://vue-i18n.intlify.dev/guide/" target="_blank" rel="noopener noreferrer" class="">vue-i18n</a> to manage multi-language support.</p>
<p>Adding a new language is pretty straightforward, with just three steps:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-create-a-new-language-file">1. Create a new Language File<a href="#1-create-a-new-language-file" class="hash-link" aria-label="Direct link to 1. Create a new Language File" title="Direct link to 1. Create a new Language File" translate="no"></a></h3>
<p>Create a new JSON file in <code>./src/assets/locales</code> name is a 2-digit <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes" target="_blank" rel="noopener noreferrer" class="">ISO-639 code</a> for your language, E.g. for German <code>de.json</code>, French <code>fr.json</code> or Spanish <code>es.json</code> - You can find a list of all ISO codes at <a href="https://www.iso.org/obp/ui" target="_blank" rel="noopener noreferrer" class="">iso.org</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-translate">2. Translate<a href="#2-translate" class="hash-link" aria-label="Direct link to 2. Translate" title="Direct link to 2. Translate" translate="no"></a></h3>
<p>Using <a href="https://github.com/Lissy93/dashy/tree/master/src/assets/locales/en.json" target="_blank" rel="noopener noreferrer" class=""><code>en.json</code></a> as an example, translate the JSON values to your language, while leaving the keys as they are. It&#x27;s fine to leave out certain items, as if they&#x27;re missing they will fall-back to English. If you see any attribute which include curly braces (<code>{xxx}</code>), then leave the inner value of these braces as is, as this is for variables.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;theme-maker&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;export-button&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Benutzerdefinierte Variablen exportieren&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;reset-button&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Stile zurücksetzen für&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;show-all-button&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Alle Variablen anzeigen&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;save-button&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Speichern&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;cancel-button&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Abbrechen&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;saved-toast&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;{theme} Erfolgreich aktualisiert&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;reset-toast&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;Benutzerdefinierte Farben für {theme} entfernt&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-add-your-file-to-the-app">3. Add your file to the app<a href="#3-add-your-file-to-the-app" class="hash-link" aria-label="Direct link to 3. Add your file to the app" title="Direct link to 3. Add your file to the app" translate="no"></a></h3>
<p>In <a href="https://github.com/Lissy93/dashy/tree/master/src/utils/languages.js" target="_blank" rel="noopener noreferrer" class=""><code>./src/utils/languages.js</code></a>, you need to do 2 small things:</p>
<p>First import your new translation file, do this at the top of the page.
E.g. <code>import de from &#x27;@/assets/locales/de.json&#x27;;</code></p>
<p>Second, add it to the array of languages, e.g:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> languages </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;English&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">code</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;en&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">locale</span><span class="token operator">:</span><span class="token plain"> en</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">flag</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;🇬🇧&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;German&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// The name of your language</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">code</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;de&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// The ISO code of your language</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">locale</span><span class="token operator">:</span><span class="token plain"> de</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// The name of the file you imported (no quotes)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">flag</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;🇩🇪&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// An optional flag emoji</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>You can also add your new language to the readme file, under the <a href="https://github.com/Lissy93/dashy#language-switching-" target="_blank" rel="noopener noreferrer" class="">Language Switching</a> section, and optionally include your name/ username if you&#x27;d like to be credited for your work. Done!</p>
<p>If you are not comfortable with making pull requests, or do not want to modify the code, then feel free to instead send the translated file to me, and I can add it into the application. I will be sure to credit you appropriately.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding-a-new-option-in-the-config-file">Adding a new option in the config file<a href="#adding-a-new-option-in-the-config-file" class="hash-link" aria-label="Direct link to Adding a new option in the config file" title="Direct link to Adding a new option in the config file" translate="no"></a></h2>
<p>This section is for, adding a new setting to the config file.</p>
<p>All of the users config is specified in <code>./user-data/conf.yml</code> - see <a class="" href="/docs/configuring">Configuring Docs</a> for info.
It&#x27;s important to first ensure that there isn&#x27;t a similar option already available, the new option is definitely necessary, and most importantly that it is fully backwards compatible.</p>
<p>Next choose the appropriate section to place it under</p>
<ul>
<li class="">Application settings should be located under <code>appConfig</code></li>
<li class="">Page info (such as text and metadata) should be under <code>pageInfo</code></li>
<li class="">Data relating to specific sections should be under <code>section[n].displayData</code></li>
<li class="">Settings applied to specific items or widgets, should be under <code>item[n]</code> or <code>widget[n]</code></li>
</ul>
<p>For example, if your option is added under <code>appConfig</code>, you can access it within your component using the <code>$store</code>, this is typically placed in a computed property, e.g:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token literal-property property">computed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">appConfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">$store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">getters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">appConfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<p>Then, where you want to get the users value within your component, use something like: <code>this.appConfig.myProperty</code>. If the user hasn&#x27;t specified the value, Don&#x27;t forget to have a fallback or default for it.</p>
<p>If you have a default fallback value, then this would typically be specified in the <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js" target="_blank" rel="noopener noreferrer" class=""><code>defaults.js</code></a> file.</p>
<p>You will now need to add the definition of your new attribute into the <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json" target="_blank" rel="noopener noreferrer" class="">ConfigSchema</a>. This will make it available in the UI config editor, and also ensure that the config validation check doesn&#x27;t fail.
For example:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token property">&quot;fontAwesomeKey&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;type&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;string&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;pattern&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;^[a-z0-9]{10}$&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;description&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;API key for font-awesome&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;example&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;0821c65656&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>or</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token property">&quot;iconSize&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;enum&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;small&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;medium&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;large&quot;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;default&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;medium&quot;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">&quot;description&quot;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&quot;The size of each link item / icon&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Finally, add your new property to the <a class="" href="/docs/configuring"><code>configuring.md</code></a> API docs. Put it under the relevant section, and be sure to include field name, data type, a description and mention that it is optional. If your new feature needs more explanation, then you can also document it under the relevant section elsewhere in the documentation.</p>
<p>Checklist:</p>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> Ensure the new attribute is actually necessary, and nothing similar already exists</li>
<li class="task-list-item"><input type="checkbox" disabled=""> Update the <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json" target="_blank" rel="noopener noreferrer" class="">Schema</a> with the parameters for your new option</li>
<li class="task-list-item"><input type="checkbox" disabled=""> If required, set a default or fallback value (usually in <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js" target="_blank" rel="noopener noreferrer" class=""><code>defaults.js</code></a>)</li>
<li class="task-list-item"><input type="checkbox" disabled=""> Document the new value in <a class="" href="/docs/configuring"><code>configuring.md</code></a>, and if required under the relevant section in the docs</li>
<li class="task-list-item"><input type="checkbox" disabled=""> Ensure your changes are backwards compatible, and that nothing breaks if the attribute isn&#x27;t specified</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="updating-dependencies">Updating Dependencies<a href="#updating-dependencies" class="hash-link" aria-label="Direct link to Updating Dependencies" title="Direct link to Updating Dependencies" translate="no"></a></h2>
<p>Running <code>yarn upgrade</code> will updated all dependencies based on the ranges specified in the <code>package.json</code>. The <code>yarn.lock</code> file will be updated, as will the contents of <code>./node_modules</code>, for more info, see the <a href="https://classic.yarnpkg.com/en/docs/cli/upgrade/" target="_blank" rel="noopener noreferrer" class="">yarn upgrade documentation</a>. <a href="https://github.com/raineorshine/npm-check-updates" target="_blank" rel="noopener noreferrer" class=""><code>npm-check-updates</code></a> is a useful tool to help with this.
It is important to thoroughly test after any big dependency updates.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="developing-netlify-cloud-functions">Developing Netlify Cloud Functions<a href="#developing-netlify-cloud-functions" class="hash-link" aria-label="Direct link to Developing Netlify Cloud Functions" title="Direct link to Developing Netlify Cloud Functions" translate="no"></a></h2>
<p>When Dashy is deployed to Netlify, it is effectively running as a static app, and therefore the server-side code for the Node.js endpoints is not available. However Netlify now supports serverless cloud lambda functions, which can be used to replace most functionality.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-run-netlify-dev-server">1. Run Netlify Dev Server<a href="#1-run-netlify-dev-server" class="hash-link" aria-label="Direct link to 1. Run Netlify Dev Server" title="Direct link to 1. Run Netlify Dev Server" translate="no"></a></h3>
<p>First off all, install the Netlify CLI: <code>npm install netlify-cli -g</code>
Then, from within the root of Dashy&#x27;s directory, start the server, by running: <code>netlify dev</code></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-create-a-lambda-function">2. Create a lambda function<a href="#2-create-a-lambda-function" class="hash-link" aria-label="Direct link to 2. Create a lambda function" title="Direct link to 2. Create a lambda function" translate="no"></a></h3>
<p>This should be saved in the <a href="https://github.com/Lissy93/dashy/tree/master/services/serverless-functions" target="_blank" rel="noopener noreferrer" class=""><code>./services/serverless-functions</code></a> directory</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">exports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(80, 250, 123)">handler</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;Return some data here...&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-redirect-the-node-endpoint-to-the-function">3. Redirect the Node endpoint to the function<a href="#3-redirect-the-node-endpoint-to-the-function" class="hash-link" aria-label="Direct link to 3. Redirect the Node endpoint to the function" title="Direct link to 3. Redirect the Node endpoint to the function" translate="no"></a></h3>
<p>In the <a href="https://github.com/Lissy93/dashy/blob/FEATURE/serverless-functions/netlify.toml" target="_blank" rel="noopener noreferrer" class=""><code>netlify.toml</code></a> file, add a 301 redirect, with the path to the original Node.js endpoint, and the name of your cloud function</p>
<div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-toml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">[[redirects]]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> from = &quot;/status-check&quot;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> to = &quot;/.netlify/functions/cloud-status-check&quot;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> status = 301</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> force = true</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hiding-page-furniture-on-certain-routes">Hiding Page Furniture on Certain Routes<a href="#hiding-page-furniture-on-certain-routes" class="hash-link" aria-label="Direct link to Hiding Page Furniture on Certain Routes" title="Direct link to Hiding Page Furniture on Certain Routes" translate="no"></a></h2>
<p>For some pages (such as the login page, the minimal start page, etc) the basic page furniture, (like header, footer, nav, etc) is not needed. This section explains how you can hide furniture on a new view (step 1), or add a component that should be hidden on certain views (step 2).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-add-the-route-name-to-the-should-hide-array">1. Add the route name to the should hide array<a href="#1-add-the-route-name-to-the-should-hide-array" class="hash-link" aria-label="Direct link to 1. Add the route name to the should hide array" title="Direct link to 1. Add the route name to the should hide array" translate="no"></a></h3>
<p>In <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js" target="_blank" rel="noopener noreferrer" class=""><code>./src/utils/defaults.js</code></a>, there&#x27;s an array called <code>hideFurnitureOn</code>. Append the name of the route (the same as it appears in <a href="https://github.com/Lissy93/dashy/blob/master/src/router.js" target="_blank" rel="noopener noreferrer" class=""><code>router.js</code></a>) here.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-add-the-conditional-to-the-structural-component-to-hide">2. Add the conditional to the structural component to hide<a href="#2-add-the-conditional-to-the-structural-component-to-hide" class="hash-link" aria-label="Direct link to 2. Add the conditional to the structural component to hide" title="Direct link to 2. Add the conditional to the structural component to hide" translate="no"></a></h3>
<p>First, import the helper function:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> shouldBeVisible </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;@/utils/SectionHelpers&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>Then you can create a computed value, that calls this function, passing in the route name:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">computed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token method function property-access" style="color:rgb(80, 250, 123)">isVisible</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">shouldBeVisible</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">$route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>Finally, in the markup of your component, just add a <code>v-if</code> statement, referencing your computed value</p>
<div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;header v-if=&quot;isVisible&quot;&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ...</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/header&gt;</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding--using-environmental-variables">Adding / Using Environmental Variables<a href="#adding--using-environmental-variables" class="hash-link" aria-label="Direct link to Adding / Using Environmental Variables" title="Direct link to Adding / Using Environmental Variables" translate="no"></a></h2>
<p>All environmental variables are optional. Currently there are not many environmental variables used, as most of the user preferences are stored under <code>appConfig</code> in the <code>conf.yml</code> file.</p>
<p>You can set variables either in your environment, or using the <a href="https://github.com/Lissy93/dashy/blob/master/.env" target="_blank" rel="noopener noreferrer" class=""><code>.env</code></a> file.</p>
<p>Any environmental variables used by the frontend are preceded with <code>VUE_APP_</code>. Vue will merge the contents of your <code>.env</code> file into the app in a similar way to the <a href="https://github.com/motdotla/dotenv" target="_blank" rel="noopener noreferrer" class="">&#x27;dotenv&#x27;</a> package, where any variables that you set on your system will always take preference over the contents of any <code>.env</code> file.</p>
<p>If add any new variables, ensure that there is always a fallback (define it in <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js" target="_blank" rel="noopener noreferrer" class=""><code>defaults.js</code></a>), so as to not cause breaking changes. Don&#x27;t commit the contents of your <code>.env</code> file to git, but instead take a few moments to document what you&#x27;ve added under the appropriate section. Try and follow the concepts outlined in the <a href="https://12factor.net/config" target="_blank" rel="noopener noreferrer" class="">12 factor app</a>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-a-widget">Building a Widget<a href="#building-a-widget" class="hash-link" aria-label="Direct link to Building a Widget" title="Direct link to Building a Widget" translate="no"></a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-0---prerequisites">Step 0 - Prerequisites<a href="#step-0---prerequisites" class="hash-link" aria-label="Direct link to Step 0 - Prerequisites" title="Direct link to Step 0 - Prerequisites" translate="no"></a></h3>
<p>If this is your first time working on Dashy, then the <a class="" href="/docs/developing">Developing Docs</a> instructions for project setup and running. In short, you just need to clone the project, cd into it, install dependencies (<code>yarn</code>) and then start the development server (<code>yarn dev</code>).</p>
<p>To build a widget, you&#x27;ll also need some basic knowledge of Vue.js. The <a href="https://vuejs.org/v2/guide/" target="_blank" rel="noopener noreferrer" class="">official Vue docs</a> provides a good starting point, as does <a href="https://www.taniarascia.com/getting-started-with-vue/" target="_blank" rel="noopener noreferrer" class="">this guide</a> by Tania Rascia</p>
<p>If you just want to jump straight in, then <a href="https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e" target="_blank" rel="noopener noreferrer" class="">here</a> is a complete implementation of a new example widget, or take a look at the <a href="https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/XkcdComic.vue" target="_blank" rel="noopener noreferrer" class=""><code>XkcdComic.vue</code></a> widget, which is pretty simple.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1---create-widget">Step 1 - Create Widget<a href="#step-1---create-widget" class="hash-link" aria-label="Direct link to Step 1 - Create Widget" title="Direct link to Step 1 - Create Widget" translate="no"></a></h3>
<p>Firstly, create a new <code>.vue</code> file under <a href="https://github.com/Lissy93/dashy/tree/master/src/components/Widgets" target="_blank" rel="noopener noreferrer" class=""><code>./src/components/Widgets</code></a>.</p>
<div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;template&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;div class=&quot;example-wrapper&quot;&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/div&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/template&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;script&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">import axios from &#x27;axios&#x27;;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">import WidgetMixin from &#x27;@/mixins/WidgetMixin&#x27;;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">import { widgetApiEndpoints } from &#x27;@/utils/defaults&#x27;;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">export default {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> mixins: [WidgetMixin],</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> data() {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> return {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> results: null,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> };</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> computed: {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> endpoint() {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> return `${widgetApiEndpoints.myApi}/something`;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> methods: {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> fetchData() {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> this.makeRequest(this.endpoint).then(this.processData);</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> processData(data) {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Do processing any here, and set component data</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> this.results = data;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">};</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/script&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;style scoped lang=&quot;scss&quot;&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/style&gt;</span><br></span></code></pre></div></div>
<p>All widgets extend from the <a href="https://github.com/Lissy93/dashy/blob/master/src/mixins/WidgetMixin.js" target="_blank" rel="noopener noreferrer" class="">Widget</a> mixin. This provides some basic functionality that is shared by all widgets. The mixin includes the following <code>options</code>, <code>startLoading()</code>, <code>finishLoading()</code>, <code>error()</code> and <code>update()</code>.</p>
<ul>
<li class=""><strong>Getting user options: <code>options</code></strong>
<ul>
<li class="">Any user-specific config can be accessed with <code>this.options.something</code> (where something is the data key you&#x27;re accessing)</li>
</ul>
</li>
<li class=""><strong>Loading state: <code>startLoading()</code> and <code>finishLoading()</code></strong>
<ul>
<li class="">You can show the loader with <code>this.startLoading()</code>, then when your data request completes, hide it again with <code>this.finishLoading()</code></li>
</ul>
</li>
<li class=""><strong>Error handling: <code>error()</code></strong>
<ul>
<li class="">If something goes wrong (such as API error, or missing user parameters), then call <code>this.error()</code> to show message to user</li>
</ul>
</li>
<li class=""><strong>Updating data: <code>update()</code></strong>
<ul>
<li class="">When the user clicks the update button, or if continuous updates are enabled, then the <code>update()</code> method within your widget will be called</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2---adding-functionality">Step 2 - Adding Functionality<a href="#step-2---adding-functionality" class="hash-link" aria-label="Direct link to Step 2 - Adding Functionality" title="Direct link to Step 2 - Adding Functionality" translate="no"></a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="accessing-user-options"><strong>Accessing User Options</strong><a href="#accessing-user-options" class="hash-link" aria-label="Direct link to accessing-user-options" title="Direct link to accessing-user-options" translate="no"></a></h4>
<p>If your widget is going to accept any parameters from the user, then we can access these with <code>this.options.[parmName]</code>. It&#x27;s best to put these as computed properties, which will enable us to check it exists, is valid, and if needed format it. For example, if we have an optional property called <code>count</code> (to determine number of results), we can do the following, and then reference it within our component with <code>this.count</code></p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token literal-property property">computed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding-an-api-endpoint"><strong>Adding an API Endpoint</strong><a href="#adding-an-api-endpoint" class="hash-link" aria-label="Direct link to adding-an-api-endpoint" title="Direct link to adding-an-api-endpoint" translate="no"></a></h4>
<p>If your widget makes a data request, then add the URL for the API endpoint to the <code>widgetApiEndpoints</code> array in <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L207" target="_blank" rel="noopener noreferrer" class=""><code>defaults.js</code></a></p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token literal-property property">widgetApiEndpoints</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">exampleEndpoint</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;https://hub.dummyapis.com/ImagesList&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<p>Then in your widget file:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> widgetApiEndpoints </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;@/utils/defaults&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>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:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">endpoint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">widgetApiEndpoints</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation property-access">exampleEndpoint</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">?count=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation property-access">count</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="making-an-api-request"><strong>Making an API Request</strong><a href="#making-an-api-request" class="hash-link" aria-label="Direct link to making-an-api-request" title="Direct link to making-an-api-request" translate="no"></a></h4>
<p>Axios is used for making data requests, so import it into your component: <code>import axios from &#x27;axios&#x27;;</code></p>
<p>Under the <code>methods</code> block, we&#x27;ll create a function called <code>fetchData</code>, here we can use Axios to make a call to our endpoint.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">fetchData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">endpoint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">then</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">processData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<p>There are three things happening here:</p>
<ul>
<li class="">If the response completes successfully, we&#x27;ll pass the results to another function that will handle them</li>
<li class="">If there&#x27;s an error, then we call <code>this.error()</code>, which will show a message to the user</li>
<li class="">Whatever the result, once the request has completed, we call <code>this.finishLoading()</code>, which will hide the loader</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="processing-response"><strong>Processing Response</strong><a href="#processing-response" class="hash-link" aria-label="Direct link to processing-response" title="Direct link to processing-response" translate="no"></a></h4>
<p>In the above example, we call the <code>processData()</code> method with the result from the API, so we need to create that under the <code>methods</code> section. How you handle this data will vary depending on what&#x27;s returned by the API, and what you want to render to the user. But however you do it, you will likely need to create a data variable to store the response, so that it can be easily displayed in the HTML.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token literal-property property">myResults</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<p>And then, inside your <code>processData()</code> method, you can set the value of this, with:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">this.myResults = &#x27;whatever&#x27;</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rendering-response"><strong>Rendering Response</strong><a href="#rendering-response" class="hash-link" aria-label="Direct link to rendering-response" title="Direct link to rendering-response" translate="no"></a></h4>
<p>Now that the results are in the correct format, and stored as data variables, we can use them within the <code>&lt;template&gt;</code> to render results to the user. Again, how you do this will depend on the structure of your data, and what you want to display, but at it&#x27;s simplest, it might look something like this:</p>
<div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;p class=&quot;results&quot;&gt;{{ myResults }}&lt;/p&gt;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="styling"><strong>Styling</strong><a href="#styling" class="hash-link" aria-label="Direct link to styling" title="Direct link to styling" translate="no"></a></h4>
<p>Styles can be written for your widget within the <code>&lt;style&gt;</code> block.</p>
<p>There are several color variables used by widgets, which extend from the base palette. Using these enables users to override colors to theme their dashboard, if they wish. The variables are: <code>--widget-text-color</code>, <code>--widget-background-color</code> and <code>--widget-accent-color</code></p>
<div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;style scoped lang=&quot;scss&quot;&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">p.results {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> color: var(--widget-text-color);</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;/style&gt;</span><br></span></code></pre></div></div>
<p>For examples of finished widget components, see the <a href="https://github.com/Lissy93/dashy/tree/master/src/components/Widgets" target="_blank" rel="noopener noreferrer" class="">Widgets</a> directory. Specifically, the <a href="https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/XkcdComic.vue" target="_blank" rel="noopener noreferrer" class=""><code>XkcdComic.vue</code></a> widget is quite minimal, so would make a good example, as will <a href="https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e" target="_blank" rel="noopener noreferrer" class="">this example implementation</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3---register">Step 3 - Register<a href="#step-3---register" class="hash-link" aria-label="Direct link to Step 3 - Register" title="Direct link to Step 3 - Register" translate="no"></a></h3>
<p>Next, register your new widget in <a href="https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/WidgetBase.vue" target="_blank" rel="noopener noreferrer" class=""><code>WidgetBase.vue</code></a>. In this file, you&#x27;ll need to add the following:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">COMPAT</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token string-property property">&#x27;example-widget&#x27;</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;ExampleWidget&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>Here, the <code>example-widget</code> property name will be used to identify the widget when parsing the <code>type</code> property in a configuration file. The <code>ExampleWidget</code> string is used to dynamically import the widget, and therefore must match the widget&#x27;s filename as it exists in the <code>components/widgets</code> folder.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4---docs">Step 4 - Docs<a href="#step-4---docs" class="hash-link" aria-label="Direct link to Step 4 - Docs" title="Direct link to Step 4 - Docs" translate="no"></a></h3>
<p>Finally, add some documentation for your widget in the <a class="" href="/docs/widgets">Widget Docs</a>, so that others know how to use it. Include the following information: Title, short description, screenshot, config options and some example YAML.</p>
<p><strong>Summary</strong>: For a complete example of everything discussed here, see: <a href="https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e" target="_blank" rel="noopener noreferrer" class=""><code>3da76ce</code></a></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="respecting-config-permissions">Respecting Config Permissions<a href="#respecting-config-permissions" class="hash-link" aria-label="Direct link to Respecting Config Permissions" title="Direct link to Respecting Config Permissions" translate="no"></a></h2>
<p>Any screen that displays part or all of the users config, must not be shown when the user has disabled viewing config.</p>
<p>This can be done by checking the <code>allowViewConfig</code> attribute of the <code>permissions</code> getter, in the store.
First create a new <code>computed</code> property, like:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">allowViewConfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">$store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">getters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">permissions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">allowViewConfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><br></span></code></pre></div></div>
<p>Then wrap the part of your UI which displays config with: <code>v-if=&quot;allowViewConfig&quot;</code></p>
<p>If required, add a message showing that the component isn&#x27;t available, using the <code>AccessError</code> component. E.g.</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token known-class-name class-name">AccessError</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">&#x27;@/components/Configuration/AccessError&#x27;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<div class="language-vue codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-vue codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;AccessError v-else /&gt;</span><br></span></code></pre></div></div>
<p>The <code>$store.getters.permissions</code> object also returns options for when and where config can be saved, using: <code>allowWriteToDisk</code>, and <code>allowSaveLocally</code> - both are booleans.</p></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="row margin-top--sm theme-doc-footer-edit-meta-row"><div class="col noPrint_WFHX"><a href="https://github.com/Lissy93/dashy/edit/gh-pages/docs/docs/development-guides.md" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_JAkA"><span class="theme-last-updated">Last updated<!-- --> on <b><time datetime="2026-03-15T15:42:20.000Z" itemprop="dateModified">Mar 15, 2026</time></b></span></div></div></footer></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/docs/developing"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">Developing</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/docs/privacy"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Privacy &amp; Security</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#creating-a-new-theme" class="table-of-contents__link toc-highlight">Creating a new theme</a><ul><li><a href="#1-add-theme-name" class="table-of-contents__link toc-highlight">1. Add Theme Name</a></li><li><a href="#2-write-some-styles" class="table-of-contents__link toc-highlight">2. Write some Styles</a></li></ul></li><li><a href="#writing-translations" class="table-of-contents__link toc-highlight">Writing Translations</a><ul><li><a href="#1-create-a-new-language-file" class="table-of-contents__link toc-highlight">1. Create a new Language File</a></li><li><a href="#2-translate" class="table-of-contents__link toc-highlight">2. Translate</a></li><li><a href="#3-add-your-file-to-the-app" class="table-of-contents__link toc-highlight">3. Add your file to the app</a></li></ul></li><li><a href="#adding-a-new-option-in-the-config-file" class="table-of-contents__link toc-highlight">Adding a new option in the config file</a></li><li><a href="#updating-dependencies" class="table-of-contents__link toc-highlight">Updating Dependencies</a></li><li><a href="#developing-netlify-cloud-functions" class="table-of-contents__link toc-highlight">Developing Netlify Cloud Functions</a><ul><li><a href="#1-run-netlify-dev-server" class="table-of-contents__link toc-highlight">1. Run Netlify Dev Server</a></li><li><a href="#2-create-a-lambda-function" class="table-of-contents__link toc-highlight">2. Create a lambda function</a></li><li><a href="#3-redirect-the-node-endpoint-to-the-function" class="table-of-contents__link toc-highlight">3. Redirect the Node endpoint to the function</a></li></ul></li><li><a href="#hiding-page-furniture-on-certain-routes" class="table-of-contents__link toc-highlight">Hiding Page Furniture on Certain Routes</a><ul><li><a href="#1-add-the-route-name-to-the-should-hide-array" class="table-of-contents__link toc-highlight">1. Add the route name to the should hide array</a></li><li><a href="#2-add-the-conditional-to-the-structural-component-to-hide" class="table-of-contents__link toc-highlight">2. Add the conditional to the structural component to hide</a></li></ul></li><li><a href="#adding--using-environmental-variables" class="table-of-contents__link toc-highlight">Adding / Using Environmental Variables</a></li><li><a href="#building-a-widget" class="table-of-contents__link toc-highlight">Building a Widget</a><ul><li><a href="#step-0---prerequisites" class="table-of-contents__link toc-highlight">Step 0 - Prerequisites</a></li><li><a href="#step-1---create-widget" class="table-of-contents__link toc-highlight">Step 1 - Create Widget</a></li><li><a href="#step-2---adding-functionality" class="table-of-contents__link toc-highlight">Step 2 - Adding Functionality</a></li><li><a href="#step-3---register" class="table-of-contents__link toc-highlight">Step 3 - Register</a></li><li><a href="#step-4---docs" class="table-of-contents__link toc-highlight">Step 4 - Docs</a></li></ul></li><li><a href="#respecting-config-permissions" class="table-of-contents__link toc-highlight">Respecting Config Permissions</a></li></ul></div></div></div></div></main></div></div></div><footer class="theme-layout-footer footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Intro</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://github.com/lissy93/dashy" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://demo.dashy.to" target="_blank" rel="noopener noreferrer" class="footer__link-item">Live Demo<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a class="footer__link-item" href="/docs/quick-start">Quick Start</a></li><li class="footer__item"><a class="footer__link-item" href="/docs">Documentation</a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Setup Guide</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/docs/deployment">Deploying</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/configuring">Configuring</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/management">Management</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/troubleshooting">Troubleshooting</a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Feature Docs Pt 1</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/docs/authentication">Authentication</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/alternate-views">Alternate Views</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/backup-restore">Backup &amp; Restore</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/icons">Icons</a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Feature Docs Pt 2</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/docs/multi-language-support">Language Switching</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/status-indicators">Status Indicators</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/searching">Searching &amp; Shortcuts</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/theming">Theming</a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/docs/developing">Developing</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/development-guides">Development Guides</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/contributing">Contributing</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/showcase">Showcase</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/credits">Credits</a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Misc</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/docs/privacy">Privacy &amp; Security</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/license">License</a></li><li class="footer__item"><a href="https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md" target="_blank" rel="noopener noreferrer" class="footer__link-item">Legal<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/Lissy93/dashy/blob/master/.github/CODE_OF_CONDUCT.md" target="_blank" rel="noopener noreferrer" class="footer__link-item">Code of Conduct<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/Lissy93/dashy/blob/master/.github/CHANGELOG.md" target="_blank" rel="noopener noreferrer" class="footer__link-item">Changelog<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div></div><div class="footer__bottom text--center"><div class="footer__copyright"><a href="https://dashy.to">Dashy</a> - The Self-Hosted Dashboard for your Homelab<br>License under <a href="https://github.com/Lissy93/dashy/blob/master/LICENSE">MIT</a>. Copyright © 2026 <a href="https://aliciasykes.com">Alicia Sykes</a></div></div></div></footer></div>
</body>
</html>