diff --git a/README.md b/README.md index 5a889a9..6a432b4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ As of now, some of the cool things Slacker News has include: - Dynamic OpenGraph Metadata - Light/dark mode - Slack channel/user tagging -- Privacy-concious analytics (abacus) +- Privacy-concious [analytics](https://plausible.io/news.hackclub.com) w/ Plausible ## Technical Contributions diff --git a/src/components/AbacusCounter.astro b/src/components/AbacusCounter.astro deleted file mode 100644 index 1a1a5c0..0000000 --- a/src/components/AbacusCounter.astro +++ /dev/null @@ -1,27 +0,0 @@ ---- -import { generateAbacusKey, getAbacusHitUrl } from "../lib/abacus"; - -interface Props { - pathname: string; -} - -const { pathname } = Astro.props; -const abacusKey = generateAbacusKey(pathname); -const abacusUrl = getAbacusHitUrl(abacusKey); ---- - - diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index e6a50f3..37de578 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,6 +1,4 @@ --- -import AbacusCounter from "../components/AbacusCounter.astro"; - interface Props { title?: string; description?: string; @@ -165,7 +163,7 @@ const socialImageAlt = openGraphImageAlt ?? `${siteTitle} social preview`; | RSS | - Stats + Stats | @@ -178,6 +176,5 @@ const socialImageAlt = openGraphImageAlt ?? `${siteTitle} social preview`; - diff --git a/src/lib/abacus.ts b/src/lib/abacus.ts deleted file mode 100644 index bc4784a..0000000 --- a/src/lib/abacus.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Generate an Abacus counter key based on the page pathname - * Examples: - * "/" → "page_index" - * "/about" → "page_about" - * "/news/article-name" → "news_article-name" - * "/opinion/better-goodbyes" → "opinion_better-goodbyes" - */ -export function generateAbacusKey(pathname: string): string { - // Remove leading/trailing slashes - const cleanPath = pathname.replace(/^\/+|\/+$/g, ""); - - if (!cleanPath) { - return "page_index"; - } - - const normalizedSegments = cleanPath - .split("/") - .map((segment) => { - try { - return decodeURIComponent(segment); - } catch { - return segment; - } - }) - .map((segment) => segment.toLowerCase().replace(/[^a-z0-9_.-]/g, "-").replace(/-+/g, "-")) - .map((segment) => segment.replace(/^-+|-+$/g, "")) - .filter(Boolean); - - if (normalizedSegments.length === 0) { - return "page_index"; - } - - if (normalizedSegments.length === 1) { - // Single-level page like "/about" → "page_about" - return `page_${normalizedSegments[0]}`.slice(0, 64); - } - - // Multi-level like "/news/article-name" → "news_article-name" - return normalizedSegments.join("_").slice(0, 64); -} - -/** - * Get the Abacus API URL for hitting a counter - */ -export function getAbacusHitUrl(key: string, namespace: string = "news.hackclub.com"): string { - return `https://abacus.jasoncameron.dev/hit/${namespace}/${key}`; -} - -/** - * Get the Abacus API URL for retrieving counter value - */ -export function getAbacusGetUrl(key: string, namespace: string = "news.hackclub.com"): string { - return `https://abacus.jasoncameron.dev/get/${namespace}/${key}`; -} diff --git a/src/pages/stats.astro b/src/pages/stats.astro deleted file mode 100644 index 0eb3a38..0000000 --- a/src/pages/stats.astro +++ /dev/null @@ -1,418 +0,0 @@ ---- -import BaseLayout from "../layouts/BaseLayout.astro"; -import { generateAbacusKey, getAbacusGetUrl } from "../lib/abacus"; -import { getChangelogEntries, getPosts, getSiteConfig, type ChangelogEntry } from "../lib/content"; - -const site = await getSiteConfig(); -const posts = await getPosts(); - -type CounterRow = { - key: string; - path: string; - label: string; - kind: "page" | "article" | "changelog"; - url: string; -}; - -const staticPaths = ["/", "/about/", "/submissions/", "/acknowledgements/", "/changelogs/", "/news/", "/opinion/", "/essays/", "/stats/"]; - -const pageRows: CounterRow[] = staticPaths.map((path) => { - const key = generateAbacusKey(path); - return { - key, - path, - label: path === "/" ? "Homepage" : `Page: ${path.replace(/^\//, "").replace(/\/$/, "")}`, - kind: "page", - url: getAbacusGetUrl(key) - }; -}); - -const articleRows: CounterRow[] = posts.map((post) => { - const key = generateAbacusKey(post.url); - return { - key, - path: post.url, - label: `Article: ${post.title}`, - kind: "article", - url: getAbacusGetUrl(key) - }; -}); - -const changelogRows: CounterRow[] = (await getChangelogEntries()) - .filter((entry): entry is Extract => entry.kind === "long") - .map((entry) => { - const key = generateAbacusKey(entry.url); - return { - key, - path: entry.url, - label: `Changelog: ${entry.title}`, - kind: "changelog", - url: getAbacusGetUrl(key) - }; - }); - -const rowsByKey = new Map(); -for (const row of [...pageRows, ...articleRows, ...changelogRows]) { - if (!rowsByKey.has(row.key)) { - rowsByKey.set(row.key, row); - } -} - -const counterRows = Array.from(rowsByKey.values()); ---- - - -
-

Pageview Stats

-

Live totals for all tracked pages, articles, and longform changelogs.

- -
-
-

All Views

-
- - - - - - - - - -
ViewsPathTitle
-
-
- -
-

Pages

-
- - - - - - - - - -
ViewsPathTitle
-
-
- -
-

News

-
- - - - - - - - - -
ViewsPathTitle
-
-
- -
-

Essays

-
- - - - - - - - - -
ViewsPathTitle
-
-
- -
-

Changelogs

-
- - - - - - - - - -
ViewsPathTitle
-
-
-
- - -
- - -
- - \ No newline at end of file