total sats sent
-
-
-
+
+
+ {showSatsInfo && (
+
+ Numbers are cumulative past payouts and don't reflect
+ current or historical balances. Sats are sent monthly
+ and spent on the work the grant was given for.{' '}
+
+ Learn more →
+
+
+ )}
+
diff --git a/scripts/generate-author-og.mjs b/scripts/generate-author-og.mjs
index a716c4798..cb3664a97 100644
--- a/scripts/generate-author-og.mjs
+++ b/scripts/generate-author-og.mjs
@@ -23,14 +23,7 @@ import {
// (light bg, Inter type, faint network decoration) but with a circular
// avatar on the right replacing the dense network cluster, so the
// person, not the abstract pattern, is the focal point.
-const outputDir = path.join(
- ROOT,
- 'public',
- 'static',
- 'images',
- 'authors',
- 'og'
-)
+const outputDir = path.join(ROOT, 'public', 'static', 'images', 'authors', 'og')
// Authors who don't get a custom OG card and fall back to the default
// brand image. Keep this list in sync with AUTHORS_WITHOUT_OG in
@@ -185,7 +178,10 @@ async function writeAuthorImage(author) {
console.warn(`Missing avatar for ${author.slug}: ${author.avatar}`)
}
const svg = renderAuthorSvg(author, avatarDataUri)
- await writePng(path.join(outputDir, `${author.slug}.png`), renderSvgToPng(svg))
+ await writePng(
+ path.join(outputDir, `${author.slug}.png`),
+ renderSvgToPng(svg)
+ )
}
async function main() {
diff --git a/scripts/generate-default-og.mjs b/scripts/generate-default-og.mjs
index 7e635858c..ac2635ba1 100644
--- a/scripts/generate-default-og.mjs
+++ b/scripts/generate-default-og.mjs
@@ -71,9 +71,7 @@ function renderDefaultSvg(wordmarkDataUri, logoDataUri) {
const linesCount = HEADLINE_LINES.length
const headlineBaselineLift = 24
const headlineStartY =
- logoBottomY -
- headlineBaselineLift -
- (linesCount - 1) * headlineLineHeight
+ logoBottomY - headlineBaselineLift - (linesCount - 1) * headlineLineHeight
const wordmarkX = PADDING
const wordmarkY = 64
@@ -114,9 +112,7 @@ function renderDefaultSvg(wordmarkDataUri, logoDataUri) {
}" font-size="22" font-family="${INTER_FONT_FAMILY}" letter-spacing="1">
${escapeXml(FOOTER_LABEL)}
-
${escapeXml(FOOTER_URL)}
diff --git a/scripts/generate-donate-banner.mjs b/scripts/generate-donate-banner.mjs
index 4f59dc058..700a270a3 100644
--- a/scripts/generate-donate-banner.mjs
+++ b/scripts/generate-donate-banner.mjs
@@ -13,13 +13,7 @@ const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const root = path.resolve(__dirname, '..')
-const OUTPUT_DIR = path.join(
- root,
- 'public',
- 'static',
- 'images',
- 'newsletter'
-)
+const OUTPUT_DIR = path.join(root, 'public', 'static', 'images', 'newsletter')
// Load static-weight Inter faces so resvg's font-weight matching maps
// reliably (its variable-font wght axis support is best-effort). The
// embedded family name on these files is "Inter 18pt", referenced in
@@ -108,11 +102,11 @@ function renderSvg(variant) {
const leftLineGap = 8
const leftStackHeight = preludeSize + leftLineGap + ctaSize
const leftPreludeBaselineY = (HEIGHT - leftStackHeight) / 2 + preludeSize
- const leftCtaBaselineY =
- leftPreludeBaselineY + leftLineGap + ctaSize * 0.95
+ const leftCtaBaselineY = leftPreludeBaselineY + leftLineGap + ctaSize * 0.95
const rightStackHeight = preTaglineSize + leftLineGap + taglineSize
- const rightPreTaglineBaselineY = (HEIGHT - rightStackHeight) / 2 + preTaglineSize
+ const rightPreTaglineBaselineY =
+ (HEIGHT - rightStackHeight) / 2 + preTaglineSize
const rightTaglineBaselineY =
rightPreTaglineBaselineY + leftLineGap + taglineSize * 0.95
diff --git a/scripts/generate-grantee-map.mjs b/scripts/generate-grantee-map.mjs
index 05f2cdc1c..4c211f305 100644
--- a/scripts/generate-grantee-map.mjs
+++ b/scripts/generate-grantee-map.mjs
@@ -16,13 +16,7 @@ const __dirname = path.dirname(__filename)
const root = path.resolve(__dirname, '..')
const SOURCE_SVG = path.join(root, 'public', 'maps', 'world.svg')
-const OUTPUT_DIR = path.join(
- root,
- 'public',
- 'static',
- 'images',
- 'newsletter'
-)
+const OUTPUT_DIR = path.join(root, 'public', 'static', 'images', 'newsletter')
const WIDTH = 2400 // render width in pixels
@@ -30,10 +24,46 @@ const HIGHLIGHT_COLOR = '#f97316' // tailwind orange-500
// Keep this in sync with components/GranteeMap.tsx
const GRANTEE_COUNTRY_CODES = [
- 'US', 'CA', 'DE', 'GB', 'IT', 'JP', 'NL', 'CH', 'CN', 'BR',
- 'AR', 'IE', 'HK', 'GE', 'SE', 'ES', 'PT', 'NO', 'GR', 'AU',
- 'IN', 'SI', 'KR', 'FI', 'CZ', 'UG', 'BE', 'FR', 'VN', 'UA',
- 'TR', 'SV', 'NZ', 'HU', 'SK', 'NG', 'PA', 'RO', 'GT', 'ID',
+ 'US',
+ 'CA',
+ 'DE',
+ 'GB',
+ 'IT',
+ 'JP',
+ 'NL',
+ 'CH',
+ 'CN',
+ 'BR',
+ 'AR',
+ 'IE',
+ 'HK',
+ 'GE',
+ 'SE',
+ 'ES',
+ 'PT',
+ 'NO',
+ 'GR',
+ 'AU',
+ 'IN',
+ 'SI',
+ 'KR',
+ 'FI',
+ 'CZ',
+ 'UG',
+ 'BE',
+ 'FR',
+ 'VN',
+ 'UA',
+ 'TR',
+ 'SV',
+ 'NZ',
+ 'HU',
+ 'SK',
+ 'NG',
+ 'PA',
+ 'RO',
+ 'GT',
+ 'ID',
'AE',
]
@@ -65,9 +95,7 @@ function buildStyledSvg(rawSvg, variant) {
// Strip the inline width/height — viewBox alone gives resvg the aspect
// ratio it needs and fitTo controls the output resolution.
- svg = svg
- .replace(/\s+width="[^"]+"/, '')
- .replace(/\s+height="[^"]+"/, '')
+ svg = svg.replace(/\s+width="[^"]+"/, '').replace(/\s+height="[^"]+"/, '')
// Make sure a viewBox exists; fall back to the original width/height
// if mapsvg's source somehow ships without one.
@@ -81,9 +109,9 @@ function buildStyledSvg(rawSvg, variant) {
}
}
- const highlightSelector = GRANTEE_COUNTRY_CODES
- .map((code) => `#${escapeForCss(code)}`)
- .join(', ')
+ const highlightSelector = GRANTEE_COUNTRY_CODES.map(
+ (code) => `#${escapeForCss(code)}`
+ ).join(', ')
// Inject a stylesheet right after the opening