Skip to content

Commit 4b55a9e

Browse files
committed
docs: update favicon links and add stars goal section with progress bar
1 parent 94b63b4 commit 4b55a9e

File tree

2 files changed

+163
-16
lines changed

2 files changed

+163
-16
lines changed

public/index.html

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
<link rel="preconnect" href="https://pydoll.tech/" />
3333

3434
<!-- Favicon -->
35-
<link rel="icon" type="image/png" href="https://pydoll.tech/images/favicon.png" />
35+
<link rel="icon" type="image/png" href="/images/favicon.png" sizes="48x48 32x32 16x16" />
36+
<link rel="shortcut icon" type="image/png" href="/images/favicon.png" />
37+
<link rel="apple-touch-icon" href="/images/favicon.png" />
3638

3739
<!-- Tailwind CSS via CDN -->
3840
<script src="https://cdn.tailwindcss.com"></script>
@@ -250,9 +252,8 @@ <h1 class="text-4xl font-bold tracking-tight sm:text-6xl">
250252
</div>
251253
</section>
252254

253-
254255
<!-- Quick Intro / Features -->
255-
<section class="mx-auto max-w-7xl px-4 pt-16 pb-8 sm:px-6 lg:px-8">
256+
<section class="mx-auto max-w-7xl px-4 pt-10 pb-6 sm:px-6 lg:px-8">
256257
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
257258
<div class="reveal tilt-card rounded-xl border border-white/10 bg-slate-900/40 p-6 transition-transform duration-200 hover:shadow-[0_10px_30px_rgba(99,102,241,0.15)]">
258259
<h3 class="flex items-center gap-2 text-lg font-semibold">
@@ -317,9 +318,37 @@ <h3 class="flex items-center gap-2 text-lg font-semibold">
317318
</div>
318319
</section>
319320

321+
<!-- Stars Goal Section -->
322+
<section id="stars-goal" class="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
323+
<div class="reveal tilt-card rounded-xl border border-white/10 bg-slate-900/60 p-5 sm:p-6 transition-transform duration-200 hover:shadow-[0_10px_30px_rgba(99,102,241,0.15)]">
324+
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
325+
<div class="min-w-0">
326+
<h3 class="text-xl font-semibold">Help us reach 10k stars</h3>
327+
<p class="mt-1 text-sm text-slate-300">Help us reach 10k stars and keep the project alive and relevant!</p>
328+
<div class="mt-4">
329+
<div class="flex items-center justify-between text-xs text-slate-400">
330+
<span id="starsProgressLabel">0 / 10,000</span>
331+
<span id="starsProgressPct">0%</span>
332+
</div>
333+
<div class="mt-2 h-2 w-full rounded-full bg-white/10 overflow-hidden">
334+
<div id="starsProgressBar" class="h-2 rounded-full bg-brand-500" style="width:0%"></div>
335+
</div>
336+
</div>
337+
</div>
338+
<div class="flex flex-col items-start sm:items-end gap-3">
339+
<div class="min-w-[220px]">
340+
<p class="text-xs font-medium text-slate-300">Latest stargazers</p>
341+
<ul id="stargazersList" class="mt-2 flex flex-wrap items-center gap-2">
342+
<!-- Filled via JS -->
343+
</ul>
344+
</div>
345+
</div>
346+
</div>
347+
</div>
348+
</section>
320349
<!-- Install CTA -->
321350
<section id="install" class="overflow-x-hidden">
322-
<div class="mx-auto max-w-7xl px-4 py-14 sm:px-6 lg:px-8">
351+
<div class="mx-auto max-w-7xl px-4 py-10 sm:px-6 lg:px-8">
323352
<div class="grid grid-cols-1 items-center gap-8 lg:grid-cols-2">
324353
<div class="min-w-0">
325354
<h2 class="text-2xl font-bold tracking-tight">Install and get started in seconds</h2>
@@ -367,7 +396,7 @@ <h2 class="text-2xl font-bold tracking-tight">Install and get started in seconds
367396
</section>
368397

369398
<!-- Highlights (vertical minimalist cards) -->
370-
<section class="mx-auto max-w-7xl px-4 py-16 sm:px-6 lg:px-8">
399+
<section class="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
371400
<div class="mb-6">
372401
<h2 class="text-2xl font-bold tracking-tight">Highlights</h2>
373402
<p class="mt-1 text-sm text-slate-300">Key capabilities with simple examples.</p>
@@ -518,7 +547,7 @@ <h4 class="text-lg font-semibold">Concurrent automation example</h4>
518547
</div>
519548
</div>
520549
<!-- FAQ (near footer) -->
521-
<section id="faq" class="mx-auto max-w-7xl px-4 pt-4 pb-12 sm:px-6 lg:px-8">
550+
<section id="faq" class="mx-auto max-w-7xl px-4 pt-4 pb-10 sm:px-6 lg:px-8">
522551
<div class="mb-6">
523552
<h2 class="text-2xl font-bold tracking-tight">Frequently asked questions</h2>
524553
<p class="mt-1 text-sm text-slate-300">Top questions about Pydoll, its features and use cases.</p>
@@ -554,8 +583,9 @@ <h2 class="text-2xl font-bold tracking-tight">Frequently asked questions</h2>
554583
</details>
555584
</div>
556585
</section>
586+
557587
<!-- Final CTA (full width) -->
558-
<section class="mx-auto max-w-7xl px-4 pb-16 sm:px-6 lg:px-8">
588+
<section class="mx-auto max-w-7xl px-4 pb-10 sm:px-6 lg:px-8">
559589
<div class="reveal rounded-xl border border-white/10 bg-slate-900/60 p-5 sm:p-6">
560590
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
561591
<div>
@@ -576,7 +606,7 @@ <h4 class="text-lg font-semibold">Enjoying Pydoll?</h4>
576606
<div class="mx-auto max-w-7xl px-4 py-10 sm:px-6 lg:px-8">
577607
<div class="flex flex-col items-center justify-between gap-4 sm:flex-row">
578608
<div class="flex items-center gap-3">
579-
<img src="https://pydoll.tech/images/E2ECED-cinza-azulado.png" alt="Pydoll" class="h-6 w-auto" />
609+
<img src="https://pydoll.tech/images/logo.png" alt="Pydoll" class="h-6 w-auto" />
580610
<p class="text-sm text-slate-400">Pydoll - making browser automation magical ✨</p>
581611
</div>
582612
<div class="flex items-center gap-3 text-sm text-slate-400">

public/script.js

Lines changed: 125 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22
(async () => {
33
const repo = 'autoscrape-labs/pydoll'
44
const apiUrl = `https://api.github.com/repos/${repo}`
5+
let repoStarsCount = 0
6+
7+
// Simple localStorage cache with TTL
8+
const cacheGet = (key, maxAgeMs) => {
9+
try {
10+
const raw = localStorage.getItem(key)
11+
if (!raw) return null
12+
const parsed = JSON.parse(raw)
13+
if (!parsed || typeof parsed !== 'object') return null
14+
if (typeof parsed.t !== 'number') return null
15+
const now = Date.now()
16+
if (now - parsed.t > maxAgeMs) return null
17+
return parsed.v
18+
} catch (_) {
19+
return null
20+
}
21+
}
22+
const cacheSet = (key, value) => {
23+
try {
24+
localStorage.setItem(key, JSON.stringify({ t: Date.now(), v: value }))
25+
} catch (_) {}
26+
}
27+
const TTL = 5 * 60 * 1000 // 5 minutes
528

629
// Cursor glow effect (subtle follow)
730
const glow = document.getElementById('cursorGlow')
@@ -34,22 +57,116 @@
3457
hero.addEventListener('mousemove', move, { passive: true })
3558
}
3659

60+
// Stars, goal progress and latest stargazers
3761
try {
38-
const res = await fetch(apiUrl, { headers: { 'Accept': 'application/vnd.github+json' } })
39-
if (res.ok) {
40-
const data = await res.json()
41-
const stars = (data.stargazers_count ?? 0).toLocaleString('pt-BR')
62+
const cacheKey = `gh:repo:${repo}`
63+
let data = cacheGet(cacheKey, TTL)
64+
if (!data) {
65+
const res = await fetch(apiUrl, { headers: { 'Accept': 'application/vnd.github+json' } })
66+
if (res.ok) {
67+
data = await res.json()
68+
cacheSet(cacheKey, data)
69+
}
70+
}
71+
if (data) {
72+
const starsCount = Number(data.stargazers_count ?? 0)
73+
repoStarsCount = starsCount
74+
const starsFmt = starsCount.toLocaleString('pt-BR')
4275

4376
const starCount = document.getElementById('starCount')
44-
if (starCount) {
45-
starCount.textContent = `${stars}★`
46-
}
47-
// forks removidos da UI
77+
if (starCount) starCount.textContent = `${starsFmt}★`
78+
79+
// Update progress bar to 10k
80+
const GOAL = 10000
81+
const pct = Math.max(0, Math.min(100, Math.round((starsCount / GOAL) * 100)))
82+
const bar = document.getElementById('starsProgressBar')
83+
const label = document.getElementById('starsProgressLabel')
84+
const pctLabel = document.getElementById('starsProgressPct')
85+
if (bar) bar.style.width = `${pct}%`
86+
if (label) label.textContent = `${starsFmt} / ${GOAL.toLocaleString('pt-BR')}`
87+
if (pctLabel) pctLabel.textContent = `${pct}%`
4888
}
4989
} catch (_) {
5090
// noop: keep placeholders on failure
5191
}
5292

93+
// Fetch latest stargazers (last 10, newest first, fill from previous page if needed)
94+
try {
95+
const perPage = 10
96+
const lastPage = Math.max(1, Math.ceil((repoStarsCount || 1) / perPage))
97+
98+
const fetchPage = async (page) => {
99+
const cacheKey = `gh:stargazers:${repo}:p${page}:pp${perPage}`
100+
let payload = cacheGet(cacheKey, TTL)
101+
if (!payload) {
102+
const res = await fetch(`https://api.github.com/repos/${repo}/stargazers?per_page=${perPage}&page=${page}`, {
103+
headers: { 'Accept': 'application/vnd.github.v3.star+json' }
104+
})
105+
if (!res.ok) return []
106+
payload = await res.json()
107+
cacheSet(cacheKey, payload)
108+
}
109+
if (!Array.isArray(payload)) return []
110+
if (payload.length && (payload[0]?.user || payload[0]?.starred_at)) {
111+
return payload
112+
.map((it) => ({
113+
login: it?.user?.login,
114+
avatar_url: it?.user?.avatar_url,
115+
html_url: it?.user?.html_url || (it?.user?.login ? `https://github.com/${it.user.login}` : '#'),
116+
starred_at: it?.starred_at ? Date.parse(it.starred_at) : 0
117+
}))
118+
.filter((u) => u.login)
119+
}
120+
// Fallback if server ignores star+json
121+
return payload.map((u) => ({
122+
login: u.login,
123+
avatar_url: u.avatar_url,
124+
html_url: u.html_url || (u.login ? `https://github.com/${u.login}` : '#'),
125+
starred_at: 0
126+
}))
127+
}
128+
129+
let entries = await fetchPage(lastPage)
130+
if (entries.length < perPage && lastPage > 1) {
131+
const prev = await fetchPage(lastPage - 1)
132+
entries = entries.concat(prev)
133+
}
134+
135+
// Sort newest first and cap to perPage
136+
entries.sort((a, b) => b.starred_at - a.starred_at)
137+
entries = entries.slice(0, perPage)
138+
139+
// Render
140+
const list = document.getElementById('stargazersList')
141+
if (list) {
142+
entries.forEach((u) => {
143+
const li = document.createElement('li')
144+
li.className = 'flex items-center gap-2'
145+
const a = document.createElement('a')
146+
a.href = u.html_url
147+
a.target = '_blank'
148+
a.rel = 'noopener'
149+
a.className = 'group inline-flex items-center gap-2 rounded-full border border-white/10 bg-slate-800/60 px-3 py-1.5 text-sm text-slate-200 hover:bg-slate-800'
150+
const img = document.createElement('img')
151+
img.src = u.avatar_url
152+
img.alt = u.login
153+
img.width = 22
154+
img.height = 22
155+
img.loading = 'lazy'
156+
img.decoding = 'async'
157+
img.className = 'h-[22px] w-[22px] rounded-full ring-1 ring-white/10'
158+
const span = document.createElement('span')
159+
span.textContent = u.login
160+
a.appendChild(img)
161+
a.appendChild(span)
162+
li.appendChild(a)
163+
list.appendChild(li)
164+
})
165+
}
166+
} catch (_) {
167+
// ignore
168+
}
169+
53170
// Copy install command
54171
const copyBtn = document.getElementById('copyBtn')
55172
const installCmd = document.getElementById('installCmd')

0 commit comments

Comments
 (0)