mirror of
https://github.com/Lissy93/dashy.git
synced 2026-03-22 12:43:56 +01:00
225 lines
No EOL
72 KiB
HTML
225 lines
No EOL
72 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-developing" data-has-hydrated="false">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v3.9.2">
|
||
<title data-rh="true">Developing | 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="Developing | Dashy"><meta data-rh="true" name="description" content="This article outlines how to get Dashy running in a development environment, and outlines the basics of the architecture."><meta data-rh="true" property="og:description" content="This article outlines how to get Dashy running in a development environment, and outlines the basics of the architecture."><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://dashy.to/docs/developing"><link data-rh="true" rel="alternate" href="https://dashy.to/docs/developing" hreflang="en"><link data-rh="true" rel="alternate" href="https://dashy.to/docs/developing" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Developing","item":"https://dashy.to/docs/developing"}]}</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's new!" href="/updates">Dashy <!-- -->V3.1.11<!-- --> is now live 🚀</a><a class="link2_y3x6" title="View the changelog, to see what's new!" href="/updates">See what's new…</a><button class="closeBtn_fC0A" title="Dismiss update, and don't show again" aria-label="Dismiss update, and don'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 menu__link--active" aria-current="page" 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" 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&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">Developing</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>Developing</h1></header>
|
||
<p>This article outlines how to get Dashy running in a development environment, and outlines the basics of the architecture.
|
||
If you're adding new features, you may want to check out the <a class="" href="/docs/development-guides">Development Guides</a> docs, for tutorials covering basic tasks.</p>
|
||
<ul>
|
||
<li class=""><a href="#setting-up-the-dev-environment" class="">Setting up the Development Environment</a>
|
||
<ul>
|
||
<li class=""><a href="#prerequisites" class="">Prerequisites</a></li>
|
||
<li class=""><a href="#running-the-project" class="">Running the App</a></li>
|
||
<li class=""><a href="#project-commands" class="">Project Commands</a></li>
|
||
<li class=""><a href="#environmental-variables" class="">Environmental Variables</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class=""><a href="#git-strategy" class="">Git Strategy</a>
|
||
<ul>
|
||
<li class=""><a href="#git-flow" class="">Flow</a></li>
|
||
<li class=""><a href="#git-branch-naming" class="">Branches</a></li>
|
||
<li class=""><a href="#commit-emojis" class="">Commit emojis</a></li>
|
||
<li class=""><a href="#pr-guidelines" class="">PR Guidelines</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class=""><a href="#resources-for-beginners" class="">Resources for Beginners</a></li>
|
||
<li class=""><a href="#app-info" class="">App Info</a></li>
|
||
<li class=""><a href="#style-guide" class="">Code Style Guide</a></li>
|
||
<li class=""><a href="#application-structure" class="">Application Structure</a></li>
|
||
<li class=""><a href="#development-tools" class="">Development Tools</a></li>
|
||
<li class=""><a href="#notes" class="">Misc / Notes</a></li>
|
||
</ul>
|
||
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="setting-up-the-dev-environment">Setting up the Dev Environment<a href="#setting-up-the-dev-environment" class="hash-link" aria-label="Direct link to Setting up the Dev Environment" title="Direct link to Setting up the Dev Environment" translate="no"></a></h2>
|
||
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="prerequisites">Prerequisites<a href="#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites" translate="no"></a></h3>
|
||
<p>You will need either the latest or LTS version of <strong><a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a></strong> to build and serve the application and <strong><a href="https://git-scm.com/downloads" target="_blank" rel="noopener noreferrer" class="">Git</a></strong> to easily fetch the code, and push any changes. If you plan on running or deploying the container, you'll also need <strong><a href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener noreferrer" class="">Docker</a></strong>. To avoid any unexpected issues, ensure you've got at least <strong><a href="https://www.npmjs.com/get-npm" target="_blank" rel="noopener noreferrer" class="">NPM</a></strong> V 7.5 or <strong><a href="https://classic.yarnpkg.com/en/docs/install/#windows-stable" target="_blank" rel="noopener noreferrer" class="">Yarn</a></strong> 1.22 (you may find <a href="https://github.com/nvm-sh/nvm" target="_blank" rel="noopener noreferrer" class="">NVM</a> helpful for switching/ managing versions).</p>
|
||
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="running-the-project">Running the Project<a href="#running-the-project" class="hash-link" aria-label="Direct link to Running the Project" title="Direct link to Running the Project" translate="no"></a></h3>
|
||
<ol>
|
||
<li class="">Get Code: <code>git clone https://github.com/Lissy93/dashy.git</code></li>
|
||
<li class="">Navigate into the directory: <code>cd dashy</code></li>
|
||
<li class="">Install dependencies: <code>yarn</code></li>
|
||
<li class="">Start dev server: <code>yarn dev</code></li>
|
||
</ol>
|
||
<p>Dashy should now be being served on <a href="http://localhost:8080/" target="_blank" rel="noopener noreferrer" class="">http://localhost:8080/</a>. Hot reload is enabled, so making changes to any of the files will trigger them to be rebuilt and the page refreshed.</p>
|
||
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="project-commands">Project Commands<a href="#project-commands" class="hash-link" aria-label="Direct link to Project Commands" title="Direct link to Project Commands" translate="no"></a></h3>
|
||
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="basics">Basics<a href="#basics" class="hash-link" aria-label="Direct link to Basics" title="Direct link to Basics" translate="no"></a></h4>
|
||
<ul>
|
||
<li class=""><strong><code>yarn build</code></strong> - In the interest of speed, the application is pre-compiled, this means that the config file is read during build-time, and therefore the app needs to rebuilt for any new changes to take effect. Luckily this is very straight forward. Just run <code>yarn build</code> or <code>docker exec -it [container-id] yarn build</code></li>
|
||
<li class=""><strong><code>yarn start</code></strong> - Starts a web server, and serves up the production site from <code>./dist</code> (must run build command first)</li>
|
||
</ul>
|
||
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="development">Development<a href="#development" class="hash-link" aria-label="Direct link to Development" title="Direct link to Development" translate="no"></a></h4>
|
||
<ul>
|
||
<li class=""><strong><code>yarn dev</code></strong> - Starts the development server with hot reloading</li>
|
||
<li class=""><strong><code>yarn lint</code></strong> - Lints code to ensure it follows a consistent, neat style</li>
|
||
<li class=""><strong><code>yarn test</code></strong> - Runs tests, and outputs results</li>
|
||
</ul>
|
||
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="utils-and-checks">Utils and Checks<a href="#utils-and-checks" class="hash-link" aria-label="Direct link to Utils and Checks" title="Direct link to Utils and Checks" translate="no"></a></h4>
|
||
<ul>
|
||
<li class=""><strong><code>yarn validate-config</code></strong> - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with <code>yarn validate-config</code> or <code>docker exec -it [container-id] yarn validate-config</code>. Your config file needs to be in <code>/user-data/conf.yml</code> (or within your Docker container at <code>/app/user-data/conf.yml</code>). This will first check that your YAML is valid, and then validates it against Dashy's <a href="https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json" target="_blank" rel="noopener noreferrer" class="">schema</a>.</li>
|
||
<li class=""><strong><code>yarn health-check</code></strong> - Checks that the application is up and running on it's specified port, and outputs current status and response times. Useful for integrating into your monitoring service, if you need to maintain high system availability</li>
|
||
</ul>
|
||
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="alternate-start-commands">Alternate Start Commands<a href="#alternate-start-commands" class="hash-link" aria-label="Direct link to Alternate Start Commands" title="Direct link to Alternate Start Commands" translate="no"></a></h4>
|
||
<ul>
|
||
<li class=""><strong><code>yarn build-and-start</code></strong> - Builds the app, runs checks and starts the production server. Commands are run in parallel, and so is faster than running them in independently. Uses the <code>yarn build</code> and <code>yarn start</code> commands</li>
|
||
<li class=""><strong><code>yarn build-watch</code></strong> - If you find yourself making frequent changes to your configuration, and do not want to have to keep manually rebuilding, then this option is for you. It will watch for changes to any files within the projects root, and then trigger a rebuild. Note that if you are developing new features, then <code>yarn dev</code> would be more appropriate, as it's significantly faster at recompiling (under 1 second), and has hot reloading, linting and testing integrated</li>
|
||
<li class=""><strong><code>yarn pm2-start</code></strong> - Starts the Node server using <a href="https://pm2.keymetrics.io/" target="_blank" rel="noopener noreferrer" class="">PM2</a>, a process manager for Node.js applications, that helps them stay alive. PM2 has some built-in basic monitoring features, and an optional <a href="https://pm2.io/" target="_blank" rel="noopener noreferrer" class="">management solution</a>. If you are running the app on bare metal, it is recommended to use this start command</li>
|
||
</ul>
|
||
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="notes">Notes<a href="#notes" class="hash-link" aria-label="Direct link to Notes" title="Direct link to Notes" translate="no"> |