{"id":13403628,"url":"https://github.com/danielbayerlein/dashboard","last_synced_at":"2025-05-16T02:07:21.859Z","repository":{"id":37732986,"uuid":"89935412","full_name":"danielbayerlein/dashboard","owner":"danielbayerlein","description":"📺 Create your own team dashboard with custom widgets. Built with Next.js, React, styled-components and polished.","archived":false,"fork":false,"pushed_at":"2023-05-03T04:58:01.000Z","size":2269,"stargazers_count":1314,"open_issues_count":23,"forks_count":192,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-08T12:11:07.702Z","etag":null,"topics":["bitbucket","dashboard","elasticsearch","github","jenkins","jira","pagespeed-insights","react","sonarqube","widget"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danielbayerlein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-05-01T15:21:02.000Z","updated_at":"2025-04-04T18:12:29.000Z","dependencies_parsed_at":"2024-04-10T00:39:24.380Z","dependency_job_id":"7853471e-f7da-42b8-b42d-79d0535be468","html_url":"https://github.com/danielbayerlein/dashboard","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielbayerlein%2Fdashboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielbayerlein%2Fdashboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielbayerlein%2Fdashboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielbayerlein%2Fdashboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielbayerlein","download_url":"https://codeload.github.com/danielbayerlein/dashboard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453652,"owners_count":22073617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitbucket","dashboard","elasticsearch","github","jenkins","jira","pagespeed-insights","react","sonarqube","widget"],"created_at":"2024-07-30T19:01:32.548Z","updated_at":"2025-05-16T02:07:21.826Z","avatar_url":"https://github.com/danielbayerlein.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cloud.githubusercontent.com/assets/457834/25781812/a981cf5a-333e-11e7-938e-378de1589b20.png\" width=\"250\" alt=\"Dashboard\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n  Dashboard\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Create your own team dashboard with custom widgets.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/danielbayerlein/vallox-api/actions\"\u003e\n    \u003cimg alt=\"Actions Status\" src=\"https://github.com/danielbayerlein/dashboard/workflows/CI/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://standardjs.com\"\u003e\n    \u003cimg alt=\"JavaScript Style Guide\" src=\"https://img.shields.io/badge/code_style-standard-brightgreen.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://dependabot.com\"\u003e\n    \u003cimg alt=\"Dependabot Status\" src=\"https://api.dependabot.com/badges/status?host=github\u0026repo=danielbayerlein/dashboard\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://deploy.now.sh/?repo=https://github.com/danielbayerlein/dashboard\"\u003e\n    \u003cimg alt=\"Deploy to now\" src=\"https://deploy.now.sh/static/button.svg\" height=\"20\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Server](#server)\n  * [Development](#development)\n  * [Production](#production)\n  * [Docker](#docker)\n* [Create a Dashboard](#create-a-dashboard)\n* [Available Widgets](#available-widgets)\n  * [DateTime](#datetime)\n  * [Jenkins Job Status](#jenkins-job-status)\n  * [Jenkins Job Health](#jenkins-job-health)\n  * [Jenkins Build Duration](#jenkins-build-duration)\n  * [JIRA Issue Count](#jira-issue-count)\n  * [JIRA Sprint Days Remaining](#jira-sprint-days-remaining)\n  * [Bitbucket PullRequest Count](#bitbucket-pullrequest-count)\n  * [PageSpeed Insights Score](#pagespeed-insights-score)\n  * [PageSpeed Insights Stats](#pagespeed-insights-stats)\n  * [SonarQube](#sonarqube)\n  * [Elasticsearch Hit Count](#elasticsearch-hit-count)\n  * [GitHub Issue Count](#github-issue-count)\n  * [Title](#title)\n* [Available Themes](#available-themes)\n  * [light](#light)\n  * [dark](#dark)\n* [Authentication](#authentication)\n* [Cross-Origin Resource Sharing (CORS)](#cross-origin-resource-sharing-cors)\n  * [Proxy](#proxy)\n  * [Resources](#resources)\n* [License](#license)\n\n## Installation\n\n1. [Download](../../archive/master.zip) or clone the repository.\n2. Install the dependencies with `npm install`.\n\n## Server\n\n### Development\n\nRun `npm run dev` and go to http://localhost:3000.\n\n### Production\n\nBuild your dashboard for production with `npm run build` and then start the\nserver with `npm start`.\n\n### Docker\n\n1. Build your dashboard for production with `npm run build`\n2. Build the image with `docker build -t dashboard .`\n3. Start the container with `docker run -d -p 8080:3000 dashboard`\n4. Go to http://localhost:8080\n\n## Create a Dashboard\n\nYou can create multiple dashboards.\nFor example populate `pages/team-unicorn.js` inside your project:\n\n```javascript\nimport Dashboard from '../components/dashboard'\nimport DateTime from '../components/widgets/datetime'\nimport lightTheme from '../styles/light-theme'\n\nexport default () =\u003e (\n  \u003cDashboard theme={lightTheme} name='Unicorn Dashboard'\u003e\n    \u003cDateTime /\u003e\n  \u003c/Dashboard\u003e\n)\n```\n\nThis dashboard is available at http://localhost:3000/team-unicorn.\n\nFor an example, see [pages/index.js](./pages/index.js).\n\n## Available Widgets\n\n### [DateTime](./components/widgets/datetime/index.js)\n\n#### Example\n\n```javascript\nimport DateTime from '../components/widgets/datetime'\n\n\u003cDateTime interval={10000} /\u003e\n```\n\n#### props\n\n* `interval`: Refresh interval in milliseconds (Default: `10000`)\n\n### [Jenkins Job Status](./components/widgets/jenkins/job-status.js)\n\n#### Example\n\n```javascript\nimport JenkinsJobStatus from '../components/widgets/jenkins/job-status'\n\n\u003cJenkinsJobStatus\n  url='https://builds.apache.org'\n  jobs={[\n    { label: 'JMeter', path: 'JMeter-trunk' },\n    { label: 'Log4j Kotlin', path: 'Log4jKotlin', branch: 'master' }\n  ]}\n/\u003e\n```\n\nFor Jenkins multibranch projects add `branch` to the object.\n\n#### props\n\n* `title`: Widget title (Default: `Job Status`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: Jenkins URL\n* `jobs`: List of all jobs\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [Jenkins Job Health](./components/widgets/jenkins/job-health.js)\n\n#### Example\n\n```javascript\nimport JenkinsJobHealth from '../components/widgets/jenkins/job-health'\n\n\u003cJenkinsJobHealth\n  url='https://builds.apache.org'\n  jobs={[\n    { label: 'JMeter', path: 'JMeter-trunk' },\n    { label: 'Log4j Kotlin', path: 'Log4jKotlin', branch: 'master' }\n  ]}\n/\u003e\n```\n\nFor Jenkins multibranch projects add `branch` to the object.\n\n#### props\n\n* `title`: Widget title (Default: `Job Health`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: Jenkins URL\n* `jobs`: List of all jobs\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n\n### [Jenkins Build Duration](./components/widgets/jenkins/build-duration.js)\n\n#### Example\n\n```javascript\nimport JenkinsBuildDuration from '../components/widgets/jenkins/build-duration'\n\n\u003cJenkinsBuildDuration\n  url='https://builds.apache.org'\n  jobs={[\n    { label: 'JMeter', path: 'JMeter-trunk' },\n    { label: 'Log4j Kotlin', path: 'Log4jKotlin', branch: 'master' }\n  ]}\n/\u003e\n```\n\nFor Jenkins multibranch projects add `branch` to the object.\n\n#### props\n\n* `title`: Widget title (Default: `Build Duration`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: Jenkins URL\n* `jobs`: List of all jobs\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [JIRA Issue Count](./components/widgets/jira/issue-count.js)\n\n#### Example\n\n```javascript\nimport JiraIssueCount from '../components/widgets/jira/issue-count'\n\n\u003cJiraIssueCount\n  title='JIRA Open Bugs'\n  url='https://jira.atlassian.com'\n  query='type=Bug AND project=\"Bitbucket Server\" AND resolution=Unresolved ORDER BY priority DESC,created DESC'\n/\u003e\n```\n\nFor Jenkins multibranch projects add `branch` to the object.\n\n#### props\n\n* `title`: Widget title (Default: `JIRA Issue Count`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: JIRA Server URL\n* `query`: JIRA search query (`jql`)\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [JIRA Sprint Days Remaining](./components/widgets/jira/sprint-days-remaining.js)\n\n#### Example\n\n```javascript\nimport JiraSprintDaysRemaining from '../components/widgets/jira/sprint-days-remaining'\n\n\u003cJiraSprintDaysRemaining\n  title='Sprint Days'\n  url='https://jira.atlassian.com'\n  boardId={42}\n/\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `JIRA Sprint Days Remaining`)\n* `interval`: Refresh interval in milliseconds (Default: `3600000`)\n* `url`: JIRA Server URL\n* `boardId`: JIRA board id\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [Bitbucket PullRequest Count](./components/widgets/bitbucket/pull-request-count.js)\n\n#### Example\n\n```javascript\nimport BitbucketPullRequestCount from '../components/widgets/bitbucket/pull-request-count'\n\n\u003cBitbucketPullRequestCount\n  title='Bitbucket Open PR'\n  url='https://bitbucket.typo3.com'\n  project='EXT'\n  repository='blog'\n  users={['stekal', 'marleg', 'denhub']}\n/\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `Bitbucket PR Count`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: Bitbucket Server URL\n* `project`: Bitbucket project key\n* `repository`: Bitbucket repository slug\n* `users`: Bitbucket user slugs as an array\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [PageSpeed Insights Score](./components/widgets/pagespeed-insights/score.js)\n\n#### Example\n\n```javascript\nimport PageSpeedInsightsScore from '../components/widgets/pagespeed-insights/score'\n\n\u003cPageSpeedInsightsScore url='https://github.com' /\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `PageSpeed Score`)\n* `interval`: Refresh interval in milliseconds (Default: `43200000`)\n* `url`: URL to fetch and analyze\n* `strategy`: Analysis strategy (Default: `desktop`)\n  * Acceptable values: `desktop` | `mobile`\n* `filterThirdPartyResources`: Indicates if third party resources should be filtered out (Default: `false`)\n\n### [PageSpeed Insights Stats](./components/widgets/pagespeed-insights/stats.js)\n\n#### Example\n\n```javascript\nimport PageSpeedInsightsStats from '../components/widgets/pagespeed-insights/stats'\n\n\u003cPageSpeedInsightsStats url='https://github.com' /\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `PageSpeed Stats`)\n* `interval`: Refresh interval in milliseconds (Default: `43200000`)\n* `url`: URL to fetch and analyze\n* `strategy`: Analysis strategy (Default: `desktop`)\n  * Acceptable values: `desktop` | `mobile`\n* `filterThirdPartyResources`: Indicates if third party resources should be filtered out (Default: `false`)\n\n### [SonarQube](./components/widgets/sonarqube/index.js)\n\n#### Example\n\n```javascript\nimport SonarQube from '../components/widgets/sonarqube'\n\n\u003cSonarQube\n  url='https://sonarcloud.io'\n  componentKey='com.icegreen:greenmail-parent'\n/\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `SonarQube`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: SonarQube URL\n* `componentKey`: SonarQube project key\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [Elasticsearch Hit Count](./components/widgets/elasticsearch/hit-count.js)\n\n#### Example\n\n```javascript\nimport ElasticsearchHitCount from '../components/widgets/elasticsearch/hit-count'\n\n\u003cElasticsearchHitCount\n  title='Log Hits'\n  url='http://ec2-34-210-144-223.us-west-2.compute.amazonaws.com:9200'\n  index='blog'\n  query='user:dilbert'\n/\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `Elasticsearch Hit Count`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `url`: Elasticsearch URL\n* `index`: Elasticsearch index to search in\n* `query`: Elasticsearch query\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [GitHub Issue Count](./components/widgets/github/issue-count.js)\n\n#### Example\n\n```javascript\nimport GitHubIssueCount from '../components/widgets/github/issue-count'\n\n\u003cGitHubIssueCount\n  owner='danielbayerlein'\n  repository='dashboard'\n/\u003e\n```\n\n#### props\n\n* `title`: Widget title (Default: `GitHub Issue Count`)\n* `interval`: Refresh interval in milliseconds (Default: `300000`)\n* `owner`: Owner of the repository\n* `repository`: Name of the repository\n* `authKey`: Credential key, defined in [auth.js](./auth.js)\n\n### [Title](./components/widgets/title/index.js)\n\n#### Example\n\n```javascript\nimport Title from '../components/widgets/title'\n\n\u003cTitle\u003eAPI Status\u003c/Title\u003e\n```\n\n## Available Themes\n\n### [light](./styles/light-theme.js)\n\n#### Example\n\n```javascript\nimport lightTheme from '../styles/light-theme'\n\n\u003cDashboard theme={lightTheme}\u003e\n  ...\n\u003c/Dashboard\u003e\n```\n\n#### Preview\n\n![dashboard-light](https://cloud.githubusercontent.com/assets/457834/26214930/8c065dce-3bfe-11e7-9da0-2d6ebba2dfb8.png)\n\n### [dark](./styles/dark-theme.js)\n\n#### Example\n\n```javascript\nimport darkTheme from '../styles/dark-theme'\n\n\u003cDashboard theme={darkTheme}\u003e\n  ...\n\u003c/Dashboard\u003e\n```\n\n#### Preview\n\n![dashboard-dark](https://cloud.githubusercontent.com/assets/457834/26214954/a668dc50-3bfe-11e7-8c19-7a0c7dd260e7.png)\n\n## Authentication\n\nAny widget can authenticate itself, should your server expect this. We use\n[basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).\n\n1. Define your credential key in [auth.js](./auth.js). For example:\n   ```javascript\n   jira: {\n     username: process.env.JIRA_USER,\n     password: process.env.JIRA_PASS\n   }\n   ```\n2. Give the defined credential key `jira` via prop `authKey` to the widget.\n   For example:\n   ```javascript\n   \u003cJiraIssueCount\n     authKey='jira'\n     url='https://jira.atlassian.com'\n     query='type=Bug AND project=\"Bitbucket Server\" AND resolution=Unresolved ORDER BY priority DESC,created DESC'\n   /\u003e\n   ```\n3. Create a `.env` file or rename `.env.example` to `.env` in the root directory of your project. Add\n   environment-specific variables on new lines in the form of `NAME=VALUE`.\n   For example:\n   ```dosini\n   JIRA_USER=root\n   JIRA_PASS=s1mpl3\n   ```\n\n## Cross-Origin Resource Sharing (CORS)\n\n[Cross-Origin Resource Sharing](https://www.w3.org/TR/cors/) (CORS) is a W3C\nspec that allows cross-domain communication from the browser. By building on\ntop of the XMLHttpRequest object, CORS allows developers to work with the same\nidioms as same-domain requests.\n\n### Proxy\n\nYou can use a proxy (e.g. [hapi-rest-proxy](https://github.com/chrishelgert/hapi-rest-proxy))\nto enable CORS request for any website.\n\n#### Server\n\n```bash\ndocker pull chrishelgert/hapi-rest-proxy\ndocker run -d -p 3001:8080 chrishelgert/hapi-rest-proxy\n```\n\n#### Dashboard\n\n```javascript\n\u003cSonarQube\n  url='http://127.0.0.1:3001/?url=https://sonarcloud.io'\n  componentKey='com.icegreen:greenmail-parent'\n/\u003e\n```\n\n### Resources\n\n* https://www.w3.org/TR/cors/\n* https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS\n* https://enable-cors.org\n* https://en.wikipedia.org/wiki/Cross-origin_resource_sharing\n\n## License\n\nCopyright (c) 2017-present Daniel Bayerlein. See [LICENSE](./LICENSE.md) for details.\n","funding_links":[],"categories":["Apps","JavaScript","react"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielbayerlein%2Fdashboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielbayerlein%2Fdashboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielbayerlein%2Fdashboard/lists"}