{"id":22585941,"url":"https://github.com/artcc/custom-deskhub","last_synced_at":"2026-05-07T06:37:55.229Z","repository":{"id":264683233,"uuid":"893842062","full_name":"ArtCC/custom-deskhub","owner":"ArtCC","description":"Node.js project to extend DeskHub functionality with custom features. Containerized with Docker and deployed using Docker Compose for easy setup.","archived":false,"fork":false,"pushed_at":"2025-01-23T13:49:24.000Z","size":35,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-02T17:54:12.638Z","etag":null,"topics":["deskhub","docker","docker-compose","github-contributions","nodejs"],"latest_commit_sha":null,"homepage":"https://www.arturocarreterocalvo.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArtCC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2024-11-25T09:59:33.000Z","updated_at":"2025-01-23T13:49:27.000Z","dependencies_parsed_at":"2025-01-23T14:28:39.940Z","dependency_job_id":"9c853bbc-2af2-4f57-9a28-49fe134cba21","html_url":"https://github.com/ArtCC/custom-deskhub","commit_stats":null,"previous_names":["artcc/custom-deskhub"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtCC%2Fcustom-deskhub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtCC%2Fcustom-deskhub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtCC%2Fcustom-deskhub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtCC%2Fcustom-deskhub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArtCC","download_url":"https://codeload.github.com/ArtCC/custom-deskhub/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246068293,"owners_count":20718503,"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":["deskhub","docker","docker-compose","github-contributions","nodejs"],"created_at":"2024-12-08T07:10:05.450Z","updated_at":"2026-05-07T06:37:55.222Z","avatar_url":"https://github.com/ArtCC.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Custom DeskHub Backend 🖥️\n\n[![Node.js](https://img.shields.io/badge/Node.js-20+-green.svg)](https://nodejs.org/)\n[![Express](https://img.shields.io/badge/Express-4.21+-blue.svg)](https://expressjs.com/)\n[![License](https://img.shields.io/badge/License-Apache%202.0-yellow.svg)](LICENSE)\n[![Docker](https://img.shields.io/badge/Docker-Ready-2496ED.svg)](https://www.docker.com/)\n\nA powerful Node.js backend service to extend [DeskHub](https://getdeskhub.com/) functionality with custom features, including real-time GitHub commit tracking, weather information, and dynamic content display.\n\n![DeskHub](https://getdeskhub.com/_next/image?url=%2Fhero2.webp\u0026w=1080\u0026q=75)\n\n\u003e **About DeskHub**: DeskHub is an innovative physical device developed by [Max Blade](https://getdeskhub.com/). If you don't have one yet, check it out!\n\n---\n\n## 📋 Table of Contents\n\n- [Features](#-features)\n- [Tech Stack](#-tech-stack)\n- [Prerequisites](#-prerequisites)\n- [Installation](#-installation)\n- [Configuration](#-configuration)\n- [API Endpoints](#-api-endpoints)\n- [Docker Deployment](#-docker-deployment)\n- [Development](#-development)\n- [Project Structure](#-project-structure)\n- [License](#-license)\n\n---\n\n## ✨ Features\n\n- **🎯 Dynamic Content Display**: Control what your DeskHub displays in real-time\n- **📊 GitHub Integration**: Automatically fetch and display today's commit statistics\n- **🌤️ Weather Information**: Real-time weather data from OpenWeatherMap API\n- **💾 Persistent Storage**: Content persists between server restarts\n- **⚡ Smart Caching**: 5-minute cache for GitHub, 15-minute cache for weather\n- **🔒 Environment Validation**: Ensures all required credentials are present\n- **🌐 CORS Enabled**: Ready for cross-origin requests\n- **📝 Structured Logging**: Comprehensive logging with timestamps\n- **🐳 Docker Ready**: Easy deployment with Docker Compose\n- **🔄 Health Checks**: Built-in health monitoring for container orchestration\n\n---\n\n## 🛠 Tech Stack\n\n- **Runtime**: Node.js 20+\n- **Framework**: Express.js 4.21+\n- **APIs**: GitHub GraphQL API, OpenWeatherMap API\n- **Containerization**: Docker \u0026 Docker Compose\n- **Code Quality**: ESLint 9\n- **Development**: Nodemon\n- **Development**: Nodemon\n\n---\n\n## 📦 Prerequisites\n\nBefore you begin, ensure you have:\n\n- **Node.js** 20 or higher ([Download](https://nodejs.org/))\n- **npm** (comes with Node.js)\n- **Docker** (optional, for containerized deployment)\n- **GitHub Account** with a personal access token\n- **DeskHub Device** ([Get one here](https://getdeskhub.com/))\n\n---\n\n## 🚀 Installation\n\n### Local Setup\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/ArtCC/custom-deskhub.git\n   cd custom-deskhub\n   ```\n\n2. **Install dependencies**\n   ```bash\n   npm install\n   ```\n\n3. **Configure environment variables**\n   \n   Create a `.env` file in the root directory:\n   ```env\n   GITHUB_TOKEN=your_github_personal_access_token\n   GITHUB_USERNAME=your_github_username\n   PORT=3005\n   LOCALHOST=http://192.168.1.100\n   \n   # Optional: Weather configuration\n   OPENWEATHER_API_KEY=your_openweather_api_key\n   OPENWEATHER_CITY=Madrid\n   OPENWEATHER_UNITS=metric\n   ```\n\n4. **Start the server**\n   ```bash\n   node index.js\n   ```\n\n   For development with auto-reload:\n   ```bash\n   npm run dev\n   ```\n\n---\n\n## ⚙️ Configuration\n\n### Environment Variables\n\n| Variable | Description | Example | Required |\n|----------|-------------|---------|----------|\n| `GITHUB_TOKEN` | GitHub Personal Access Token ([Create one](https://github.com/settings/tokens)) | `ghp_xxxxxxxxxxxx` | ✅ Yes |\n| `GITHUB_USERNAME` | Your GitHub username | `ArtCC` | ✅ Yes |\n| `PORT` | Server listening port | `3005` | ✅ Yes |\n| `LOCALHOST` | Server URL/IP address | `http://192.168.1.100` | ✅ Yes |\n| `OPENWEATHER_API_KEY` | OpenWeatherMap API Key ([Get free key](https://openweathermap.org/api)) | `abc123...` | ⚪ Optional |\n| `OPENWEATHER_CITY` | City name for weather | `Madrid` or `London,UK` | ⚪ Optional |\n| `OPENWEATHER_UNITS` | Temperature units | `metric` (°C) or `imperial` (°F) | ⚪ Optional (default: metric) |\n\n\u003e **Note:** Weather variables are optional. The `/weather` endpoint requires `OPENWEATHER_API_KEY` and `OPENWEATHER_CITY` to be set.\n\n### Creating a GitHub Token\n\n1. Go to [GitHub Settings → Developer Settings → Personal Access Tokens](https://github.com/settings/tokens)\n2. Click \"Generate new token (classic)\"\n3. **Select scopes based on your needs:**\n\n   **Option A: Public repositories only (Recommended for most users)**\n   ```\n   ☑️ read:user\n   ```\n   This is sufficient to read your profile and commits from public repositories.\n\n   **Option B: Include private repositories**\n   ```\n   ☑️ read:user\n   ☑️ repo (full access to private repositories)\n   ```\n   Use this if you want to see commits from your private repositories.\n\n   **What the token is used for:**\n   - ✅ Read user profile information\n   - ✅ Fetch commit statistics and contributions\n   - ✅ List repositories where you've committed\n   - ❌ No write access - read-only\n\n4. Set an expiration date (recommended: 90 days or no expiration for personal use)\n5. Click \"Generate token\" and copy it immediately (you won't see it again!)\n\n\u003e **⚠️ Security Note:** Never share your token or commit it to repositories. Use environment variables only.\n\n---\n\n## 🔌 API Endpoints\n\nAll endpoints return data in a format optimized for DeskHub display (ASCII text only, no emojis or special Unicode characters).\n\n### `GET /display`\n\nReturns the current content to display on DeskHub.\n\n**Response:**\n```json\n{\n  \"content\": \"Your custom text here\"\n}\n```\n\n**DeskHub Configuration:**\n- **Endpoint:** `http://your-server:3005/display`\n- **Recommended fetch rate:** 60,000 ms (1 minute)\n\n---\n\n### `GET /setDisplay`\n\nUpdates the display content. Content persists between server restarts.\n\n**Parameters:**\n- `text` (required): The text to display\n\n**Example:**\n```bash\ncurl \"http://your-server:3005/setDisplay?text=Hello%20World\"\n```\n\n**Response:**\n```json\n{\n  \"content\": \"Hello World\"\n}\n```\n\n---\n\n### `GET /commits`\n\nFetches your GitHub commits for the current day. Results are cached for 5 minutes.\n\n**Example:**\n```bash\ncurl \"http://your-server:3005/commits\"\n```\n\n**Response:**\n```json\n{\n  \"content\": \"Today: 5 commits (custom-deskhub: 3, my-project: 2)\"\n}\n```\n\n**DeskHub Configuration:**\n- **Endpoint:** `http://your-server:3005/commits`\n- **Recommended fetch rate:** 180,000 ms (3 minutes)\n\n**Features:**\n- ✅ Automatic caching (5 min TTL)\n- ✅ Formatted for DeskHub display (ASCII only)\n- ✅ Counts commits from midnight UTC\n- ✅ Counts commits from midnight UTC\n\n---\n\n### `GET /weather`\n\nFetches current weather for a configured city. Results are cached for 15 minutes.\n\n\u003e **Configuration required:** Set `OPENWEATHER_API_KEY` and `OPENWEATHER_CITY` environment variables.\n\n**Example:**\n```bash\ncurl \"http://your-server:3005/weather\"\n```\n\n**Response:**\n```json\n{\n  \"content\": \"Madrid: 22C Clear\"\n}\n```\n\n**DeskHub Configuration:**\n- **Endpoint:** `http://your-server:3005/weather`\n- **Recommended fetch rate:** 600,000 ms (10 minutes)\n\n**Features:**\n- ✅ Automatic caching (15 min TTL)\n- ✅ ASCII-only format (no Unicode/emojis - DeskHub compatible)\n- ✅ Supports metric (C) and imperial (F) units\n- ✅ Compact single-line format\n\n**Weather Conditions:**\n- Clear - Clear sky\n- Cloudy - Cloudy\n- Rain - Rainy weather\n- Storm - Thunderstorm\n- Snow - Snowy weather\n- Fog - Fog/Mist\n- Drizzle - Light rain\n\n**Get your free API key:**\n1. Go to [OpenWeatherMap](https://openweathermap.org/api)\n2. Sign up for a free account\n3. Generate an API key (free tier: 60 calls/min, 1M calls/month)\n\n---\n\n## 🐳 Docker Deployment\n\n### Quick Start with Pre-built Image\n\nThe easiest way to deploy is using the pre-built Docker image from GitHub Container Registry:\n\n1. **Create a `.env` file:**\n   ```env\n   GITHUB_TOKEN=your_github_token\n   GITHUB_USERNAME=your_github_username\n   PORT=3005\n   LOCALHOST=http://192.168.1.100\n   \n   # Optional: Weather configuration\n   OPENWEATHER_API_KEY=your_openweather_api_key\n   OPENWEATHER_CITY=Madrid\n   OPENWEATHER_UNITS=metric\n   ```\n\n2. **Create a `docker-compose.yml` file:**\n   ```yaml\n   version: '3.8'\n\n   services:\n     custom-deskhub:\n       image: ghcr.io/artcc/custom-deskhub:latest\n       container_name: custom-deskhub\n       restart: unless-stopped\n       ports:\n         - \"${PORT:-3005}:${PORT:-3005}\"\n       environment:\n         - GITHUB_TOKEN=${GITHUB_TOKEN}\n         - GITHUB_USERNAME=${GITHUB_USERNAME}\n         - PORT=${PORT:-3005}\n         - LOCALHOST=${LOCALHOST}\n         - OPENWEATHER_API_KEY=${OPENWEATHER_API_KEY}\n         - OPENWEATHER_CITY=${OPENWEATHER_CITY}\n         - OPENWEATHER_UNITS=${OPENWEATHER_UNITS:-metric}\n       volumes:\n         - ./data:/app/data\n       networks:\n         - deskhub-network\n       healthcheck:\n         test: [\"CMD\", \"sh\", \"-c\", \"node -e \\\"require('http').get('http://localhost:' + process.env.PORT + '/display', (r) =\u003e {process.exit(r.statusCode === 200 ? 0 : 1)})\\\"\"]\n         interval: 60s\n         timeout: 3s\n         retries: 3\n         start_period: 10s\n\n   networks:\n     deskhub-network:\n       driver: bridge\n   ```\n\n3. **Run the container:**\n   ```bash\n   docker-compose up -d\n   ```\n\n**Docker Commands:**\n```bash\n# View logs\ndocker-compose logs -f\n\n# Check container health\ndocker-compose ps\n\n# Restart container\ndocker-compose restart\n\n# Stop container\ndocker-compose down\n\n# Pull latest image\ndocker-compose pull \u0026\u0026 docker-compose up -d\n```\n\n### Building Your Own Image\n\nIf you want to build the image locally:\n\n```bash\n# Build the image\ndocker build -t custom-deskhub:local .\n\n# Run with custom image\ndocker run -d \\\n  --name custom-deskhub \\\n  -p 3005:3005 \\\n  -e GITHUB_TOKEN=your_token \\\n  -e GITHUB_USERNAME=your_username \\\n  -e PORT=3005 \\\n  -e LOCALHOST=http://192.168.1.100 \\\n  -v $(pwd)/data:/app/data \\\n  custom-deskhub:local\n```\n\n### Automated Builds\n\nEvery push to `main` branch automatically:\n- ✅ Builds a new Docker image\n- ✅ Pushes to GitHub Container Registry\n- ✅ Tags with `latest` and commit SHA\n- ✅ Supports multi-platform (amd64, arm64)\n\n**Image Tags:**\n- `latest` - Latest stable version from main branch\n- `v1.0.0` - Specific version tags\n- `main-abc123` - Commit-specific builds\n\n---\n\n## 💻 Development\n\n### Available Scripts\n\n| Command | Description |\n|---------|-------------|\n| `npm start` | Start the production server |\n| `npm run dev` | Start with auto-reload (nodemon) |\n| `npm run lint` | Check code style with ESLint |\n| `npm run lint:fix` | Auto-fix linting issues |\n\n### Code Style\n\nThis project uses ESLint with the following rules:\n- Indentation: 2 spaces\n- Quotes: Single quotes\n- Semicolons: Required\n- Line endings: Unix (LF)\n\n### Development Workflow\n\n1. Make your changes\n2. Run `npm run lint:fix` to auto-fix style issues\n3. Test your changes locally\n4. Commit with meaningful messages\n\n---\n\n## 📁 Project Structure\n\n```\ncustom-deskhub/\n├── .github/\n│   └── workflows/\n│       └── docker-publish.yml  # CI/CD pipeline\n├── index.js                    # Main application file\n├── data.json                   # Persistent storage (auto-generated)\n├── package.json                # Project dependencies\n├── eslint.config.js            # ESLint configuration\n├── Dockerfile                  # Docker image definition\n├── .dockerignore               # Docker build exclusions\n├── docker-compose.yml          # Docker Compose configuration\n├── .env                        # Environment variables (create this)\n├── LICENSE                     # Apache 2.0 License\n└── README.md                   # This file\n```\n\n---\n\n## 🔧 Troubleshooting\n\n### Server won't start\n\n**Error:** `Missing required environment variables`\n- **Solution:** Ensure your `.env` file contains all required variables (GITHUB_TOKEN, GITHUB_USERNAME, PORT, LOCALHOST)\n\n### GitHub API errors\n\n**Error:** `Failed to fetch GitHub commits`\n- **Solution 1:** Check your GitHub token is valid\n- **Solution 2:** Ensure token has correct scopes (`read:user`)\n- **Solution 3:** Check GitHub API rate limits\n\n### Weather endpoint returns 503\n\n**Error:** `Weather service not configured`\n- **Solution:** Set `OPENWEATHER_API_KEY` and `OPENWEATHER_CITY` in your `.env` file\n- **Note:** Weather configuration is optional - other endpoints will work without it\n\n### DeskHub shows Unicode characters instead of text\n\n**Issue:** Seeing weird symbols like `\\u2600` or `°C` showing as boxes\n- **Solution:** This has been fixed - all endpoints now return ASCII-only text\n- **Note:** Make sure you're using the latest version of the server\n\n### Docker container exits immediately\n\n**Solution:** Check logs with `docker-compose logs` and verify environment variables\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n---\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n---\n\n## 👨‍💻 Author\n\n**Arturo Carretero Calvo**\n\n- GitHub: [@ArtCC](https://github.com/ArtCC)\n- Year: 2026\n\n---\n\n## 🙏 Acknowledgments\n\n- **Max Blade** for creating the amazing DeskHub device\n- **GitHub** for their GraphQL API\n- **OpenWeatherMap** for their free weather API\n- The Node.js and Express.js communities\n\n---\n\n## 📝 Additional Notes\n\n### DeskHub Display Compatibility\n\nThis server is optimized for DeskHub's display limitations:\n- ✅ ASCII-only text (no emojis or Unicode symbols)\n- ✅ Single-line compact formats\n- ✅ Clear, readable information\n\n### Recommended Fetch Rates\n\nConfigure your DeskHub with these recommended fetch intervals:\n- **`/display`**: 60,000 ms (1 minute) - For dynamic content\n- **`/commits`**: 180,000 ms (3 minutes) - Aligns with 5-min cache\n- **`/weather`**: 600,000 ms (10 minutes) - Aligns with 15-min cache\n\n---\n\n\u003cp align=\"center\"\u003eMade with ❤️ for DeskHub users\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartcc%2Fcustom-deskhub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartcc%2Fcustom-deskhub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartcc%2Fcustom-deskhub/lists"}