1 # Desktop Downloads Feature - README
2
3 Complete guide for the desktop application downloads system that fetches releases from private GitHub repositories.
4
5 ## 📋 Table of Contents
6
7 - [Overview](#overview)
8 - [Quick Start](#quick-start)
9 - [Features](#features)
10 - [Architecture](#architecture)
11 - [Setup](#setup)
12 - [Usage](#usage)
13 - [Configuration](#configuration)
14 - [API Reference](#api-reference)
15 - [Testing](#testing)
16 - [Deployment](#deployment)
17 - [Troubleshooting](#troubleshooting)
18 - [Best Practices](#best-practices)
19
20 ## Overview
21
22 This system provides secure download links for desktop applications stored in a private GitHub repository. It automatically detects platform and architecture from release assets and presents them in a user-friendly interface.
23
24 ### Key Features
25
26 - 🔒 **Secure**: GitHub tokens never exposed to clients
27 - 🚀 **Fast**: 5-minute response caching
28 - 📱 **Responsive**: Mobile-friendly design
29 - 🎯 **Smart Detection**: Automatic platform/architecture detection
30 - 🔧 **Type-Safe**: Full TypeScript support
31 - 📊 **Testable**: Built-in test utilities
32
33 ### Supported Platforms
34
35 - **macOS**: Apple Silicon (M1/M2/M3), Intel, Universal
36 - **Windows**: x64, ARM64, x86
37 - **Linux**: x64, ARM64 (AppImage, DEB, RPM, Snap)
38
39 ## Quick Start
40
41 ### 1. Create GitHub Token
42
43 ```bash
44 # Visit: https://github.com/settings/tokens
45 # Create token with 'repo' scope
46 # Copy the token
47 ```
48
49 ### 2. Configure Environment
50
51 ```bash
52 # Create .env file
53 echo "GITHUB_TOKEN=ghp_your_token_here" > .env
54 ```
55
56 ### 3. Test Connection
57
58 ```bash
59 # Verify GitHub API access
60 npm run test:releases
61 ```
62
63 ### 4. Start Development
64
65 ```bash
66 # Start dev server
67 npm run dev
68
69 # Visit download page
70 open http://localhost:4321/download
71 ```
72
73 ## Features
74
75 ### API Endpoint
76
77 **Location**: `/src/pages/api/download-desktop-app.ts`
78
79 - Fetches latest release from GitHub
80 - Authenticates with Personal Access Token
81 - Detects platforms and architectures
82 - Proxies downloads securely
83 - Caches responses (5 minutes)
84 - Full TypeScript types
85
86 ### Download Page
87
88 **Location**: `/src/pages/download.astro`
89
90 - Displays mobile app store links
91 - Shows desktop download options
92 - Real-time release fetching
93 - Platform-specific icons
94 - File size formatting
95 - Responsive design
96
97 ### Type System
98
99 **Location**: `/src/types/github-releases.ts`
100
101 - GitHub API response types
102 - Application-specific interfaces
103 - Platform detection patterns
104 - Type guards
105 - Full IntelliSense support
106
107 ## Architecture
108
109 ```
110 ┌─────────────┐
111 │ Browser │
112 │ (User) │
113 └──────┬──────┘
114 │ GET /download
115 ▼
116 ┌─────────────────┐
117 │ Download Page │ ← Astro SSG/SSR
118 └──────┬──────────┘
119 │ Fetch /api/download-desktop-app
120 ▼
121 ┌──────────────────────┐
122 │ API Endpoint │ ← Astro API Route
123 │ - Authenticate │
124 │ - Parse assets │
125 │ - Detect platforms │
126 └──────┬───────────────┘
127 │ Bearer Token Auth
128 ▼
129 ┌──────────────────┐
130 │ GitHub API │
131 │ Private Repo │
132 │ /releases │
133 └──────────────────┘
134 ```
135
136 ### Data Flow
137
138 1. **User visits** `/download` page
139 2. **JavaScript fetches** `/api/download-desktop-app`
140 3. **API authenticates** with GitHub using token
141 4. **GitHub returns** latest release data
142 5. **API parses** assets and detects platforms
143 6. **API returns** structured download links
144 7. **Page displays** download buttons
145 8. **User clicks** download
146 9. **API proxies** download with GitHub auth
147 10. **User receives** file
148
149 ## Setup
150
151 ### Prerequisites
152
153 - Node.js 18+ or compatible
154 - GitHub account with repository access
155 - Astro project (this is an Astro plugin/feature)
156
157 ### Installation
158
159 Files are already created. Just configure:
160
161 ```bash
162 # 1. Copy environment template
163 cp .env.example .env
164
165 # 2. Edit .env and add your GitHub token
166 nano .env
167 # Add: GITHUB_TOKEN=ghp_your_actual_token
168
169 # 3. Install dependencies (if needed)
170 npm install
171
172 # 4. Test setup
173 npm run test:releases
174 ```
175
176 ### GitHub Token Setup
177
178 #### Option 1: Classic Token
179
180 1. Go to https://github.com/settings/tokens
181 2. Click "Generate new token (classic)"
182 3. Name: "PepakBasaJawa Downloads"
183 4. Scopes: Select `repo` (Full control of private repositories)
184 5. Expiration: Choose duration
185 6. Generate and copy token
186
187 #### Option 2: Fine-Grained Token (Recommended)
188
189 1. Go to https://github.com/settings/tokens?type=beta
190 2. Click "Generate new token"
191 3. Name: "PepakBasaJawa Downloads"
192 4. Repository access: Select `setoelkahfi/pepakbasajawa`
193 5. Permissions:
194 - Contents: Read-only
195 - Metadata: Read-only (auto-selected)
196 6. Expiration: 1 year recommended
197 7. Generate and copy token
198
199 ### Environment Variables
200
201 **Development (.env)**:
202 ```env
203 GITHUB_TOKEN=ghp_your_token_here
204 ```
205
206 **Production**:
207 Add to your hosting platform's environment variables dashboard.
208
209 ## Usage
210
211 ### Creating Releases
212
213 1. **Build your desktop apps** (macOS, Windows, Linux)
214
215 2. **Name files consistently**:
216 ```
217 pepakbasajawa-1.0.0-macos-arm64.dmg
218 pepakbasajawa-1.0.0-macos-x64.dmg
219 pepakbasajawa-1.0.0-windows-x64.exe
220 pepakbasajawa-1.0.0-linux-x64.AppImage
221 ```
222
223 3. **Create GitHub release**:
224 ```bash
225 # Via GitHub web interface
226 # Or via gh CLI:
227 gh release create v1.0.0 \
228 dist/*.dmg \
229 dist/*.exe \
230 dist/*.AppImage \
231 --title "Release 1.0.0" \
232 --notes "Release notes here"
233 ```
234
235 ### File Naming Convention
236
237 Format: `{app}-{version}-{platform}-{arch}.{ext}`
238
239 **Examples**:
240 - ✅ `pepakbasajawa-1.0.0-macos-arm64.dmg`
241 - ✅ `pepakbasajawa-1.0.0-macos-x64.dmg`
242 - ✅ `pepakbasajawa-1.0.0-windows-x64.exe`
243 - ✅ `pepakbasajawa-1.0.0-windows-x64.msi`
244 - ✅ `pepakbasajawa-1.0.0-linux-x64.AppImage`
245 - ✅ `pepakbasajawa-1.0.0-linux-x64.deb`
246 - ❌ `app.dmg` (too generic)
247 - ❌ `release-v1.exe` (no platform info)
248
249 ## Configuration
250
251 ### Adjust Cache Duration
252
253 Edit `/src/pages/api/download-desktop-app.ts`:
254
255 ```typescript
256 return new Response(JSON.stringify(responseData), {
257 status: 200,
258 headers: {
259 'Content-Type': 'application/json',
260 'Cache-Control': 'public, max-age=300' // ← Change 300 to desired seconds
261 }
262 })
263 ```
264
265 ### Change Repository
266
267 Edit `/src/pages/api/download-desktop-app.ts`:
268
269 ```typescript
270 const GITHUB_REPO = 'setoelkahfi/pepakbasajawa' // ← Change to your repo
271 ```
272
273 ### Customize Platform Detection
274
275 Edit `/src/types/github-releases.ts`:
276
277 ```typescript
278 export const PLATFORM_PATTERNS = {
279 macOS: {
280 keywords: ['mac', 'darwin'], // ← Add more keywords
281 extensions: ['.dmg', '.pkg'],
282 // ...
283 }
284 }
285 ```
286
287 ## API Reference
288
289 ### GET /api/download-desktop-app
290
291 Fetches available desktop downloads.
292
293 **Response**:
294 ```json
295 {
296 "version": "v1.0.0",
297 "name": "Release 1.0.0",
298 "published_at": "2024-01-15T10:00:00Z",
299 "downloads": [
300 {
301 "platform": "macOS",
302 "architecture": "Apple Silicon",
303 "url": "/api/download-desktop-app?action=download&assetId=12345",
304 "filename": "pepakbasajawa-1.0.0-macos-arm64.dmg",
305 "size": 125829120,
306 "version": "v1.0.0",
307 "assetId": 12345
308 }
309 ]
310 }
311 ```
312
313 ### GET /api/download-desktop-app?action=download&assetId={id}
314
315 Downloads a specific asset.
316
317 **Parameters**:
318 - `action`: Must be "download"
319 - `assetId`: GitHub asset ID from releases response
320
321 **Response**: HTTP 302 redirect to temporary download URL
322
323 ## Testing
324
325 ### Test GitHub Connection
326
327 ```bash
328 npm run test:releases
329 ```
330
331 **Expected Output**:
332 ```
333 🔍 Testing GitHub API Connection
334
335 ✓ GitHub token found (ghp_abcd12...)
336 ✓ Repository: setoelkahfi/pepakbasajawa
337 ✓ Authenticated as: setoelkahfi
338 ✓ Found release: Release 1.0.0
339
340 📋 Release Assets:
341 ────────────────────────────────────
342 🍎 pepakbasajawa-1.0.0-macos-arm64.dmg
343 Platform: macOS (Apple Silicon)
344 Size: 120.00 MB
345 ...
346
347 ✅ All tests passed!
348 ```
349
350 ### Manual API Testing
351
352 ```bash
353 # Test releases endpoint
354 curl http://localhost:4321/api/download-desktop-app | jq
355
356 # Test download (replace asset ID)
357 curl -L "http://localhost:4321/api/download-desktop-app?action=download&assetId=12345" \
358 -o test-download.dmg
359 ```
360
361 ### Integration Testing
362
363 ```bash
364 # Start dev server
365 npm run dev
366
367 # In another terminal, test endpoints
368 curl http://localhost:4321/api/download-desktop-app
369
370 # Test in browser
371 open http://localhost:4321/download
372 ```
373
374 ## Deployment
375
376 ### Vercel
377
378 ```bash
379 # Set environment variable
380 vercel env add GITHUB_TOKEN
381 # Paste your token when prompted
382
383 # Deploy
384 vercel --prod
385 ```
386
387 Or via Vercel dashboard:
388 1. Project Settings → Environment Variables
389 2. Add `GITHUB_TOKEN` with your token
390 3. Redeploy
391
392 ### Netlify
393
394 ```bash
395 # Via CLI
396 netlify env:set GITHUB_TOKEN your_token_here
397
398 # Deploy
399 netlify deploy --prod
400 ```
401
402 Or via Netlify dashboard:
403 1. Site settings → Environment variables
404 2. Add variable: `GITHUB_TOKEN`
405 3. Redeploy site
406
407 ### Docker
408
409 ```dockerfile
410 FROM node:18-alpine
411 WORKDIR /app
412 COPY . .
413 RUN npm install && npm run build
414
415 ENV GITHUB_TOKEN=${GITHUB_TOKEN}
416
417 EXPOSE 4321
418 CMD ["npm", "run", "preview"]
419 ```
420
421 Build and run:
422 ```bash
423 docker build -t pepakbasajawa-web .
424 docker run -e GITHUB_TOKEN=your_token -p 4321:4321 pepakbasajawa-web
425 ```
426
427 ## Troubleshooting
428
429 ### Common Issues
430
431 #### 1. "GITHUB_TOKEN is not configured"
432
433 **Symptoms**: API returns 500 error
434 **Solutions**:
435 - Check `.env` file exists and contains token
436 - Verify token is not empty or commented out
437 - Restart dev server after adding token
438 - In production, check environment variables in hosting dashboard
439
440 ```bash
441 # Verify token is loaded
442 cat .env | grep GITHUB_TOKEN
443
444 # Restart server
445 npm run dev
446 ```
447
448 #### 2. "Failed to fetch releases"
449
450 **Symptoms**: API returns error or 404
451 **Solutions**:
452 - Verify token has correct permissions (`repo` scope)
453 - Check token hasn't expired
454 - Confirm repository name is correct
455 - Ensure at least one release exists
456
457 ```bash
458 # Test token manually
459 curl -H "Authorization: Bearer $GITHUB_TOKEN" \
460 https://api.github.com/repos/setoelkahfi/pepakbasajawa/releases/latest
461 ```
462
463 #### 3. No downloads showing on page
464
465 **Symptoms**: Page loads but no desktop downloads appear
466 **Solutions**:
467 - Check browser console for errors
468 - Verify release is marked as "latest" (not draft)
469 - Ensure release has uploaded assets
470 - Run `npm run test:releases` to debug
471
472 #### 4. Downloads not detected correctly
473
474 **Symptoms**: Files show as "Unknown" platform
475 **Solutions**:
476 - Check filename follows naming convention
477 - Add platform keywords to filename
478 - Verify file extension is standard (.dmg, .exe, .AppImage)
479 - Update detection patterns if needed
480
481 #### 5. Rate limit exceeded
482
483 **Symptoms**: API returns 403 after many requests
484 **Solutions**:
485 - Authenticated limit is 5,000/hour (should be plenty)
486 - Check cache is working (5-minute default)
487 - Monitor rate limit: `curl https://api.github.com/rate_limit`
488 - Consider increasing cache duration
489
490 ## Best Practices
491
492 ### Security
493
494 1. **Never commit tokens**
495 - Add `.env` to `.gitignore`
496 - Use environment variables
497 - Rotate tokens regularly
498
499 2. **Use fine-grained tokens**
500 - Limit scope to specific repository
501 - Read-only permissions
502 - Set expiration dates
503
504 3. **Monitor token usage**
505 - Check GitHub token logs
506 - Watch for suspicious activity
507 - Revoke compromised tokens immediately
508
509 ### Release Management
510
511 1. **Consistent naming**
512 - Use version tags (v1.0.0)
513 - Follow semantic versioning
514 - Include platform in filename
515
516 2. **Complete releases**
517 - Build all platforms
518 - Test on each platform
519 - Include changelogs
520
521 3. **Automation**
522 - Use GitHub Actions for releases
523 - Automate builds
524 - Run tests before publishing
525
526 ### Performance
527
528 1. **Caching**
529 - Keep 5-minute cache for balance
530 - Increase for stable releases
531 - Decrease for active development
532
533 2. **Asset optimization**
534 - Compress installers when possible
535 - Use appropriate formats
536 - Consider delta updates
537
538 3. **CDN**
539 - Consider CDN for large files
540 - GitHub provides good distribution
541 - Monitor download speeds
542
543 ## Support
544
545 ### Documentation
546
547 - **Setup Guide**: `DESKTOP_DOWNLOADS_SETUP.md`
548 - **Quick Start**: `QUICK_START_DOWNLOADS.md`
549 - **Implementation Details**: `IMPLEMENTATION_SUMMARY.md`
550
551 ### Contact
552
553 - **Email**: info@pepakbasajawa.com
554 - **Repository**: https://github.com/setoelkahfi/pepakbasajawa
555 - **Web**: https://github.com/setoelkahfi/pepakbasajawa-web
556
557 ### Resources
558
559 - [GitHub Releases API](https://docs.github.com/en/rest/releases)
560 - [Astro API Routes](https://docs.astro.build/en/core-concepts/endpoints/)
561 - [TypeScript Handbook](https://www.typescriptlang.org/docs/)
562
563 ## License
564
565 This feature is part of the PepakBasaJawa project.
566
567 ---
568
569 **Version**: 1.0.0
570 **Last Updated**: 2024
571 **Status**: ✅ Production Ready