dependabot/npm_and_yarn/astro-5.16.4
copilot/add-i18n-support-for-english
dependabot/npm_and_yarn/astro-5.16.4
dependabot/npm_and_yarn/katex-0.16.27
dependabot/npm_and_yarn/prettier-3.7.4
dependabot/npm_and_yarn/tailwindcss-4.1.16
dependabot/npm_and_yarn/tailwindcss/vite-4.1.16
dependabot/npm_and_yarn/typescript-eslint-8.46.2
dependabot/npm_and_yarn/typescript-eslint/parser-8.46.2
development
main
| 1 | # Desktop Downloads Implementation Summary |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | Successfully implemented a secure, production-ready system to fetch and display desktop application download links from a private GitHub repository. |
| 6 | |
| 7 | ## What Was Built |
| 8 | |
| 9 | ### 1. API Endpoint (`/api/download-desktop-app`) |
| 10 | |
| 11 | **Location:** `/src/pages/api/download-desktop-app.ts` |
| 12 | |
| 13 | **Features:** |
| 14 | - Fetches latest release from private GitHub repository |
| 15 | - Authenticates using GitHub Personal Access Token |
| 16 | - Automatically detects platform and architecture from filenames |
| 17 | - Proxies downloads to keep GitHub token secure |
| 18 | - Includes 5-minute cache to reduce API calls |
| 19 | - Type-safe implementation with TypeScript |
| 20 | |
| 21 | **Endpoints:** |
| 22 | - `GET /api/download-desktop-app` - Returns list of available downloads |
| 23 | - `GET /api/download-desktop-app?action=download&assetId=123` - Proxies asset download |
| 24 | |
| 25 | ### 2. Download Page (`/download`) |
| 26 | |
| 27 | **Location:** `/src/pages/download.astro` |
| 28 | |
| 29 | **Features:** |
| 30 | - Mobile and App Store download links |
| 31 | - Dynamic desktop downloads section |
| 32 | - Client-side JavaScript fetches releases |
| 33 | - Responsive design with platform-specific icons |
| 34 | - Shows version, file size, and architecture |
| 35 | - Graceful error handling |
| 36 | |
| 37 | **Displays:** |
| 38 | - 🍎 macOS (Apple Silicon, Intel, Universal) |
| 39 | - 🪟 Windows (x64, ARM64) |
| 40 | - 🐧 Linux (x64, ARM64, various formats) |
| 41 | |
| 42 | ### 3. Type Definitions |
| 43 | |
| 44 | **Location:** `/src/types/github-releases.ts` |
| 45 | |
| 46 | **Includes:** |
| 47 | - GitHub API response types |
| 48 | - Application-specific types |
| 49 | - Platform detection patterns |
| 50 | - Type guards for runtime validation |
| 51 | - Full TypeScript intellisense support |
| 52 | |
| 53 | ### 4. Test Script |
| 54 | |
| 55 | **Location:** `/scripts/test-github-releases.js` |
| 56 | |
| 57 | **Capabilities:** |
| 58 | - Tests GitHub API authentication |
| 59 | - Verifies token permissions |
| 60 | - Lists all release assets |
| 61 | - Analyzes platform detection |
| 62 | - Provides debugging information |
| 63 | - Color-coded output for readability |
| 64 | |
| 65 | **Usage:** |
| 66 | ```bash |
| 67 | npm run test:releases |
| 68 | ``` |
| 69 | |
| 70 | ### 5. Documentation |
| 71 | |
| 72 | **Files Created:** |
| 73 | 1. `DESKTOP_DOWNLOADS_SETUP.md` - Comprehensive setup guide |
| 74 | 2. `QUICK_START_DOWNLOADS.md` - 5-minute quick start |
| 75 | 3. `IMPLEMENTATION_SUMMARY.md` - This file |
| 76 | 4. `.env.example` - Environment variables template |
| 77 | |
| 78 | ## Technical Architecture |
| 79 | |
| 80 | ``` |
| 81 | ┌──────────────────────────────────────────────────────────────┐ |
| 82 | │ Browser │ |
| 83 | │ ┌────────────────────────────────────────────────────┐ │ |
| 84 | │ │ Download Page (/download) │ │ |
| 85 | │ │ • Lists mobile app stores │ │ |
| 86 | │ │ • Fetches desktop downloads via API │ │ |
| 87 | │ └─────────────────┬──────────────────────────────────┘ │ |
| 88 | └────────────────────┼──────────────────────────────────────────┘ |
| 89 | │ |
| 90 | │ HTTPS Request |
| 91 | ▼ |
| 92 | ┌──────────────────────────────────────────────────────────────┐ |
| 93 | │ API Server (Astro) │ |
| 94 | │ ┌────────────────────────────────────────────────────┐ │ |
| 95 | │ │ API Endpoint (/api/download-desktop-app) │ │ |
| 96 | │ │ • Authenticates with GitHub token │ │ |
| 97 | │ │ • Parses release assets │ │ |
| 98 | │ │ • Detects platforms/architectures │ │ |
| 99 | │ │ • Returns structured data or proxies download │ │ |
| 100 | │ └─────────────────┬──────────────────────────────────┘ │ |
| 101 | └────────────────────┼──────────────────────────────────────────┘ |
| 102 | │ |
| 103 | │ Authenticated Request |
| 104 | │ (Bearer token) |
| 105 | ▼ |
| 106 | ┌──────────────────────────────────────────────────────────────┐ |
| 107 | │ GitHub API │ |
| 108 | │ ┌────────────────────────────────────────────────────┐ │ |
| 109 | │ │ Private Repository │ │ |
| 110 | │ │ (setoelkahfi/pepakbasajawa) │ │ |
| 111 | │ │ • /releases/latest │ │ |
| 112 | │ │ • /releases/assets/:id │ │ |
| 113 | │ └────────────────────────────────────────────────────┘ │ |
| 114 | └──────────────────────────────────────────────────────────────┘ |
| 115 | ``` |
| 116 | |
| 117 | ## Security Features |
| 118 | |
| 119 | ### 1. Token Protection |
| 120 | - GitHub token never exposed to client |
| 121 | - Stored securely in environment variables |
| 122 | - Used only in server-side API routes |
| 123 | |
| 124 | ### 2. Download Proxying |
| 125 | - Downloads go through API endpoint |
| 126 | - API authenticates with GitHub on user's behalf |
| 127 | - GitHub provides temporary redirect URLs |
| 128 | - Users don't need GitHub accounts |
| 129 | |
| 130 | ### 3. Fine-Grained Permissions |
| 131 | - Token only needs `repo` scope (or just `Contents: Read`) |
| 132 | - No unnecessary permissions granted |
| 133 | - Can use fine-grained tokens for better security |
| 134 | |
| 135 | ### 4. Rate Limiting |
| 136 | - 5-minute cache reduces API calls |
| 137 | - GitHub allows 5,000 authenticated requests/hour |
| 138 | - More than sufficient for production traffic |
| 139 | |
| 140 | ## Platform Detection Logic |
| 141 | |
| 142 | ### Detection Patterns |
| 143 | |
| 144 | **macOS:** |
| 145 | - Keywords: `mac`, `darwin` |
| 146 | - Extensions: `.dmg`, `.pkg` |
| 147 | - Architectures: |
| 148 | - Apple Silicon: `arm64`, `aarch64`, `apple` |
| 149 | - Intel: `x64`, `x86_64`, `intel` |
| 150 | - Universal: `universal` or no architecture specified |
| 151 | |
| 152 | **Windows:** |
| 153 | - Keywords: `win`, `windows` |
| 154 | - Extensions: `.exe`, `.msi`, `.msix` |
| 155 | - Architectures: |
| 156 | - x64: `x64`, `x86_64`, `amd64` |
| 157 | - ARM64: `arm64`, `aarch64` |
| 158 | |
| 159 | **Linux:** |
| 160 | - Keywords: `linux` |
| 161 | - Extensions: `.appimage`, `.deb`, `.rpm`, `.tar.gz`, `.snap` |
| 162 | - Architectures: |
| 163 | - x64: `x64`, `x86_64`, `amd64` |
| 164 | - ARM64: `arm64`, `aarch64` |
| 165 | |
| 166 | ### Recommended Naming Convention |
| 167 | |
| 168 | ``` |
| 169 | {app-name}-{version}-{platform}-{arch}.{ext} |
| 170 | |
| 171 | Examples: |
| 172 | ✅ pepakbasajawa-1.0.0-macos-arm64.dmg |
| 173 | ✅ pepakbasajawa-1.0.0-macos-x64.dmg |
| 174 | ✅ pepakbasajawa-1.0.0-windows-x64.exe |
| 175 | ✅ pepakbasajawa-1.0.0-linux-x64.AppImage |
| 176 | ✅ pepakbasajawa-1.0.0-linux-x64.deb |
| 177 | ``` |
| 178 | |
| 179 | ## Setup Requirements |
| 180 | |
| 181 | ### 1. Environment Variables |
| 182 | |
| 183 | **Development (.env):** |
| 184 | ```env |
| 185 | GITHUB_TOKEN=ghp_your_token_here |
| 186 | ``` |
| 187 | |
| 188 | **Production:** |
| 189 | Set in hosting platform dashboard (Vercel, Netlify, etc.) |
| 190 | |
| 191 | ### 2. GitHub Token |
| 192 | |
| 193 | **Required Scopes:** |
| 194 | - Classic Token: `repo` scope |
| 195 | - Fine-Grained Token: `Contents: Read` + `Metadata: Read` |
| 196 | |
| 197 | **Create Token:** |
| 198 | 1. Go to https://github.com/settings/tokens |
| 199 | 2. Generate new token |
| 200 | 3. Select required scopes |
| 201 | 4. Copy token immediately |
| 202 | |
| 203 | ### 3. Release Assets |
| 204 | |
| 205 | **Upload to GitHub:** |
| 206 | 1. Create release tag (e.g., `v1.0.0`) |
| 207 | 2. Upload built application files |
| 208 | 3. Follow naming convention |
| 209 | 4. Publish release |
| 210 | |
| 211 | ## API Response Format |
| 212 | |
| 213 | ### Get Releases Response |
| 214 | |
| 215 | ```json |
| 216 | { |
| 217 | "version": "v1.0.0", |
| 218 | "name": "Release 1.0.0", |
| 219 | "published_at": "2024-01-15T10:00:00Z", |
| 220 | "downloads": [ |
| 221 | { |
| 222 | "platform": "macOS", |
| 223 | "architecture": "Apple Silicon", |
| 224 | "url": "/api/download-desktop-app?action=download&assetId=12345", |
| 225 | "filename": "pepakbasajawa-1.0.0-macos-arm64.dmg", |
| 226 | "size": 125829120, |
| 227 | "version": "v1.0.0", |
| 228 | "assetId": 12345 |
| 229 | }, |
| 230 | { |
| 231 | "platform": "macOS", |
| 232 | "architecture": "Intel", |
| 233 | "url": "/api/download-desktop-app?action=download&assetId=12346", |
| 234 | "filename": "pepakbasajawa-1.0.0-macos-x64.dmg", |
| 235 | "size": 123456789, |
| 236 | "version": "v1.0.0", |
| 237 | "assetId": 12346 |
| 238 | }, |
| 239 | { |
| 240 | "platform": "Windows", |
| 241 | "architecture": "x64", |
| 242 | "url": "/api/download-desktop-app?action=download&assetId=12347", |
| 243 | "filename": "pepakbasajawa-1.0.0-windows-x64.exe", |
| 244 | "size": 98765432, |
| 245 | "version": "v1.0.0", |
| 246 | "assetId": 12347 |
| 247 | }, |
| 248 | { |
| 249 | "platform": "Linux", |
| 250 | "architecture": "x64", |
| 251 | "url": "/api/download-desktop-app?action=download&assetId=12348", |
| 252 | "filename": "pepakbasajawa-1.0.0-linux-x64.AppImage", |
| 253 | "size": 87654321, |
| 254 | "version": "v1.0.0", |
| 255 | "assetId": 12348 |
| 256 | } |
| 257 | ] |
| 258 | } |
| 259 | ``` |
| 260 | |
| 261 | ### Error Response |
| 262 | |
| 263 | ```json |
| 264 | { |
| 265 | "error": "Failed to fetch releases", |
| 266 | "details": "GitHub API error message" |
| 267 | } |
| 268 | ``` |
| 269 | |
| 270 | ## Testing Checklist |
| 271 | |
| 272 | - [ ] Create `.env` file with `GITHUB_TOKEN` |
| 273 | - [ ] Run `npm run test:releases` to verify GitHub connection |
| 274 | - [ ] Create test release on GitHub with sample assets |
| 275 | - [ ] Start dev server: `npm run dev` |
| 276 | - [ ] Visit `http://localhost:4321/download` |
| 277 | - [ ] Verify all platforms are detected correctly |
| 278 | - [ ] Test downloading each asset type |
| 279 | - [ ] Check mobile responsiveness |
| 280 | - [ ] Verify error handling (remove token temporarily) |
| 281 | - [ ] Deploy to staging environment |
| 282 | - [ ] Test production environment |
| 283 | - [ ] Monitor API rate limits |
| 284 | |
| 285 | ## Performance Considerations |
| 286 | |
| 287 | ### Caching Strategy |
| 288 | |
| 289 | **API Response Cache:** |
| 290 | - Duration: 5 minutes (300 seconds) |
| 291 | - Type: Public cache |
| 292 | - Header: `Cache-Control: public, max-age=300` |
| 293 | |
| 294 | **Benefits:** |
| 295 | - Reduces GitHub API calls |
| 296 | - Faster page loads for subsequent visitors |
| 297 | - Stays within rate limits |
| 298 | |
| 299 | **Trade-offs:** |
| 300 | - New releases take up to 5 minutes to appear |
| 301 | - Can be adjusted in API endpoint if needed |
| 302 | |
| 303 | ### API Rate Limits |
| 304 | |
| 305 | **GitHub API:** |
| 306 | - Authenticated: 5,000 requests/hour |
| 307 | - Unauthenticated: 60 requests/hour |
| 308 | |
| 309 | **With 5-minute cache:** |
| 310 | - Max requests: 12 per hour per server |
| 311 | - Comfortable margin for high traffic |
| 312 | |
| 313 | ## Deployment Guide |
| 314 | |
| 315 | ### Vercel |
| 316 | |
| 317 | ```bash |
| 318 | # Add environment variable |
| 319 | vercel env add GITHUB_TOKEN |
| 320 | |
| 321 | # Deploy |
| 322 | vercel --prod |
| 323 | ``` |
| 324 | |
| 325 | ### Netlify |
| 326 | |
| 327 | ```bash |
| 328 | # Via Netlify CLI |
| 329 | netlify env:set GITHUB_TOKEN your_token_here |
| 330 | |
| 331 | # Or via dashboard: |
| 332 | # Site settings → Environment variables → Add variable |
| 333 | ``` |
| 334 | |
| 335 | ### Other Platforms |
| 336 | |
| 337 | Add `GITHUB_TOKEN` environment variable in platform dashboard. |
| 338 | |
| 339 | ## Monitoring & Maintenance |
| 340 | |
| 341 | ### What to Monitor |
| 342 | |
| 343 | 1. **GitHub API Rate Limits** |
| 344 | - Check usage at https://api.github.com/rate_limit |
| 345 | - Should stay well under 5,000/hour |
| 346 | |
| 347 | 2. **Error Logs** |
| 348 | - Monitor API errors |
| 349 | - Check for authentication failures |
| 350 | - Watch for malformed asset names |
| 351 | |
| 352 | 3. **Download Analytics** |
| 353 | - Track which platforms are popular |
| 354 | - Monitor download completion rates |
| 355 | |
| 356 | ### Maintenance Tasks |
| 357 | |
| 358 | 1. **Token Rotation** (Every 6-12 months) |
| 359 | - Generate new GitHub token |
| 360 | - Update environment variables |
| 361 | - Test thoroughly before rotating |
| 362 | |
| 363 | 2. **Release Management** |
| 364 | - Keep consistent naming convention |
| 365 | - Test detection before publishing |
| 366 | - Consider changelog display |
| 367 | |
| 368 | 3. **Performance Optimization** |
| 369 | - Adjust cache duration if needed |
| 370 | - Monitor API response times |
| 371 | - Consider CDN for assets |
| 372 | |
| 373 | ## Future Enhancements |
| 374 | |
| 375 | ### Possible Improvements |
| 376 | |
| 377 | 1. **Version History** |
| 378 | - Show previous releases |
| 379 | - Allow downloading older versions |
| 380 | - Display changelogs |
| 381 | |
| 382 | 2. **Download Statistics** |
| 383 | - Track download counts |
| 384 | - Show popularity metrics |
| 385 | - Analytics integration |
| 386 | |
| 387 | 3. **Auto-Update Checks** |
| 388 | - API endpoint for version checking |
| 389 | - Desktop app can check for updates |
| 390 | - Notify users of new versions |
| 391 | |
| 392 | 4. **Beta Releases** |
| 393 | - Support pre-release downloads |
| 394 | - Separate stable/beta channels |
| 395 | - Early access program |
| 396 | |
| 397 | 5. **Signature Verification** |
| 398 | - Display file checksums |
| 399 | - Provide GPG signatures |
| 400 | - Security verification guide |
| 401 | |
| 402 | 6. **Localization** |
| 403 | - Translate download page |
| 404 | - Multi-language support |
| 405 | - Platform-specific instructions |
| 406 | |
| 407 | ## Troubleshooting |
| 408 | |
| 409 | ### Common Issues |
| 410 | |
| 411 | **Issue:** "GITHUB_TOKEN is not configured" |
| 412 | - **Solution:** Verify `.env` file exists with token |
| 413 | - **Solution:** Check environment variables in production |
| 414 | - **Solution:** Restart dev server after adding token |
| 415 | |
| 416 | **Issue:** "Failed to fetch releases" |
| 417 | - **Solution:** Verify token has `repo` scope |
| 418 | - **Solution:** Check token hasn't expired |
| 419 | - **Solution:** Confirm repository name is correct |
| 420 | |
| 421 | **Issue:** No downloads showing |
| 422 | - **Solution:** Verify release exists and is marked as "latest" |
| 423 | - **Solution:** Check assets follow naming conventions |
| 424 | - **Solution:** Run `npm run test:releases` to debug |
| 425 | |
| 426 | **Issue:** Download links not working |
| 427 | - **Solution:** Check asset IDs are being passed correctly |
| 428 | - **Solution:** Verify token has download permissions |
| 429 | - **Solution:** Check API logs for errors |
| 430 | |
| 431 | ## Resources |
| 432 | |
| 433 | ### Documentation Files |
| 434 | - `DESKTOP_DOWNLOADS_SETUP.md` - Comprehensive setup guide |
| 435 | - `QUICK_START_DOWNLOADS.md` - Quick start guide |
| 436 | - `.env.example` - Environment variables template |
| 437 | |
| 438 | ### External References |
| 439 | - [GitHub Releases API](https://docs.github.com/en/rest/releases) |
| 440 | - [GitHub Authentication](https://docs.github.com/en/rest/authentication) |
| 441 | - [Astro API Routes](https://docs.astro.build/en/core-concepts/endpoints/) |
| 442 | - [Practical Bazel Blog Post](https://www.stevenengelhardt.com/2023/05/23/practical-bazel-downloading-private-release-assets-from-github/) |
| 443 | |
| 444 | ### Support |
| 445 | - Email: info@pepakbasajawa.com |
| 446 | - Repository: https://github.com/setoelkahfi/pepakbasajawa |
| 447 | - Web: https://github.com/setoelkahfi/pepakbasajawa-web |
| 448 | |
| 449 | ## Credits |
| 450 | |
| 451 | **Inspiration:** |
| 452 | - Steve Engelhardt's blog post on downloading private GitHub assets |
| 453 | - GitHub's API documentation and best practices |
| 454 | - Astro framework patterns for API routes |
| 455 | |
| 456 | **Implementation:** |
| 457 | - Secure token handling |
| 458 | - Type-safe TypeScript implementation |
| 459 | - Production-ready error handling |
| 460 | - Comprehensive documentation |
| 461 | |
| 462 | ## License |
| 463 | |
| 464 | This implementation is part of the PepakBasaJawa project. |
| 465 | |
| 466 | --- |
| 467 | |
| 468 | **Last Updated:** 2024 |
| 469 | **Version:** 1.0.0 |
| 470 | **Status:** Production Ready ✅ |