diff --git a/src/components/Home.astro b/src/components/Home.astro
index bf48b5f..dcf3a91 100644
--- a/src/components/Home.astro
+++ b/src/components/Home.astro
@@ -5,7 +5,7 @@
*/
import { libraries as allLibraries } from '../content'
import { AREA_TEXT, AREAS, repositoryUrl } from '../content/catalog'
-import { MAIN_ID, SITE, TEXT } from '../content/site'
+import { MAIN_ID, releaseDate, SITE, TEXT } from '../content/site'
import BaseLayout from '../layouts/BaseLayout.astro'
import Icon from './Icon.astro'
import HeroCompose from './HeroCompose.astro'
@@ -103,9 +103,9 @@ const origin = Astro.site ?? Astro.url.origin
{library.data.description}
diff --git a/src/components/LibraryPage.astro b/src/components/LibraryPage.astro
index 2c0852f..88eca60 100644
--- a/src/components/LibraryPage.astro
+++ b/src/components/LibraryPage.astro
@@ -6,7 +6,7 @@
import { render } from 'astro:content'
import type { Library } from '../content'
import { AREA_TEXT, packagistUrl, repositoryUrl } from '../content/catalog'
-import { MAIN_ID, TEXT } from '../content/site'
+import { MAIN_ID, releaseDate, TEXT } from '../content/site'
import BaseLayout from '../layouts/BaseLayout.astro'
import Icon from './Icon.astro'
@@ -21,8 +21,7 @@ const packageName = `tiny-blocks/${data.name}`
const install = `composer require ${packageName}`
const origin = Astro.site ?? Astro.url.origin
const url = new URL(`/${data.name}/`, origin).href
-const released = new Intl.DateTimeFormat('en', { dateStyle: 'medium', timeZone: 'UTC' }).format(new Date(data.released))
-const downloads = new Intl.NumberFormat('en').format(data.downloads.monthly)
+const released = releaseDate(data.released)
/** Search engines show about 160 characters, so a short summary is completed with what the library is. */
const completed = `${data.description} ${TEXT.library.pitch}`
const description = completed.length <= 165 ? completed : data.description
@@ -91,7 +90,6 @@ const relations = [
{TEXT.library.version} {data.version}, {TEXT.library.released} {released}
{TEXT.library.php} {data.php}
{TEXT.library.license} {data.license}
- {TEXT.library.downloads} {downloads} {TEXT.library.perMonth}
{TEXT.library.source}
diff --git a/src/content.config.ts b/src/content.config.ts
index 40cd0ef..091fea1 100644
--- a/src/content.config.ts
+++ b/src/content.config.ts
@@ -6,7 +6,7 @@ import { z } from 'astro/zod'
import { AREAS, CATALOG } from './content/catalog'
import { dependencyGraph } from './content/graph'
import { documentation } from './content/readme'
-import { composerFile, downloads, latestRelease, readme } from './content/sources'
+import { composerFile, latestRelease, readme } from './content/sources'
const libraries = defineCollection({
loader: {
@@ -15,19 +15,18 @@ const libraries = defineCollection({
const names = new Set(CATALOG.map((entry) => entry.name))
const sources = await Promise.all(
CATALOG.map(async (entry) => {
- const [text, composer, release, stats] = await Promise.all([
+ const [text, composer, release] = await Promise.all([
readme(entry.name),
composerFile(entry.name),
latestRelease(entry.name),
- downloads(entry.name),
])
- return { entry, text, composer, release, stats }
+ return { entry, text, composer, release }
}),
)
const graph = dependencyGraph(new Map(sources.map((source) => [source.entry.name, source.composer])))
store.clear()
- for (const [index, { entry, text, composer, release, stats }] of sources.entries()) {
+ for (const [index, { entry, text, composer, release }] of sources.entries()) {
const node = graph[index]
if (node === undefined) {
throw new Error(`No node of the graph for ${entry.name}.`)
@@ -45,7 +44,6 @@ const libraries = defineCollection({
license: [composer.license ?? 'MIT'].flat().join(', '),
version: release.version,
released: release.time,
- downloads: stats,
dependsOn: node.dependsOn,
usedBy: node.usedBy,
testedWith: node.testedWith,
@@ -69,7 +67,6 @@ const libraries = defineCollection({
license: z.string(),
version: z.string(),
released: z.string(),
- downloads: z.object({ total: z.number(), monthly: z.number() }),
dependsOn: z.array(z.string()),
usedBy: z.array(z.string()),
testedWith: z.array(z.string()),
diff --git a/src/content/site.ts b/src/content/site.ts
index 8ef8f8a..5c9aebe 100644
--- a/src/content/site.ts
+++ b/src/content/site.ts
@@ -53,8 +53,6 @@ export const TEXT = {
released: 'released',
php: 'PHP',
license: 'License',
- downloads: 'Downloads',
- perMonth: 'a month',
source: 'Source',
packagist: 'Packagist',
dependsOn: 'Stands on',
@@ -67,7 +65,6 @@ export const TEXT = {
headline: (title: string) => `${title} for PHP`,
/** What closes the description of a library page when the summary of the library is short. */
pitch: 'A small, framework-agnostic PHP library from Tiny Blocks.',
- usedByCount: (count: number) => (count === 1 ? 'used by 1 library' : `used by ${count} libraries`),
},
search: {
title: 'Search the libraries',
@@ -82,3 +79,8 @@ export const TEXT = {
},
notFound: { title: 'Page not found', lede: 'This address does not exist or has moved.', back: 'Back to home' },
} as const
+
+/** The day a release was published, from its ISO 8601 instant, as the site shows it: Oct 24, 2026. */
+export function releaseDate(instant: string): string {
+ return new Intl.DateTimeFormat('en', { dateStyle: 'medium', timeZone: 'UTC' }).format(new Date(instant))
+}
diff --git a/src/content/sources.ts b/src/content/sources.ts
index 6c3f284..4aa09fa 100644
--- a/src/content/sources.ts
+++ b/src/content/sources.ts
@@ -1,6 +1,6 @@
/**
* What the site reads about each library when it is built: the README and the `composer.json` from
- * its repository, and the latest release and the downloads from Packagist. A failed request fails the
+ * its repository, and the latest release from Packagist. A failed request fails the
* build, so the site never publishes a library with half of its page missing.
*/
import { ORGANIZATION, rawUrl } from './catalog'
@@ -17,11 +17,6 @@ export interface Release {
readonly time: string
}
-export interface Downloads {
- readonly total: number
- readonly monthly: number
-}
-
async function fetchOk(url: string): Promise {
const response = await fetch(url)
if (!response.ok) {
@@ -49,10 +44,3 @@ export async function latestRelease(name: string): Promise {
}
return { version: release.version, time: release.time }
}
-
-export async function downloads(name: string): Promise {
- const body = (await (await fetchOk(`https://packagist.org/packages/${ORGANIZATION}/${name}/stats.json`)).json()) as {
- downloads: Downloads
- }
- return { total: body.downloads.total, monthly: body.downloads.monthly }
-}