a new start

This commit is contained in:
valknarness
2025-10-25 16:09:02 +02:00
commit b63592f153
94 changed files with 23058 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180" viewBox="0 0 180 180">
<defs>
<linearGradient id="bg-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#9733EE;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background with rounded corners for iOS -->
<rect width="180" height="180" rx="40" fill="url(#bg-gradient)" />
<!-- Awesome icon centered and scaled -->
<g transform="translate(90, 90) scale(2.8)">
<path fill="#FFFFFF" opacity="0.3" d="m14.8 8.625l-.3-1.5-4.95 1.05V2.5h-1.5v4.6125l-5.2125-3.375-.825 1.275 5.7 3.675-5.7 8.25 1.2.9 4.2375-5.55 3.15 4.7625 1.275-.825-3.15-4.6875z" />
<circle cx="9" cy="9" r="2.625" fill="#FFFFFF" />
<g fill="#FFFFFF" opacity="0.9">
<circle cx="9" cy="3" r="1.875" />
<circle cx="14.625" cy="7.875" r="1.875" />
<circle cx="2.625" cy="4.875" r="1.875" />
<circle cx="4.125" cy="15.375" r="1.875" />
<circle cx="12.75" cy="14.625" r="1.875" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

14
public/awesome-icon.svg Normal file
View File

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 48 48">
<!-- Main structure - Awesome Purple -->
<path fill="#9733EE" d="m39.4 23l-.8-4L26 21.6V8h-4v12.3l-13.9-9l-2.2 3.4l15.2 9.8L9.4 39.8l3.2 2.4l11.3-14.8l8.4 12.7l3.4-2.2l-8.4-12.5z" />
<!-- Center circle - Awesome Pink -->
<circle cx="24" cy="24" r="7" fill="#FF69B4" />
<!-- Outer circles - Gradient from Pink to Purple to Gold -->
<circle cx="24" cy="8" r="5" fill="#DA22FF" /> <!-- Top: Primary Purple -->
<circle cx="39" cy="21" r="5" fill="#FF69B4" /> <!-- Right: Pink -->
<circle cx="7" cy="13" r="5" fill="#FFD700" /> <!-- Left: Gold -->
<circle cx="11" cy="41" r="5" fill="#FF1493" /> <!-- Bottom Left: Dark Pink -->
<circle cx="34" cy="39" r="5" fill="#E855FF" /> <!-- Bottom Right: Light Purple -->
</svg>

After

Width:  |  Height:  |  Size: 864 B

14
public/favicon.svg Normal file
View File

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<defs>
<linearGradient id="favicon-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#FF69B4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Simplified for 16x16 favicon -->
<circle cx="8" cy="8" r="7" fill="url(#favicon-gradient)" />
<circle cx="8" cy="8" r="4" fill="#FF69B4" />
<circle cx="8" cy="8" r="2" fill="#FFFFFF" />
</svg>

After

Width:  |  Height:  |  Size: 659 B

27
public/icon-192.svg Normal file
View File

@@ -0,0 +1,27 @@
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 48 48">
<defs>
<linearGradient id="bg-192" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#9733EE;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background -->
<rect width="48" height="48" fill="url(#bg-192)" />
<!-- Main structure - White with opacity -->
<path fill="#FFFFFF" opacity="0.3" d="m39.4 23l-.8-4L26 21.6V8h-4v12.3l-13.9-9l-2.2 3.4l15.2 9.8L9.4 39.8l3.2 2.4l11.3-14.8l8.4 12.7l3.4-2.2l-8.4-12.5z" />
<!-- Center circle - White -->
<circle cx="24" cy="24" r="7" fill="#FFFFFF" />
<!-- Outer circles - White with high opacity -->
<g fill="#FFFFFF" opacity="0.9">
<circle cx="24" cy="8" r="5" />
<circle cx="39" cy="21" r="5" />
<circle cx="7" cy="13" r="5" />
<circle cx="11" cy="41" r="5" />
<circle cx="34" cy="39" r="5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

27
public/icon-512.svg Normal file
View File

@@ -0,0 +1,27 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 48 48">
<defs>
<linearGradient id="bg-512" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#9733EE;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background -->
<rect width="48" height="48" fill="url(#bg-512)" />
<!-- Main structure - White with opacity -->
<path fill="#FFFFFF" opacity="0.3" d="m39.4 23l-.8-4L26 21.6V8h-4v12.3l-13.9-9l-2.2 3.4l15.2 9.8L9.4 39.8l3.2 2.4l11.3-14.8l8.4 12.7l3.4-2.2l-8.4-12.5z" />
<!-- Center circle - White -->
<circle cx="24" cy="24" r="7" fill="#FFFFFF" />
<!-- Outer circles - White with high opacity -->
<g fill="#FFFFFF" opacity="0.9">
<circle cx="24" cy="8" r="5" />
<circle cx="39" cy="21" r="5" />
<circle cx="7" cy="13" r="5" />
<circle cx="11" cy="41" r="5" />
<circle cx="34" cy="39" r="5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

15
public/icon.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<!-- Simplified awesome icon for small sizes -->
<defs>
<linearGradient id="awesome-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#FF69B4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Center star shape -->
<circle cx="16" cy="16" r="14" fill="url(#awesome-gradient)" />
<circle cx="16" cy="16" r="8" fill="#FF69B4" />
<circle cx="16" cy="16" r="4" fill="#DA22FF" />
</svg>

After

Width:  |  Height:  |  Size: 708 B

46
public/manifest.json Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "Awesome - Curated Lists Explorer",
"short_name": "Awesome",
"description": "Next-level ground-breaking AAA webapp for exploring awesome lists from GitHub",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#DA22FF",
"orientation": "portrait-primary",
"icons": [
{
"src": "/icon.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any"
},
{
"src": "/icon-192.svg",
"sizes": "192x192",
"type": "image/svg+xml",
"purpose": "any"
},
{
"src": "/icon-512.svg",
"sizes": "512x512",
"type": "image/svg+xml",
"purpose": "any"
},
{
"src": "/apple-touch-icon.svg",
"sizes": "180x180",
"type": "image/svg+xml",
"purpose": "maskable"
}
],
"categories": ["productivity", "education", "developer-tools"],
"shortcuts": [
{
"name": "Search",
"short_name": "Search",
"description": "Search awesome lists",
"url": "/?action=search",
"icons": [{ "src": "/icons/search-96x96.png", "sizes": "96x96" }]
}
]
}

73
public/og-image.svg Normal file
View File

@@ -0,0 +1,73 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630">
<defs>
<linearGradient id="og-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="30%" style="stop-color:#9733EE;stop-opacity:1" />
<stop offset="70%" style="stop-color:#FF69B4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
<linearGradient id="text-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#DA22FF;stop-opacity:1" />
<stop offset="50%" style="stop-color:#9733EE;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FFD700;stop-opacity:1" />
</linearGradient>
<!-- Glow filter -->
<filter id="glow">
<feGaussianBlur stdDeviation="4" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="1200" height="630" fill="url(#og-gradient)" />
<!-- Decorative circles -->
<circle cx="100" cy="100" r="150" fill="#FFFFFF" opacity="0.05" />
<circle cx="1100" cy="530" r="200" fill="#FFFFFF" opacity="0.05" />
<circle cx="900" cy="100" r="120" fill="#FFD700" opacity="0.1" />
<circle cx="300" cy="500" r="80" fill="#FF69B4" opacity="0.15" />
<!-- Main content container -->
<rect x="100" y="150" width="1000" height="330" rx="20" fill="#FFFFFF" opacity="0.95" />
<!-- Awesome Icon (centered at top) -->
<g transform="translate(500, 200) scale(3.5)" filter="url(#glow)">
<path fill="#9733EE" d="m14.8 8.625l-.3-1.5-4.95 1.05V2.5h-1.5v4.6125l-5.2125-3.375-.825 1.275 5.7 3.675-5.7 8.25 1.2.9 4.2375-5.55 3.15 4.7625 1.275-.825-3.15-4.6875z" />
<circle cx="9" cy="9" r="2.625" fill="#FF69B4" />
<g fill="url(#text-gradient)">
<circle cx="9" cy="3" r="1.875" />
<circle cx="14.625" cy="7.875" r="1.875" />
<circle cx="2.625" cy="4.875" r="1.875" />
<circle cx="4.125" cy="15.375" r="1.875" />
<circle cx="12.75" cy="14.625" r="1.875" />
</g>
</g>
<!-- Title -->
<text x="600" y="340" font-family="system-ui, -apple-system, sans-serif" font-size="80" font-weight="900" text-anchor="middle" fill="url(#text-gradient)">
AWESOME
</text>
<!-- Subtitle -->
<text x="600" y="400" font-family="system-ui, -apple-system, sans-serif" font-size="32" font-weight="600" text-anchor="middle" fill="#666666">
Curated Lists Explorer
</text>
<!-- Stats -->
<g transform="translate(600, 440)">
<text x="-250" y="0" font-family="system-ui, -apple-system, sans-serif" font-size="24" font-weight="700" text-anchor="middle" fill="#9733EE">
209 Lists
</text>
<text x="0" y="0" font-family="system-ui, -apple-system, sans-serif" font-size="24" font-weight="700" text-anchor="middle" fill="#FF69B4">
14K+ Repos
</text>
<text x="250" y="0" font-family="system-ui, -apple-system, sans-serif" font-size="24" font-weight="700" text-anchor="middle" fill="#FFD700">
FTS5 Search
</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

170
public/worker.js Normal file
View File

@@ -0,0 +1,170 @@
/**
* Awesome Web Worker
* Intelligently polls for database updates and manages cache invalidation
*/
const POLL_INTERVAL = 5 * 60 * 1000; // 5 minutes
const DB_VERSION_ENDPOINT = '/api/db-version';
let currentDbVersion = null;
let pollTimer = null;
// Smart polling with exponential backoff
class SmartPoller {
constructor(interval) {
this.baseInterval = interval;
this.currentInterval = interval;
this.maxInterval = interval * 4;
this.minInterval = interval / 2;
this.consecutiveErrors = 0;
}
increaseInterval() {
this.currentInterval = Math.min(this.currentInterval * 1.5, this.maxInterval);
console.log('[Worker] Increased poll interval to', this.currentInterval / 1000, 'seconds');
}
decreaseInterval() {
this.currentInterval = Math.max(this.currentInterval * 0.75, this.minInterval);
console.log('[Worker] Decreased poll interval to', this.currentInterval / 1000, 'seconds');
}
resetInterval() {
this.currentInterval = this.baseInterval;
}
getInterval() {
return this.currentInterval;
}
}
const poller = new SmartPoller(POLL_INTERVAL);
// Check for database updates
async function checkForUpdates() {
try {
const response = await fetch(DB_VERSION_ENDPOINT, {
method: 'GET',
headers: {
'Cache-Control': 'no-cache',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// First time or version changed
if (currentDbVersion === null) {
currentDbVersion = data.version;
console.log('[Worker] Initial DB version:', currentDbVersion);
} else if (data.version !== currentDbVersion) {
console.log('[Worker] New DB version detected!', data.version);
// Notify all clients
const clients = await self.clients.matchAll();
clients.forEach(client => {
client.postMessage({
type: 'DB_UPDATE',
version: data.version,
metadata: data,
});
});
currentDbVersion = data.version;
// Invalidate cache
await invalidateCache();
}
// Reset error counter and adjust interval
poller.consecutiveErrors = 0;
poller.resetInterval();
} catch (error) {
console.error('[Worker] Poll failed:', error);
poller.consecutiveErrors++;
if (poller.consecutiveErrors > 3) {
poller.increaseInterval();
}
}
}
// Invalidate cache
async function invalidateCache() {
try {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(cacheName => {
if (cacheName.includes('awesome')) {
console.log('[Worker] Clearing cache:', cacheName);
return caches.delete(cacheName);
}
})
);
console.log('[Worker] Cache invalidated');
} catch (error) {
console.error('[Worker] Cache invalidation failed:', error);
}
}
// Start polling
function startPolling() {
if (pollTimer) {
clearInterval(pollTimer);
}
// Initial check
checkForUpdates();
// Schedule periodic checks
pollTimer = setInterval(() => {
checkForUpdates();
}, poller.getInterval());
console.log('[Worker] Polling started');
}
// Stop polling
function stopPolling() {
if (pollTimer) {
clearInterval(pollTimer);
pollTimer = null;
console.log('[Worker] Polling stopped');
}
}
// Service Worker event listeners
self.addEventListener('install', (event) => {
console.log('[Worker] Installing...');
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
console.log('[Worker] Activated');
event.waitUntil(self.clients.claim());
startPolling();
});
self.addEventListener('message', (event) => {
console.log('[Worker] Message received:', event.data);
if (event.data.type === 'CHECK_UPDATE') {
checkForUpdates();
} else if (event.data.type === 'START_POLLING') {
startPolling();
} else if (event.data.type === 'STOP_POLLING') {
stopPolling();
}
});
// Fetch event - cache strategy
self.addEventListener('fetch', (event) => {
// Add caching strategy here if needed
event.respondWith(fetch(event.request));
});