Casa21 is a community space in São Paulo for learning, hacking, and building on Bitcoin. This repository contains the public Casa21 website, built with Next.js.
Production site:
Repository:
- Next.js 16, App Router
- React 19
- TypeScript
- Tailwind CSS 4
- pnpm
- systemd-based production deployment on the Casa21 VM
Install dependencies:
pnpm installRun the development server:
pnpm devOpen:
http://localhost:3000Build for production:
pnpm buildStart a production server locally:
pnpm startRun linting:
pnpm lintapp/ Next.js App Router routes and layout
app/api/events/ Evento.so events API proxy
app/api/newsletter/ Ghost newsletter subscription endpoint
app/api/deploy/ GitHub webhook deploy endpoint
components/ React UI components
components/layout/ Navbar and Footer
components/sections/ Homepage sections
constants/ Shared constants
data/ Static content and navigation data
hooks/ React hooks
lib/ Shared utilities and service clients
public/ Static assets
types/ Shared TypeScript types
scripts/deploy-main.sh Production deploy scriptCreate a local environment file when needed:
cp .env.example .env.localSupported variables include:
EVENTO_SO_API_KEY=...
EVENTO_SO_USERNAME=casa21
GHOST_URL=...
GHOST_ADMIN_API_KEY=...
GITHUB_WEBHOOK_SECRET=...Notes:
.env.localis intentionally ignored by git.GITHUB_WEBHOOK_SECRETis required only on the production VM for webhook autodeploy.- Ghost variables are used by the newsletter integration.
- Evento.so variables are used by the events integration.
The production VM runs the site through systemd:
casa21.serviceThe service starts Next.js on port 8000:
next start -H 0.0.0.0 -p 8000Useful commands on the VM:
sudo systemctl status casa21.service --no-pager -l
sudo systemctl restart casa21.service
journalctl -u casa21.service -fManual deploy from the VM:
scripts/deploy-main.shThe deploy script:
- Locks with
flockto avoid overlapping deploys. - Fetches
origin/main. - Resets the working tree to
origin/main. - Installs dependencies with
pnpm install --frozen-lockfile. - Builds with
pnpm build. - Restarts
casa21.service. - Writes logs to
/home/exedev/casa21-deploy.log.
Pushes to main can automatically deploy the site through the webhook endpoint:
POST https://casa21.vinteum.org/api/deployGitHub webhook settings:
Payload URL: https://casa21.vinteum.org/api/deploy
Content type: application/json
Events: Just the push event
Secret: same value as GITHUB_WEBHOOK_SECRET on the VM
Active: yesThe deploy endpoint verifies GitHub's X-Hub-Signature-256 HMAC signature. It only deploys when all of these are true:
- event is
push - ref is
refs/heads/main - the branch was not deleted
- the signature matches
GITHUB_WEBHOOK_SECRET
Health check:
curl https://casa21.vinteum.org/api/deployExpected response:
{ "ok": true, "route": "deploy" }Events are fetched from Evento.so via:
app/api/events/route.tsThe route expects EVENTO_SO_API_KEY and optionally EVENTO_SO_USERNAME.
Newsletter subscriptions are handled through Ghost Admin API via:
app/api/newsletter/subscribe/route.tsThe route expects GHOST_URL and GHOST_ADMIN_API_KEY.
Use short, descriptive commits. Before pushing, run:
pnpm buildIf possible, also run:
pnpm lintPush changes to main only when they are ready to deploy.