---
/**
* The federation index. /mints' twin, and deliberately built from the same parts.
*
* Same container, same card, same search, same result line, same leave-and-return
* animation. Two differences, both of them because a federation is a different thing
* rather than because this page is:
*
* - There is no "recently seen online" sort. It reads as a claim about uptime, and
* for the federations nothing checks there is no such reading. Ordering a column
* that is null for a third of the rows is not a sort, it is a shuffle.
* - The count line names the announced ones separately, because "12 federations, 6
* online" invites the reader to assume the other 6 are down.
*/
import Base from '../../layouts/Base.astro';
import MintCard from '../../components/MintCard.astro';
import ReviewByUrl from '../../components/ReviewByUrl.astro';
import { fetchFedimints } from '../../lib/api';
import { localePath, useI18n, type Locale } from '../../i18n';
import { itemListNode } from '../../lib/schema';
import { isIndexableMint } from '../../lib/seo';
import { localePaths } from '../../i18n/paths';
/** One page per locale: `/fedimints`, `/es/fedimints`, `/nl/fedimints`. */
export const getStaticPaths = localePaths;
interface Props {
locale: Locale;
}
const { locale } = Astro.props;
const t = useI18n(locale);
const federations = await fetchFedimints();
/*
* No capability fetch, unlike /mints.
*
* That page asks the API for each mint's detail to read NUT-04 and NUT-05 and draw a
* "melt only" chip. A federation publishes no such switches, so there is nothing to
* fetch and no chip to draw — and inventing one from its module list would be exactly
* the fake capability warning this whole feature refuses to ship.
*/
const online = federations.filter((f) => f.status === 'online').length;
const announced = federations.filter((f) => f.status === 'announced').length;
const description = t('fedimints.description', {
total: federations.length,
online,
announced,
});
const canonical = new URL(localePath('/fedimints', locale), Astro.site).href;
const schema = [
itemListNode({
canonical,
fragment: 'fedimints',
name: t('fedimints.heading'),
items: federations.filter(isIndexableMint).map((federation) => ({
name: federation.name ?? federation.host,
url: new URL(localePath(`/fedimint/${federation.host}`, locale), Astro.site).href,
})),
}),
];
---
{t('fedimints.lede')}
{t('fedimints.showing', { total: federations.length, online, announced })}
{/* What "announced" means, said once at the top of the list rather than on every card that carries it. The status is unusual enough that a reader meeting it for the first time deserves the sentence. */} { announced > 0 && ({t('fedimints.announcedNote', { n: announced })}
) }{t('fedimints.noResults')}
{ federations.length === 0 && ({t('fedimints.emptyIndex')}
) }