Official website for the 256 Foundation, a 501(c)(3) nonprofit building the open-source Bitcoin mining ecosystem. Built with Next.js 15 and Tailwind CSS v4.
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- Deployment — Vercel · Proxmox (LXC + Nginx + PM2) · Coolify · Netlify · Railway
- Site Architecture — Pages & Navigation
- External Integrations & Links
- Design System
- Data Layer
- API Routes
- Content Updates
| Layer | Technology | Version |
|---|---|---|
| Framework | Next.js (App Router) | ^15.x |
| UI Library | React | ^19.x |
| Language | TypeScript | ^5.x |
| Styling | Tailwind CSS v4 | ^4.x |
| XML Parsing | fast-xml-parser (Substack feed) | ^5.x |
| MDX Rendering | next-mdx-remote (Newsroom posts) | ^6.x |
| Frontmatter Parsing | gray-matter (Newsroom posts) | ^4.x |
| Analytics | Umami (self-hosted, optional) | — |
There are no other runtime dependencies — no CSS-in-JS, UI kit, state manager, ORM, or 3D library. The full dependency list is in package.json.
Key architectural decisions:
- App Router — all pages use Next.js 15 App Router with server components by default
- Tailwind CSS v4 — CSS-first config via
@themeand@custom-variantinglobals.css(notailwind.config.js) - Dark mode — driven by
@media (prefers-color-scheme: dark)OS preference, not a toggle; Tailwinddark:prefix maps to this media query - ISR — the home page (
/) and the Open Mining Stack page (/projects) useexport const revalidate = 3600for hourly ISR so live GitHub, forum, and Substack data stays fresh without blocking builds - Static-first — every other page is statically generated at build time (
/newsroomand/newsroom/[slug]are explicitlyforce-static); only the/api/hashdashproxy is server-rendered on demand (force-dynamic)
website-256F/
├── app/ # Next.js App Router pages
│ ├── layout.tsx # Root layout — wraps all pages with Header + Footer
│ ├── page.tsx # Home page (/)
│ ├── globals.css # Global styles, Tailwind theme, font vars, dark mode
│ ├── robots.ts # Auto-generated robots.txt
│ ├── sitemap.ts # Auto-generated sitemap.xml
│ ├── mission/page.tsx # /mission
│ ├── donate/page.tsx # /donate
│ ├── grants/page.tsx # /grants
│ ├── grants/announcements/page.tsx # /grants/announcements — funding log archive
│ ├── faq/page.tsx # /faq
│ ├── telehash/page.tsx # /telehash
│ ├── newsroom/
│ │ ├── page.tsx # /newsroom — post list (force-static)
│ │ └── [slug]/page.tsx # /newsroom/[slug] — MDX post detail (generateStaticParams)
│ ├── projects/
│ │ └── page.tsx # /projects — "Open Mining Stack" (ISR); retired /projects/[slug] 308-redirect to project sites
│ └── api/
│ └── hashdash/route.ts # Prometheus proxy for live hashrate leaderboard (only API route)
│
├── components/
│ ├── ui/ # Reusable primitive components
│ │ ├── Button.tsx
│ │ ├── Card.tsx
│ │ ├── Badge.tsx
│ │ ├── Logo.tsx
│ │ ├── SectionWrapper.tsx
│ │ ├── SectionHeader.tsx
│ │ ├── DecorativeBg.tsx
│ │ ├── PCBBackground.tsx
│ │ └── ExternalLink.tsx
│ ├── layout/ # Header, Footer, Navigation
│ │ ├── Header.tsx
│ │ ├── Footer.tsx
│ │ ├── MobileNav.tsx
│ │ └── NavDropdown.tsx
│ ├── home/ # Home page section components
│ │ ├── HeroSection.tsx
│ │ ├── DonateCards.tsx
│ │ ├── WhySection.tsx
│ │ ├── AllocationStats.tsx
│ │ ├── BlocksFound.tsx
│ │ ├── StayUpdated.tsx # Forum topics + GitHub activity strips
│ │ ├── ProjectsSection.tsx # Live GitHub org activity feed
│ │ ├── ApplySection.tsx
│ │ ├── CommunitySection.tsx
│ │ ├── EcosystemSection.tsx
│ │ ├── FAQSection.tsx # Curated 4-question accordion from data/faq.ts
│ │ ├── SupporterShowcase.tsx
│ │ ├── HashrateLeaderboard.tsx # Live Prometheus hashrate data
│ │ └── ContactForm.tsx # Formspree-powered contact form
│ ├── newsroom/ # Newsroom components
│ │ ├── PostCard.tsx # Card for post list (cover image, category, date, title, excerpt)
│ │ ├── NewsroomIndex.tsx # Client-side category filter + post grid
│ │ └── PostBody.tsx # MDXRemote wrapper — renders MDX content with .newsroom-body styles
│ ├── grants/ # Grants funding-log components
│ │ ├── FundingAnnouncements.tsx # Log section: cards, empty state, "View all →"
│ │ └── GrantAnnouncementCard.tsx # One log entry (date, project, program chip, term, line)
│ ├── projects/ # Project detail components
│ │ ├── PillarProjectCard.tsx # Card with live GitHub stars/forks/issues
│ │ ├── MilestoneTracker.tsx
│ │ ├── GrantLogTable.tsx
│ │ ├── HardwareProjectViewer.tsx
│ │ ├── EcosystemCard.tsx
│ │ ├── ProjectForumSection.tsx # Per-project Discourse category topics
│ │ └── GitHubActivitySection.tsx # Per-project GitHub repo activity feed
│ ├── shared/ # Cross-page shared components
│ │ ├── TeamMemberCard.tsx
│ │ ├── Timeline.tsx
│ │ ├── NewsletterSignup.tsx
│ │ └── SubstackEmbed.tsx
│ └── telehash/ # TeleHash-specific components
│ ├── CountdownTimer.tsx
│ ├── TeleHashEventCard.tsx
│ └── PhotoCarousel.tsx # Client-side photo carousel for event photos
│
├── data/ # Static data — edit these to update site content
│ ├── navigation.ts # All nav links (top nav + footer)
│ ├── projects.ts # Pillar project definitions (Ember One, Mujina, etc.)
│ ├── grants.ts # Grant recipient log
│ ├── supporters.ts # Donor tiers
│ ├── team.ts # Team member profiles
│ ├── stats.ts # Foundation statistics (BTC raised, blocks found)
│ ├── telehash.ts # TeleHash event history, next event, photos
│ └── faq.ts # FAQ entries by category
│
├── content/
│ └── newsroom/ # MDX posts for the Newsroom — one file per article ([slug].mdx)
│
├── lib/
│ ├── metadata.ts # SEO metadata generation helper
│ ├── newsroom.ts # Newsroom helpers — getAllPosts, getPostBySlug, getLatestPost, formatPostDate; re-exports newsroomMeta
│ ├── newsroomMeta.ts # Client-safe: category vocabulary/labels, formatPostDate (no fs)
│ ├── substack.ts # Substack RSS fetch + parse
│ ├── discourse.ts # Discourse forum API — latest topics + per-category topics
│ └── github.ts # GitHub REST API — repo meta, org repos, org events
│
├── types/
│ └── index.ts # All TypeScript interfaces
│
├── public/
│ ├── logos/ # 256-logo-{horizontal,secondary,vertical}-{dark,light}.png (dark=for light bg)
│ ├── projects/ # Project images
│ ├── team/ # Team headshots
│ ├── supporters/ # Supporter tier logos (tier1/, tier2/, tier3/)
│ ├── ecosystem/ # Ecosystem partner logos
│ ├── newsroom/ # Newsroom article images, organized by post slug
│ ├── telehash/ # TeleHash event photos (th3-*.jpg, etc.)
│ └── og/ # Open Graph images
│
├── content/newsroom/*.mdx # Newsroom articles (one .mdx per post)
├── tests/ # Node built-in test runner (`node --test`)
└── next.config.ts # Next.js config (image domains, package-import optimization)
See
CLAUDE.mdfor a condensed orientation guide (conventions, gotchas, and where things live) aimed at AI coding assistants and new contributors.
- Node.js 20 LTS or newer (the app uses
AbortSignal.timeout; built and verified on Node 20) - npm
git clone https://github.com/256foundation/website.git
cd website
npm installnpm run dev
# → http://localhost:3000npm run build # compile for production
npm start # run production server
npm run lint # run ESLint (next lint)
npm test # run the Node test suite (node --test tests/)Create a .env.local file in the project root:
# ─── Public (exposed to browser) ─────────────────────────────────────────────
NEXT_PUBLIC_SITE_URL=https://256foundation.org
# Zaprite donation link (used on /donate page and home donate cards)
NEXT_PUBLIC_ZAPRITE_URL=https://pay.zaprite.com/pl_...
# Typeform grant application URL — unused; the URL is hardcoded in app/grants/page.tsx
# (the General Grant "Apply for a Grant" button links straight to it)
# NEXT_PUBLIC_TYPEFORM_URL=https://form.typeform.com/to/oqyJAntF
# Umami analytics (optional — only injected in production)
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
NEXT_PUBLIC_UMAMI_URL=
# ─── Private (server-only) ────────────────────────────────────────────────────
# GitHub personal access token (optional — increases API rate limit from 60 to 5000 req/hr)
# Without this, GitHub data still loads but may hit rate limits under heavy traffic
GITHUB_TOKEN=ghp_...Note: The site builds and runs without any env vars — all pages fall back gracefully. Donation and grant form buttons link to
#without their respective env vars. GitHub and forum data are fetched unauthenticated and cached via ISR.
The contact form now posts directly to Formspree from the client (components/home/ContactForm.tsx) — no server-side email API is needed. The Resend integration and /api/contact route have been removed.
The Hashdash leaderboard now calls the Prometheus API at pool.256foundation.org/api/v1/query directly from the /api/hashdash server route — no external API key required.
Three hosting paths are documented below: Vercel (easiest), self-hosted Proxmox (full control), and other platform hosts (Coolify, Netlify, Railway).
No config file needed. Vercel detects Next.js automatically.
- Push repo to GitHub
- Import the repo at vercel.com/new
- Add environment variables under Project → Settings → Environment Variables (see Environment Variables)
- Deploy — every push to
maintriggers a production deploy; PRs get preview URLs automatically
Custom domain: add it under Project → Settings → Domains. Vercel provisions an SSL certificate automatically.
Run the site on your own Proxmox server using a lightweight LXC container and Nginx as a reverse proxy.
In the Proxmox web UI or shell:
# Download Ubuntu 22.04 template if not already present
pveam download local ubuntu-22.04-standard_22.04-1_amd64.tar.zst
# Create the container (adjust storage, cores, memory as needed)
pct create 200 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
--hostname website-256f \
--cores 2 \
--memory 1024 \
--swap 512 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--storage local-lvm \
--rootfs local-lvm:8 \
--unprivileged 1 \
--start 1SSH into the container:
pct enter 200apt update && apt upgrade -y
apt install -y curl git build-essential
# Install Node.js 20 LTS via NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
# Install PM2 globally (process manager — keeps the app alive and restarts on crash)
npm install -g pm2Verify:
node -v # should be v20.x
npm -v
pm2 -v# Create a dedicated user (optional but recommended)
useradd -m -s /bin/bash website
su - website
# Clone the repo
git clone https://github.com/256foundation/website.git
cd website
# Install dependencies
npm install
# Create the env file
cp .env.example .env.local
nano .env.local # fill in your values (see Environment Variables section)
# Build for production
npm run build# Start the Next.js production server on port 3000
pm2 start npm --name "website-256f" -- start
# Save the process list so it survives reboots
pm2 save
# Set PM2 to start on system boot
pm2 startup
# → copy and run the command PM2 printsCheck it's running:
pm2 status
pm2 logs website-256fThe site is now running at http://<container-ip>:3000. Next, put Nginx in front of it.
apt install -y nginxCreate the site config:
nano /etc/nginx/sites-available/256foundationPaste:
server {
listen 80;
server_name 256foundation.org www.256foundation.org;
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# Proxy to Next.js
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Cache Next.js static assets aggressively
location /_next/static/ {
proxy_pass http://127.0.0.1:3000;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location /public/ {
proxy_pass http://127.0.0.1:3000;
add_header Cache-Control "public, max-age=86400";
}
}Enable the site and reload:
ln -s /etc/nginx/sites-available/256foundation /etc/nginx/sites-enabled/
nginx -t # verify config is valid
systemctl reload nginxapt install -y certbot python3-certbot-nginx
certbot --nginx -d 256foundation.org -d www.256foundation.orgCertbot edits your Nginx config to redirect HTTP → HTTPS and auto-renews the certificate.
To pull new changes and rebuild:
cd ~/website-256F
git pull origin main
npm install # only needed if package.json changed
npm run build
pm2 restart website-256fOptionally script this as a deploy hook or cron job.
- Assign the container a static IP in
pct set 200 --net0 name=eth0,bridge=vmbr0,ip=192.168.1.x/24,gw=192.168.1.1 - Point your domain's A record to your Proxmox host's public IP
- Forward ports 80 and 443 from your router/firewall to the container IP
- If you run multiple containers, put Nginx Proxy Manager in its own LXC and use it to route by hostname — it has a GUI for managing SSL certs across containers
Coolify is an open-source Heroku alternative you can run inside its own Proxmox LXC. It handles builds, deployments, SSL, and environment variables through a web UI — no manual Nginx config.
# Install Coolify on a fresh Ubuntu server / LXC
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bashOnce running at http://<server-ip>:8000:
- Add your GitHub repo as a New Resource → Application
- Select Nixpacks (auto-detects Next.js) or Dockerfile if you add one
- Set environment variables in the Coolify UI
- Assign a domain — Coolify provisions SSL via Let's Encrypt automatically
- Push to
main→ Coolify auto-deploys via webhook
- Connect your GitHub repo at app.netlify.com
- Build command:
npm run build - Publish directory:
.next - Install the Netlify Next.js Runtime plugin (added automatically when it detects Next.js)
- Add environment variables under Site Settings → Environment Variables
Note: Netlify supports Next.js App Router and ISR but may lag behind the latest Next.js releases. Verify your Next.js version is in their supported versions list.
- New project → Deploy from GitHub repo
- Railway auto-detects Next.js — no config needed
- Add environment variables in the Railway dashboard
- Set a custom domain under Settings → Networking
Configured in next.config.ts under images.remotePatterns for next/image optimization. Required on all hosting platforms:
| Domain | Used For |
|---|---|
i.ytimg.com |
YouTube video thumbnails |
img.youtube.com |
YouTube video thumbnails |
substackcdn.com |
Substack post thumbnails |
substack-post-media.s3.amazonaws.com |
Substack post images |
bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com |
Substack-hosted media |
next/image also negotiates image/avif → image/webp → original for all optimized images.
| Route | Page | Description |
|---|---|---|
/ |
Home | Hero, donate CTAs, why section, stats, blocks found, forum + GitHub activity, FAQ, supporters, contact form |
/mission |
Mission | Mission statement, photo-framed narrative, principles, founders + board |
/projects |
Open Mining Stack | Four stack layers (hash board → control board → firmware → pool) with live activity badges; retired /projects/[slug] 308-redirect to project sites |
/grants |
Grants | Two programs — Core Projects Program / General Grant Program (#grant-programs); funding announcements log (#funding-announcements) |
/grants/announcements |
Funding Archive | Every grant-announcement newsroom post, newest first |
/donate |
Donate | BTC/Lightning/card + hashrate donation with participation steps |
/telehash |
TeleHash | Countdown, participation guide, event history with photo carousels |
/faq |
FAQ | Categorized Q&A accordion (sourced from old site + expanded) |
/newsroom |
Newsroom | List of org-authored MDX posts (perspective, foundation news, project updates, highlights, grant announcements) |
/newsroom/[slug] |
Post Detail | Full article rendered from MDX with cover image and article body |
Logo (→ /) Mission Mining Stack Grants Newsroom Ecosystem ▾ Community ▾ [GitHub] [Forum] [Donate]
Mining Stack → /projects (single "Open Mining Stack" page; layers jump to /projects#ember-one, #libre-board, #mujina, #hydrapool)
Ecosystem dropdown:
• Bitaxe → https://bitaxe.org (external)
• OSMU → https://osmu.wiki (external)
• Hashrate Heatpunks → https://heatpunks.org (external)
• Jua Kali → https://github.com/GridlessCompute/Jua-Kali-Miner (external)
• ASIC-rs → https://docs.rs/asic-rs/latest/asic_rs/index.html (external)
• HashScope → https://github.com/256foundation/HashScope (external)
Community dropdown:
• Forum → https://forum.256foundation.org (external)
• Group Chat → https://t.me/the256foundation (external)
• Newsletter → https://256foundation.substack.com (external)
• POD256 → https://www.pod256.org (external)
• X / Twitter → https://x.com/256FOUNDATION (external)
• Nostr → https://primal.net/p/nprofile1... (external)
• Hashdash → https://dash.256f.org (external)
• Telehash → /telehash
| Breakpoint | Nav |
|---|---|
| < 1024px (mobile/tablet) | Hamburger → full-screen MobileNav overlay |
| ≥ 1024px (desktop) | Full horizontal nav with dropdown menus |
| Service | URL | Used In |
|---|---|---|
| Zaprite | NEXT_PUBLIC_ZAPRITE_URL (env var) |
/donate, home donate cards |
| Formspree | https://formspree.io/f/xkndjepy |
Contact form (client-side POST) |
| Service | URL | Used In |
|---|---|---|
| Hydrapool (mining pool) | stratum+tcp://pool.256foundation.org:3333 |
/donate, /telehash |
| Hashdash (pool dashboard) | https://dash.256f.org |
Footer, donate, nav |
| Prometheus API | https://pool.256foundation.org/api/v1/query |
/api/hashdash — live hashrate leaderboard |
| Endpoint | Used In |
|---|---|
https://forum.256foundation.org/latest.json |
Home page live forum activity strip |
https://forum.256foundation.org/c/ember-one/5.json |
Ember One project page forum section |
https://forum.256foundation.org/c/mujina/7.json |
Mujina project page forum section |
https://forum.256foundation.org/c/fibre-board/6.json |
Libre Board project page forum section |
https://forum.256foundation.org/c/hydrapool/8.json |
Hydrapool project page forum section |
Note: Libre Board's Discourse category uses the slug
fibre-board(legacy typo) notlibre-board.
| Endpoint | Used In |
|---|---|
https://api.github.com/repos/256foundation/{repo} |
Live stars/forks/issues on project cards |
https://api.github.com/orgs/256foundation |
Org stats (repo count, followers) for /projects CTA |
https://api.github.com/orgs/256foundation/repos |
Total star count aggregated for /projects CTA |
https://api.github.com/orgs/256foundation/events |
GitHub activity strip on home page |
https://api.github.com/repos/{owner}/{repo}/events |
Per-project GitHub activity on project pages |
GitHub API is called unauthenticated by default (60 req/hr limit). Set GITHUB_TOKEN in env to raise the limit to 5,000 req/hr.
| Platform | URL |
|---|---|
| X / Twitter | https://x.com/256FOUNDATION |
| GitHub (org) | https://github.com/256foundation |
| Telegram | https://t.me/the256foundation |
| Nostr | https://primal.net/p/nprofile1qqsqhk42dz0exfcsln4yqmdkjys0nvd7dqndgacpsa7w7pt7njq2uuss2u9cq |
| Forum | https://forum.256foundation.org |
| Events Calendar | https://forum.256foundation.org/upcoming-events/ |
| Newsletter (Substack) | https://256foundation.substack.com |
| POD256 Podcast | https://www.pod256.org |
| Project | GitHub |
|---|---|
| Ember One | github.com/256foundation/emberone00-pcb |
| Mujina | github.com/256foundation/mujina |
| Libre Board | github.com/256foundation/libre-board |
| Hydrapool | github.com/256foundation/hydrapool |
| ASIC-rs | github.com/256foundation/asic-rs |
| HashScope | github.com/256foundation/HashScope |
| Service | Purpose |
|---|---|
| Substack RSS | Blog post feed (https://256foundation.substack.com/feed) |
| Typeform | Grant application form (env var) |
| Name | Hex | Usage |
|---|---|---|
| Purple Dark | #3b1445 |
Primary accent — buttons, links, hover states, labels, borders (light mode) |
| Purple Mid | #5c2070 |
Border accents in dark mode |
| Purple Light | #c084d8 |
Links, labels, hover states (dark mode) |
| Terminal Green | #00FF41 |
Live status indicators, code block text |
| Code Block BG | #2d0f36 |
Background for stratum/code blocks |
| Role | Value |
|---|---|
| Page background | #1a1a1a |
| Card / elevated surface | #242424 |
| Border | #1f1f1f |
| Primary text | #ffffff |
| Secondary text | text-gray-400 |
| Role | Value |
|---|---|
| Page background | #ffffff |
| Elevated surface | bg-gray-50 |
| Border | border-gray-200 |
| Primary text | text-gray-900 |
| Secondary text | text-gray-600 |
| Font | CSS Class | Role |
|---|---|---|
| Barlow Condensed | font-display |
Headings, uppercase UI text |
| Space Mono | font-mono |
Code, labels, buttons, nav links, tags, stats |
| Inter | font-sans |
Body text (default) |
- No border-radius — all cards, buttons, inputs use
rounded-none - Uppercase headings — all H1 and H2 use
.uppercasewith Barlow Condensed - Purple is the only accent —
#3b1445(light) /#c084d8(dark) for all interactive states - Terminal green = live/success only —
#00FF41for status indicators and code text only - Dark mode is the primary experience — optimize dark first, light is fully supported
- Borders over shadows — depth via
#1f1f1fborders, not box shadows - Arrow symbols — use
→(→) for directional UI, not chevrons
- PCBBackground — SVG circuit board tile pattern, always subtle (opacity 0.05–0.12)
- DecorativeBg — composes PCBBackground + purple radial glow + vignette. Use inside
<SectionWrapper decorative> - Purple radial glow —
radial-gradient(ellipse at {position}, rgba(124,58,237,0.08) 0%, transparent 60%) - Live indicator dot —
w-1.5 h-1.5 rounded-full bg-[#00FF41]withbox-shadow: 0 0 6px #00FF41
All site content lives in data/. Edit these files to update content without touching components.
Foundation statistics shown on the home page: BTC raised, blocks found, active grantees.
The four Open Mining Stack layers (pillarProjects), ordered hash board → control board → firmware → pool. Each carries a tagline, problem statement, key specs/features, core architect, and GitHub/forum URLs. The forumCategoryApiUrl points to the Discourse category JSON used for the live activity badge. Backs /projects.
teleHashEvents[]— event history. Each event can haveblockFound,btcRaised,blockUrl,videoUrl,summary, andphotos[](paths relative to/public).nextEventDate— ISO date string for the countdown timer (nullif unannounced).nextEventDetails— display name, date, time, location, links for the next event.
FAQ entries with question, answer (multi-paragraph answers separated by \n\n), and category.
All nav links for the header dropdowns and footer. Add/remove/reorder without touching layout components.
Supporter logos by tier (1, 2, 3) with name, image path, and link.
MDX files for org-authored articles. Each file is [slug].mdx with frontmatter:
---
title: "Post Title"
date: "2026-05-01" # ISO date — controls sort order and display
author: "256 Foundation"
category: "foundation-news" # perspective | foundation-news | project-update | highlight | grant-announcement
excerpt: "One-sentence summary shown on the list page and in the home page card."
coverImage: "/newsroom/[post-slug]/banner.png" # optional — shown at top of post
ogImage: "/newsroom/[post-slug]/og.png" # optional — used for social share OG image
# grant-announcement only, all optional — feed the /grants funding log:
project: "Libre Board"
program: "core" # core | general
term: "Four months, September to December"
---
Article body in Markdown...Parsed by lib/newsroom.ts at build time. Posts are sorted newest-first. The most recent post is surfaced on the home page in the StayUpdated section.
Posts with category: grant-announcement additionally appear, newest first, in the /grants funding log (#funding-announcements, max 6) and its /grants/announcements archive. Grants received from third parties (HRF, MARA) are foundation-news, not announcements. The log never shows a dollar amount, and its copy avoids "cycle"/"wave"/"round", "pillar", retired program names, and em dashes; tests/grant-announcements.test.mjs enforces this.
/api/hashdash is the only API route (export const dynamic = 'force-dynamic').
| Route | Method | Description |
|---|---|---|
/api/hashdash |
GET | Runs 3 Prometheus queries in parallel against pool.256foundation.org/api/v1/query (top 5 workers by 5-min share rate, total hashrate, active worker count). For npub… identities it resolves Nostr display names + avatars via the Primal API (primal.net/api), with an in-memory 10-min cache. Each upstream call has a 5s AbortSignal.timeout; returns 503 if the pool is unreachable. |
Substack posts are not an API route. The home page server component (
app/page.tsx) callsfetchSubstackPosts()fromlib/substack.tsdirectly at render time (ISR,revalidate: 3600).
The contact form (components/home/ContactForm.tsx) posts directly to Formspree (https://formspree.io/f/xkndjepy) from the browser — no server route needed. Fields: name, _replyto (email), message. (The empty app/api/contact/ directory is a leftover from the removed Resend integration and can be deleted.)
- Create a new MDX file in
content/newsroom/[slug].mdxwith required frontmatter (title, date, author, category, excerpt) - Drop any article images into
public/newsroom/[slug]/and reference them in the MDX body using standard Markdown image syntax: - Optionally set
coverImage(displayed at top of post) andogImage(social share preview) in frontmatter - The post appears automatically on
/newsroom, at/newsroom/[slug], and if it's the newest post it surfaces on the home page in the StayUpdated section — no code changes needed - Redeploy (or wait for ISR) to publish — all newsroom routes are statically generated via
generateStaticParams
Add an entry to teleHashEvents[] in data/telehash.ts. For photos, drop images into public/telehash/ and add the paths to the photos[] array on the event object.
Set nextEventDate to an ISO date string and fill in nextEventDetails in data/telehash.ts.
- Drop the logo into
public/supporters/tier1/(or tier2, tier3) - Add an entry to
data/supporters.ts
- Add headshot to
public/team/ - Add entry to
data/team.ts
Donation link: set NEXT_PUBLIC_ZAPRITE_URL in .env.local or Vercel environment variables. The Typeform grant application URL is hardcoded in app/grants/page.tsx (GENERAL_GRANT_APPLICATION_URL); NEXT_PUBLIC_TYPEFORM_URL is unused.
- Add logo(s) to
public/ecosystem/— for dark/light variants name them<Project>_square_dark.pngand<Project>_square_light.png - Add an entry to the
projectsarray incomponents/home/EcosystemSection.tsx(uselogoDark/logoLightfor dual-logo projects,logofor single-image) - Add an entry to the
ecosystemProjectsarray inapp/projects/page.tsx - Add the link to the Ecosystem children array in
data/navigation.ts
Search for pool.256foundation.org — it appears as static strings in app/donate/page.tsx and app/telehash/page.tsx.
GitHub data is fetched at build time and revalidated every hour via ISR. To change which repos are featured, update githubUrl and forumCategoryApiUrl fields in data/projects.ts. Org repos are auto-discovered from the 256foundation GitHub organization.