diff --git a/frontend/about.html b/frontend/about.html new file mode 100644 index 0000000..135ff0b --- /dev/null +++ b/frontend/about.html @@ -0,0 +1,43 @@ + + +
+ + +You think you have too many tabs open?
+ +Welcome to EveryTab, a collection of every site on the Web.
+ +The data comes from Common Crawl, a free, open archive of the web. Every month, we process the latest crawl, extract website titles, download the favicons, and bundle it up into the site you see here.
+ +Click on a tab to visit the site and scroll down for more.
+ +Note that some sites do not allow embedding and will open a new tab instead. Also note that just like the Web itself, some sites are broken, not suitable for work, trying to harvest your data, or an affront to humanity itself.> + +
EveryTab just shows a random slice of the Web, in all of it's messy and beautiful glory. Enjoy!
+ + + + diff --git a/frontend/site.js b/frontend/site.js index 141231f..1ddc802 100644 --- a/frontend/site.js +++ b/frontend/site.js @@ -63,7 +63,14 @@ function createTab(entry) { tab.classList.add("tab-external"); } - if (entry.icon) { + if (entry._isAbout) { + // About tab gets a rotating icon like the site favicon + const img = document.createElement("img"); + img.className = "tab-icon"; + img.alt = ""; + aboutIcons.push(img); + tab.appendChild(img); + } else if (entry.icon) { const img = document.createElement("img"); img.className = "tab-icon"; img.src = `data:image/png;base64,${entry.icon}`; @@ -82,6 +89,10 @@ function createTab(entry) { // Click handler tab.addEventListener("click", () => { + if (entry._isAbout) { + openInlineViewer(tab, entry, "/about.html"); + return; + } const url = `${entry.protocol || "https"}://${entry.host}`; if (entry.iframe_ok) { openInlineViewer(tab, entry, url); @@ -149,6 +160,18 @@ async function loadMore() { } if (entries.length > 0) { + // Inject the "About Every Tab" tab at a random position in the first load + if (container.children.length === 0) { + const aboutEntry = { + host: "everytab.site/about.html", + title: "About Every Tab", + icon: "", + iframe_ok: true, + _isAbout: true, + }; + const pos = Math.floor(rng() * Math.min(entries.length, tabsPerRow() * 3)); + entries.splice(pos, 0, aboutEntry); + } renderEntries(entries); loadingEl.style.display = "none"; } @@ -161,11 +184,16 @@ faviconLink.type = "image/png"; document.head.appendChild(faviconLink); const loadedIcons = []; +const aboutIcons = []; // img elements for "About" tabs — rotate their icons too setInterval(() => { if (loadedIcons.length === 0) return; const icon = loadedIcons[Math.floor(Math.random() * loadedIcons.length)]; - faviconLink.href = `data:image/png;base64,${icon}`; + const dataUri = `data:image/png;base64,${icon}`; + faviconLink.href = dataUri; + for (const img of aboutIcons) { + img.src = dataUri; + } }, 1000); // Infinite scroll diff --git a/pipeline/06_frontend/deploy.sh b/pipeline/06_frontend/deploy.sh index 58359f8..ba4641c 100755 --- a/pipeline/06_frontend/deploy.sh +++ b/pipeline/06_frontend/deploy.sh @@ -65,6 +65,7 @@ TMPDIR=$(mktemp -d) cp "$FRONTEND_DIR/index.html" "$TMPDIR/index.html" cp "$FRONTEND_DIR/site.js" "$TMPDIR/site.js" cp "$FRONTEND_DIR/bot.html" "$TMPDIR/bot.html" +cp "$FRONTEND_DIR/about.html" "$TMPDIR/about.html" sed -i "s/const TOTAL_BUNDLES = [0-9]*/const TOTAL_BUNDLES = ${TOTAL_BUNDLES}/" "$TMPDIR/index.html" echo "Injected TOTAL_BUNDLES = $TOTAL_BUNDLES" @@ -74,7 +75,8 @@ echo "Uploading to s3://$SITE_BUCKET/..." aws s3 cp "$TMPDIR/index.html" "s3://$SITE_BUCKET/" --content-type "text/html" aws s3 cp "$TMPDIR/site.js" "s3://$SITE_BUCKET/" --content-type "application/javascript" aws s3 cp "$TMPDIR/bot.html" "s3://$SITE_BUCKET/" --content-type "text/html" -echo "Uploaded 3 files" +aws s3 cp "$TMPDIR/about.html" "s3://$SITE_BUCKET/" --content-type "text/html" +echo "Uploaded 4 files" rm -rf "$TMPDIR" @@ -86,7 +88,7 @@ if ! $SKIP_INVALIDATION; then if [ -n "$DIST_ID" ]; then echo "Invalidating CloudFront $DIST_ID..." - aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "/index.html" "/site.js" "/bot.html" > /dev/null + aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "/index.html" "/site.js" "/bot.html" "/about.html" > /dev/null echo "Invalidation submitted" else echo "Warning: no CloudFront distribution found, skipping invalidation"