Skip to content

Commit 8d4918e

Browse files
committed
Update mobile nav and also make github stat gathering more intellegent
1 parent 474114f commit 8d4918e

File tree

11 files changed

+1165
-7
lines changed

11 files changed

+1165
-7
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Update GitHub Stats
2+
3+
on:
4+
schedule:
5+
# Run every day at 2:00 AM UTC
6+
- cron: '0 2 * * *'
7+
workflow_dispatch: # Allow manual triggering
8+
push:
9+
branches:
10+
- main
11+
- new-landing-page
12+
paths:
13+
- 'scripts/update-github-stats.js'
14+
- '.github/workflows/update-github-stats.yml'
15+
16+
permissions:
17+
contents: write
18+
19+
jobs:
20+
update-stats:
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version: '18'
33+
34+
- name: Update GitHub stats
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
run: |
38+
node scripts/update-github-stats.js
39+
40+
- name: Check if stats were updated
41+
id: check-changes
42+
run: |
43+
if git diff --quiet data/github-stats.json; then
44+
echo "No changes to commit"
45+
echo "changes=false" >> $GITHUB_OUTPUT
46+
else
47+
echo "Stats have been updated"
48+
echo "changes=true" >> $GITHUB_OUTPUT
49+
fi
50+
51+
- name: Commit and push if stats changed
52+
if: steps.check-changes.outputs.changes == 'true'
53+
run: |
54+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
55+
git config --local user.name "github-actions[bot]"
56+
git add data/github-stats.json
57+
git commit -m "chore: update GitHub repository statistics [skip ci]"
58+
git push

data/github-stats.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"stars": 3435,
3+
"forks": 108,
4+
"contributors": 41,
5+
"lastUpdated": "2025-08-01T16:35:38.030Z"
6+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# GitHub Stats Implementation Guide
2+
3+
## Overview
4+
5+
The Positron website displays real-time GitHub repository statistics (stars, forks, contributors) using a flexible system that supports both live API fetching and static fallbacks.
6+
7+
## Architecture
8+
9+
### Components
10+
11+
1. **Static JSON File** (`data/github-stats.json`)
12+
- Updated daily via GitHub Actions
13+
- Serves as fallback when API is unavailable
14+
- No rate limit concerns
15+
16+
2. **Client-side JavaScript** (`js/github-stats-unified.js`)
17+
- Supports three modes: `live`, `static`, and `auto`
18+
- Implements caching to reduce API calls
19+
- Gracefully handles rate limits
20+
21+
3. **Configuration** (`js/github-stats-config.js`)
22+
- Simple configuration file to set fetching mode
23+
- Can be modified without touching main script
24+
25+
4. **GitHub Action** (`.github/workflows/update-github-stats.yml`)
26+
- Runs daily to update static JSON
27+
- Ensures fallback data is always fresh
28+
29+
### Fetching Modes
30+
31+
#### 1. Live Mode (`'live'`)
32+
- Fetches directly from GitHub API
33+
- Real-time data
34+
- Subject to rate limits (60 requests/hour for unauthenticated)
35+
- Best for development or low-traffic sites
36+
37+
```javascript
38+
window.GITHUB_STATS_MODE = 'live';
39+
```
40+
41+
#### 2. Static Mode (`'static'`)
42+
- Uses pre-generated JSON file only
43+
- No API calls from client
44+
- Updated daily via GitHub Actions
45+
- Best for high-traffic sites
46+
47+
```javascript
48+
window.GITHUB_STATS_MODE = 'static';
49+
```
50+
51+
#### 3. Auto Mode (`'auto'`) - Default
52+
- Tries live API first
53+
- Falls back to static if rate limited
54+
- Best balance of freshness and reliability
55+
56+
```javascript
57+
window.GITHUB_STATS_MODE = 'auto'; // or omit for default
58+
```
59+
60+
## Rate Limit Considerations
61+
62+
### GitHub API Limits
63+
- **Unauthenticated**: 60 requests/hour per IP
64+
- **Authenticated**: 5,000 requests/hour (not used in client)
65+
66+
### Our Implementation
67+
- **Caching**: 1-hour client-side cache via localStorage
68+
- **Smart Fetching**: Contributors limited to first 100 (1-2 API calls)
69+
- **Fallback**: Automatic switch to static data when rate limited
70+
71+
### Traffic Calculations
72+
With 1-hour caching:
73+
- Each unique visitor: 2 API calls (repo info + contributors)
74+
- Supports ~30 unique visitors/hour in live mode
75+
- Unlimited in static mode
76+
77+
## HTML Implementation
78+
79+
Elements use data attributes for identification:
80+
81+
```html
82+
<!-- Simple stat -->
83+
<span data-stat="forks">108</span>
84+
85+
<!-- Formatted stat -->
86+
<div data-stat="stars" data-format="short-plus">3.4k+</div>
87+
88+
<!-- Stat with nested elements -->
89+
<span data-stat="stars" data-format="short">
90+
<svg>...</svg>
91+
<span class="stat-number">3.4k</span>
92+
</span>
93+
```
94+
95+
## Debugging
96+
97+
Open browser console and use:
98+
99+
```javascript
100+
// Check current mode
101+
GitHubStats.getMode()
102+
103+
// Force refresh
104+
GitHubStats.refresh()
105+
106+
// Clear cache
107+
GitHubStats.clearCache()
108+
109+
// Check if stats loaded
110+
document.body.getAttribute('data-github-stats-loaded')
111+
```
112+
113+
## Adding New Stats
114+
115+
1. Update `scripts/update-github-stats.js` to fetch new stat
116+
2. Add to JSON structure
117+
3. Add HTML element with appropriate `data-stat` attribute
118+
4. Stats will automatically update
119+
120+
## Performance Tips
121+
122+
1. **High Traffic Sites**: Use `'static'` mode
123+
2. **Low Traffic Sites**: Use `'auto'` or `'live'` mode
124+
3. **Development**: Use `'live'` mode with `GitHubStats.clearCache()`
125+
126+
## Security Notes
127+
128+
- No authentication tokens in client-side code
129+
- API calls are read-only
130+
- CORS handled by GitHub's API
131+
- Fallback ensures site never breaks
132+
133+
## Future Enhancements
134+
135+
Possible improvements:
136+
1. WebSocket for real-time updates
137+
2. Service Worker for better caching
138+
3. GraphQL API for more efficient queries
139+
4. Server-side proxy for authenticated requests

index.html

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424

2525
<!-- Styles -->
2626
<link rel="stylesheet" href="landing.css">
27+
28+
<!-- Scripts -->
29+
<!-- Configure GitHub stats fetching mode: 'live', 'static', or 'auto' (default) -->
30+
<script src="js/github-stats-config.js"></script>
31+
<script src="js/github-stats-unified.js" defer></script>
2732
</head>
2833
<body>
2934
<!-- Navigation Header -->
@@ -72,6 +77,34 @@
7277
</button>
7378
</div>
7479
</nav>
80+
81+
<!-- Mobile Menu -->
82+
<div class="nav-mobile-menu">
83+
<a href="start.html" class="nav-link">
84+
<svg class="nav-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
85+
<path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z"/>
86+
</svg>
87+
Getting Started
88+
</a>
89+
<a href="add-to-path.html" class="nav-link">
90+
<svg class="nav-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
91+
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
92+
</svg>
93+
Guides
94+
</a>
95+
<a href="troubleshooting.html" class="nav-link">
96+
<svg class="nav-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
97+
<path stroke-linecap="round" stroke-linejoin="round" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
98+
</svg>
99+
Help
100+
</a>
101+
<a href="download.html" class="nav-link nav-link-cta">
102+
<svg class="nav-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
103+
<path stroke-linecap="round" stroke-linejoin="round" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10"/>
104+
</svg>
105+
Download
106+
</a>
107+
</div>
75108
</header>
76109

77110
<main>
@@ -317,20 +350,20 @@ <h3 class="community-card-title">GitHub</h3>
317350
<div class="community-stats">
318351
<div class="community-stat">
319352
<span class="stat-label">Stars</span>
320-
<span class="stat-value">
353+
<span class="stat-value" data-stat="stars" data-format="short">
321354
<svg class="stat-icon" fill="currentColor" viewBox="0 0 20 20">
322355
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
323356
</svg>
324-
3.4k
357+
<span class="stat-number">3.4k</span>
325358
</span>
326359
</div>
327360
<div class="community-stat">
328361
<span class="stat-label">Forks</span>
329-
<span class="stat-value">108</span>
362+
<span class="stat-value" data-stat="forks">108</span>
330363
</div>
331364
<div class="community-stat">
332365
<span class="stat-label">Contributors</span>
333-
<span class="stat-value">100+</span>
366+
<span class="stat-value" data-stat="contributors">41</span>
334367
</div>
335368
</div>
336369
<a href="https://github.com/posit-dev/positron" target="_blank" rel="noopener noreferrer"
@@ -410,12 +443,12 @@ <h3 class="community-card-title">Documentation</h3>
410443
<div class="community-stats-bar">
411444
<a href="https://github.com/posit-dev/positron/stargazers" target="_blank" rel="noopener noreferrer"
412445
class="stats-bar-item">
413-
<div class="stats-bar-value">3.4k+</div>
446+
<div class="stats-bar-value" data-stat="stars" data-format="short-plus">3.4k+</div>
414447
<div class="stats-bar-label">GitHub Stars</div>
415448
</a>
416449
<a href="https://github.com/posit-dev/positron/graphs/contributors" target="_blank" rel="noopener noreferrer"
417450
class="stats-bar-item">
418-
<div class="stats-bar-value">100+</div>
451+
<div class="stats-bar-value" data-stat="contributors">41</div>
419452
<div class="stats-bar-label">Contributors</div>
420453
</a>
421454
<a href="https://github.com/posit-dev/positron/discussions" target="_blank" rel="noopener noreferrer"
@@ -504,6 +537,45 @@ <h3 class="footer-heading">Posit</h3>
504537

505538
lastScroll = currentScroll;
506539
});
540+
541+
// Mobile menu toggle functionality
542+
const mobileToggle = document.querySelector('.nav-mobile-toggle');
543+
const mobileMenu = document.querySelector('.nav-mobile-menu');
544+
const siteNav = document.querySelector('.site-nav');
545+
546+
function openMobileMenu() {
547+
mobileMenu.classList.add('active');
548+
siteNav.classList.add('menu-open');
549+
mobileToggle.setAttribute('aria-expanded', 'true');
550+
}
551+
552+
function closeMobileMenu() {
553+
mobileMenu.classList.remove('active');
554+
mobileToggle.setAttribute('aria-expanded', 'false');
555+
siteNav.classList.remove('menu-open');
556+
}
557+
558+
mobileToggle.addEventListener('click', () => {
559+
if (mobileMenu.classList.contains('active')) {
560+
closeMobileMenu();
561+
} else {
562+
openMobileMenu();
563+
}
564+
});
565+
566+
// Close mobile menu when clicking outside
567+
document.addEventListener('click', (e) => {
568+
if (!mobileToggle.contains(e.target) && !mobileMenu.contains(e.target) && mobileMenu.classList.contains('active')) {
569+
closeMobileMenu();
570+
}
571+
});
572+
573+
// Close mobile menu when resizing to desktop
574+
window.addEventListener('resize', () => {
575+
if (window.innerWidth >= 768 && mobileMenu.classList.contains('active')) {
576+
closeMobileMenu();
577+
}
578+
});
507579
</script>
508580
</body>
509581
</html>

js/github-stats-config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* GitHub Stats Configuration
3+
*
4+
* This file allows you to configure how GitHub stats are fetched.
5+
* Options:
6+
* - 'live': Fetch directly from GitHub API (real-time but subject to rate limits)
7+
* - 'static': Use pre-generated JSON file (updated daily via GitHub Actions)
8+
* - 'auto': Try live first, fall back to static if rate limited (default)
9+
*/
10+
11+
window.GITHUB_STATS_MODE = 'auto'; // Change to 'live' or 'static' as needed

0 commit comments

Comments
 (0)