Desktop Downloads Implementation Summary

Overview

Successfully implemented a secure, production-ready system to fetch and display desktop application download links from a private GitHub repository.

What Was Built

1. API Endpoint (/api/download-desktop-app)

Location: /src/pages/api/download-desktop-app.ts

Features: - Fetches latest release from private GitHub repository - Authenticates using GitHub Personal Access Token - Automatically detects platform and architecture from filenames - Proxies downloads to keep GitHub token secure - Includes 5-minute cache to reduce API calls - Type-safe implementation with TypeScript

Endpoints: - GET /api/download-desktop-app - Returns list of available downloads - GET /api/download-desktop-app?action=download&assetId=123 - Proxies asset download

2. Download Page (/download)

Location: /src/pages/download.astro

Features: - Mobile and App Store download links - Dynamic desktop downloads section - Client-side JavaScript fetches releases - Responsive design with platform-specific icons - Shows version, file size, and architecture - Graceful error handling

Displays: - 🍎 macOS (Apple Silicon, Intel, Universal) - 🪟 Windows (x64, ARM64) - 🐧 Linux (x64, ARM64, various formats)

3. Type Definitions

Location: /src/types/github-releases.ts

Includes: - GitHub API response types - Application-specific types - Platform detection patterns - Type guards for runtime validation - Full TypeScript intellisense support

4. Test Script

Location: /scripts/test-github-releases.js

Capabilities: - Tests GitHub API authentication - Verifies token permissions - Lists all release assets - Analyzes platform detection - Provides debugging information - Color-coded output for readability

Usage: bash npm run test:releases

5. Documentation

Files Created: 1. DESKTOP_DOWNLOADS_SETUP.md - Comprehensive setup guide 2. QUICK_START_DOWNLOADS.md - 5-minute quick start 3. IMPLEMENTATION_SUMMARY.md - This file 4. .env.example - Environment variables template

Technical Architecture

┌──────────────────────────────────────────────────────────────┐
│                         Browser                              │
│  ┌────────────────────────────────────────────────────┐     │
│  │         Download Page (/download)                  │     │
│  │  • Lists mobile app stores                         │     │
│  │  • Fetches desktop downloads via API               │     │
│  └─────────────────┬──────────────────────────────────┘     │
└────────────────────┼──────────────────────────────────────────┘
                     │
                     │ HTTPS Request
                     ▼
┌──────────────────────────────────────────────────────────────┐
│                    API Server (Astro)                        │
│  ┌────────────────────────────────────────────────────┐     │
│  │   API Endpoint (/api/download-desktop-app)         │     │
│  │  • Authenticates with GitHub token                 │     │
│  │  • Parses release assets                           │     │
│  │  • Detects platforms/architectures                 │     │
│  │  • Returns structured data or proxies download     │     │
│  └─────────────────┬──────────────────────────────────┘     │
└────────────────────┼──────────────────────────────────────────┘
                     │
                     │ Authenticated Request
                     │ (Bearer token)
                     ▼
┌──────────────────────────────────────────────────────────────┐
│                      GitHub API                              │
│  ┌────────────────────────────────────────────────────┐     │
│  │   Private Repository                               │     │
│  │   (setoelkahfi/pepakbasajawa)                     │     │
│  │  • /releases/latest                                │     │
│  │  • /releases/assets/:id                            │     │
│  └────────────────────────────────────────────────────┘     │
└──────────────────────────────────────────────────────────────┘

Security Features

1. Token Protection

  • GitHub token never exposed to client
  • Stored securely in environment variables
  • Used only in server-side API routes

2. Download Proxying

  • Downloads go through API endpoint
  • API authenticates with GitHub on user's behalf
  • GitHub provides temporary redirect URLs
  • Users don't need GitHub accounts

3. Fine-Grained Permissions

  • Token only needs repo scope (or just Contents: Read)
  • No unnecessary permissions granted
  • Can use fine-grained tokens for better security

4. Rate Limiting

  • 5-minute cache reduces API calls
  • GitHub allows 5,000 authenticated requests/hour
  • More than sufficient for production traffic

Platform Detection Logic

Detection Patterns

macOS: - Keywords: mac, darwin - Extensions: .dmg, .pkg - Architectures: - Apple Silicon: arm64, aarch64, apple - Intel: x64, x86_64, intel - Universal: universal or no architecture specified

Windows: - Keywords: win, windows - Extensions: .exe, .msi, .msix - Architectures: - x64: x64, x86_64, amd64 - ARM64: arm64, aarch64

Linux: - Keywords: linux - Extensions: .appimage, .deb, .rpm, .tar.gz, .snap - Architectures: - x64: x64, x86_64, amd64 - ARM64: arm64, aarch64

{app-name}-{version}-{platform}-{arch}.{ext}

Examples:
✅ pepakbasajawa-1.0.0-macos-arm64.dmg
✅ pepakbasajawa-1.0.0-macos-x64.dmg
✅ pepakbasajawa-1.0.0-windows-x64.exe
✅ pepakbasajawa-1.0.0-linux-x64.AppImage
✅ pepakbasajawa-1.0.0-linux-x64.deb

Setup Requirements

1. Environment Variables

Development (.env): env GITHUB_TOKEN=ghp_your_token_here

Production: Set in hosting platform dashboard (Vercel, Netlify, etc.)

2. GitHub Token

Required Scopes: - Classic Token: repo scope - Fine-Grained Token: Contents: Read + Metadata: Read

Create Token: 1. Go to https://github.com/settings/tokens 2. Generate new token 3. Select required scopes 4. Copy token immediately

3. Release Assets

Upload to GitHub: 1. Create release tag (e.g., v1.0.0) 2. Upload built application files 3. Follow naming convention 4. Publish release

API Response Format

Get Releases Response

{
  "version": "v1.0.0",
  "name": "Release 1.0.0",
  "published_at": "2024-01-15T10:00:00Z",
  "downloads": [
    {
      "platform": "macOS",
      "architecture": "Apple Silicon",
      "url": "/api/download-desktop-app?action=download&assetId=12345",
      "filename": "pepakbasajawa-1.0.0-macos-arm64.dmg",
      "size": 125829120,
      "version": "v1.0.0",
      "assetId": 12345
    },
    {
      "platform": "macOS",
      "architecture": "Intel",
      "url": "/api/download-desktop-app?action=download&assetId=12346",
      "filename": "pepakbasajawa-1.0.0-macos-x64.dmg",
      "size": 123456789,
      "version": "v1.0.0",
      "assetId": 12346
    },
    {
      "platform": "Windows",
      "architecture": "x64",
      "url": "/api/download-desktop-app?action=download&assetId=12347",
      "filename": "pepakbasajawa-1.0.0-windows-x64.exe",
      "size": 98765432,
      "version": "v1.0.0",
      "assetId": 12347
    },
    {
      "platform": "Linux",
      "architecture": "x64",
      "url": "/api/download-desktop-app?action=download&assetId=12348",
      "filename": "pepakbasajawa-1.0.0-linux-x64.AppImage",
      "size": 87654321,
      "version": "v1.0.0",
      "assetId": 12348
    }
  ]
}

Error Response

{
  "error": "Failed to fetch releases",
  "details": "GitHub API error message"
}

Testing Checklist

  • Create .env file with GITHUB_TOKEN
  • Run npm run test:releases to verify GitHub connection
  • Create test release on GitHub with sample assets
  • Start dev server: npm run dev
  • Visit http://localhost:4321/download
  • Verify all platforms are detected correctly
  • Test downloading each asset type
  • Check mobile responsiveness
  • Verify error handling (remove token temporarily)
  • Deploy to staging environment
  • Test production environment
  • Monitor API rate limits

Performance Considerations

Caching Strategy

API Response Cache: - Duration: 5 minutes (300 seconds) - Type: Public cache - Header: Cache-Control: public, max-age=300

Benefits: - Reduces GitHub API calls - Faster page loads for subsequent visitors - Stays within rate limits

Trade-offs: - New releases take up to 5 minutes to appear - Can be adjusted in API endpoint if needed

API Rate Limits

GitHub API: - Authenticated: 5,000 requests/hour - Unauthenticated: 60 requests/hour

With 5-minute cache: - Max requests: 12 per hour per server - Comfortable margin for high traffic

Deployment Guide

Vercel

# Add environment variable
vercel env add GITHUB_TOKEN

# Deploy
vercel --prod

Netlify

# Via Netlify CLI
netlify env:set GITHUB_TOKEN your_token_here

# Or via dashboard:
# Site settings → Environment variables → Add variable

Other Platforms

Add GITHUB_TOKEN environment variable in platform dashboard.

Monitoring & Maintenance

What to Monitor

  1. GitHub API Rate Limits

  2. Error Logs

    • Monitor API errors
    • Check for authentication failures
    • Watch for malformed asset names
  3. Download Analytics

    • Track which platforms are popular
    • Monitor download completion rates

Maintenance Tasks

  1. Token Rotation (Every 6-12 months)

    • Generate new GitHub token
    • Update environment variables
    • Test thoroughly before rotating
  2. Release Management

    • Keep consistent naming convention
    • Test detection before publishing
    • Consider changelog display
  3. Performance Optimization

    • Adjust cache duration if needed
    • Monitor API response times
    • Consider CDN for assets

Future Enhancements

Possible Improvements

  1. Version History

    • Show previous releases
    • Allow downloading older versions
    • Display changelogs
  2. Download Statistics

    • Track download counts
    • Show popularity metrics
    • Analytics integration
  3. Auto-Update Checks

    • API endpoint for version checking
    • Desktop app can check for updates
    • Notify users of new versions
  4. Beta Releases

    • Support pre-release downloads
    • Separate stable/beta channels
    • Early access program
  5. Signature Verification

    • Display file checksums
    • Provide GPG signatures
    • Security verification guide
  6. Localization

    • Translate download page
    • Multi-language support
    • Platform-specific instructions

Troubleshooting

Common Issues

Issue: "GITHUB_TOKEN is not configured" - Solution: Verify .env file exists with token - Solution: Check environment variables in production - Solution: Restart dev server after adding token

Issue: "Failed to fetch releases" - Solution: Verify token has repo scope - Solution: Check token hasn't expired - Solution: Confirm repository name is correct

Issue: No downloads showing - Solution: Verify release exists and is marked as "latest" - Solution: Check assets follow naming conventions - Solution: Run npm run test:releases to debug

Issue: Download links not working - Solution: Check asset IDs are being passed correctly - Solution: Verify token has download permissions - Solution: Check API logs for errors

Resources

Documentation Files

  • DESKTOP_DOWNLOADS_SETUP.md - Comprehensive setup guide
  • QUICK_START_DOWNLOADS.md - Quick start guide
  • .env.example - Environment variables template

External References

Support

Credits

Inspiration: - Steve Engelhardt's blog post on downloading private GitHub assets - GitHub's API documentation and best practices - Astro framework patterns for API routes

Implementation: - Secure token handling - Type-safe TypeScript implementation - Production-ready error handling - Comprehensive documentation

License

This implementation is part of the PepakBasaJawa project.


Last Updated: 2024 Version: 1.0.0 Status: Production Ready ✅