- TypeScript 98.8%
- Dockerfile 1.2%
| .forgejo/workflows | ||
| charts/app | ||
| src | ||
| .gitignore | ||
| .prettierignore | ||
| biome.json | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| PLAN.md | ||
| README.md | ||
| tsconfig.json | ||
im-present
Show up when you're needed. im-present is a presence-first volunteering board. Instead of browsing endless listings, you tell the app "I'm present" — available to help locally, right now — and nearby needs come to you. Anyone can post a request for presence (a local need: a food-bank shift, a warming center, a cleanup), and every present volunteer in that area sees it and can pledge to show up. Each request shows live progress toward the number of hands it needs.
The core loop
- Go present. Sign in, flip the presence switch, and tag the area you can reach. The board filters to needs near you.
- Post a need. Anyone signed in can post a request for presence — what's needed, where, when, and how many people.
- Pledge & fill. Present volunteers pledge to a request. When pledges reach the number needed (or the organizer closes it), the request is marked filled.
The board is readable by anyone; posting and pledging require signing in. It ships seeded with a few realistic local requests so you can see the loop working on the first visit.
Stack
- Fastify 5 + TypeScript (Node 22) with TypeBox-typed routes that
auto-generate the OpenAPI 3.1 spec at
/openapi.json(Swagger UI at/openapi). - Postgres for presence, requests, and pledges. The schema is bootstrapped (and demo content seeded) at boot — no separate migration step.
- Forgejo SSO via better-auth, out of the box.
API
| Route | Does |
|---|---|
GET /api/board |
Live board: present count, area list, and request cards. |
GET /api/presence · PUT /api/presence |
Read / set your presence + area. |
POST /api/requests |
Post a request for presence. |
GET /api/requests/:id |
A single request with pledge progress. |
POST /api/requests/:id/pledge · DELETE …/pledge |
Pledge / withdraw. |
POST /api/requests/:id/status |
Organizer marks a request filled / re-opens. |
All write routes require a signed-in session; they return typed JSON errors.
Running locally
npm install
npm run build
DATABASE_URL=postgres://user:pass@localhost:5432/im_present \
BETTER_AUTH_SECRET=dev-secret-0123456789 \
BETTER_AUTH_URL=http://localhost:8080 \
FORGEJO_CLIENT_ID=… FORGEJO_CLIENT_SECRET=… \
npm start
npm run lint, npm run typecheck, and npm run build gate every change in
CI (alongside boot smoke tests).