Turn thousands of Swiss foundations into a focused, actionable pipeline, then generate a tailored Gesuch for each one in seconds.
Hirnli helps mission-driven organizations find the right foundation funders, build per-foundation fit narratives, and ship professional German-language applications (Gesuche) that stand out from the templated norm. Multi-tenant by design — each organization runs its own branded instance.
Architecture & Conventions · Scripts Reference · Onboarding a New Org
Swiss universe (Zefix) 16,900
↓
In DB (active) 15,506 — minus 1,117 archived
↓ LLM-triaged 13,823 stay rapid/unverified
Generated (sync-eligible) 1,683
↓ scored & researched
Actionable (P1–P3) 240 — P1=20, P2=78, P3=142
↓ assembled
Gesuch pages (P1–P3) 212 — 199 quality-perfect (94%)
| Tier | Count | Coverage |
|---|---|---|
| P1 (perfect fit) | 20 | 20/20 Gesuche perfect · 100% appUrl · 95% email |
| P2 (good fit) | 78 | 70/75 Gesuche perfect · 100% appUrl · 97% email |
| P3 (possible fit) | 142 | 109/117 Gesuche perfect · 96% appUrl · 89% email |
| P4 (network / D-list) | 1,443 | LLM-triaged from Zefix purpose text |
The remaining 13 imperfect Gesuche need verified external research (email or real website) — automated enrichment is forbidden after the 2026-04-07 incident where guessed URLs were 54% wrong. See data-integrity rules in CLAUDE.md.
- INGEST — Zefix register + ESA + Fundraiso + StiftungSchweiz feeds, deduped into one Foundation entity per legal Stiftung. DB-write SSOT, Zod-validated.
- TRIAGE — Groq-hosted LLM scores every active row from raw Zefix text
alone, producing a
fitScore(0–10) +priority(P1–P4). 14,919 rapid-triaged. - RESEARCH — Operator-driven deep research for promising candidates pulls websites, grant ranges, deadlines, past grantees, contact channels.
- PRESENT — Each foundation gets a public-feeling detail page that doubles as a relationship tool: fit analysis, trust badge, sources, recherche links.
- GENERATE — Per-foundation × per-Schwerpunkt × per-template Gesuch composer produces: 4-page Gesuch PDF, one-pager concept note, shareable HMAC landing page, pitch deck (8-slide A4 landscape), and 2-page impact report — all from one Foundation entry + ORG_PROFILE config.
| Signal | Value |
|---|---|
| Tests | 869 pass across 40 files (Vitest) |
| Type safety | 0 errors, 0 any, 0 @ts-ignore in src/ |
| Lint | 0 errors (ESLint flat config) |
| CI | Typecheck + lint + build on every push (GitHub Actions) |
| Mobile | Verified on iPhone SE (375×667) via Playwright |
| Race conditions | 6 fetch-in-useEffect sites guarded, 1 DB TOCTOU closed with unique constraint |
| Design tokens | All in globals.css (@theme inline) — zero hex literals in components |
| Dark mode | Fully wired via next-themes + semantic two-tier token system |
| Security | Explicit auth modes (Basic Auth / public demo / fail-closed default); HMAC share tokens; security headers on every response |
| Multi-tenant | org_id on all 5 DB tables; org identity behind ORG_PROFILE config |
| Deploy | Self-hosted on Hetzner (Caddy + Next.js standalone output) — docs/DEPLOYMENT.md |
Every page that ships data shows a click-to-inspect "where did this number come
from" modal. Every metric traces back to a NUMBERS_REGISTRY entry with source,
formula, and confidence level. No black boxes.
- Next.js 16 App Router · TypeScript strict
- PostgreSQL (self-hosted,
node-postgresdriver) · Drizzle ORM — schema is SSOT - Zod 4 — types derived via
z.infer<>, never defined separately - Tailwind v4 — design tokens via
@theme inlineinglobals.css - Chart.js for finance dashboards ·
@react-pdf/rendererfor PDFs - Groq (Llama 3.x) — LLM triage + rewrite (configurable, rate-limit aware)
- Hetzner — self-hosted behind Caddy, Next.js
standaloneserver output
npm install
npm run dev # http://localhost:3000 (pre-runs sync: DB → generated TS)
npm test # 850 tests
npm run audit # live pipeline + Gesuch funnel report
npm run build # production build, auto-syncs firstInternal routes (/fundraising/*, /api/*) support HTTP Basic Auth via
src/middleware.ts — set INTERNAL_PASSWORD in the
server environment, or INTERNAL_AUTH=off for a fully public deployment
(the current demo-phase setting). /gesuch/share/[token] is always public,
with HMAC-SHA256 tokens for sending foundation-specific content to program
officers.
src/
├── app/ # Next.js App Router (28 page routes)
├── components/ # UI: layout, foundation, fundraising, gesuch, charts, ui
├── lib/
│ ├── schemas/ # Zod — SSOT for every type
│ ├── config/ # Foundations, stories, metrics, numbers, themes (org-specific)
│ ├── db/ # Drizzle schema + migrations + Postgres client
│ ├── domain/ # Pure business logic (scoring, composing, filtering)
│ ├── pdf/ # @react-pdf/renderer templates (Gesuch, pitch deck, impact)
│ └── utils/ # Format, errors, share-token, a11y, slug
└── hooks/ # useFinancialData, useFoundationFilters, useGesuchOverrides
scripts/ # 23 pipeline scripts (ingest, triage, research, audit)
docs/ # KNOWLEDGE_ARCHITECTURE, DATABASE_SETUP, design guides
research/ # Pipeline notes + drafts (gitignored except notes)
org-context/ # New-org onboarding inputs (per-tenant)
public/documents/ # Source documents (anonymised) — SSOT for displayed numbers
| Phase | Status | What it means |
|---|---|---|
| 1 — Revamp-IT MVP | ✅ Shipped | Dashboards, foundation list, Gesuch workflow, pipeline kanban |
| 2 — Document generation | ✅ Shipped | Gesuch PDF (4-page), one-pager, share landing, pitch deck (8-slide), impact report |
| 3 — Multi-tenant (Hirnli) | 🚧 Designed | New org clones repo + drops 19 ORG-SPECIFIC files in org-context/<name>/. Auth via Clerk replaces middleware password. |
The architecture is multi-tenant-by-construction: the foundation registry layer (universal Swiss-foundation facts) is independent from the analysis layer (one org's fit scores and research notes), so adding a tenant means rewriting analysis + branding, not re-doing the registry.
CLAUDE.md— full product vision, scoring model, schema, data flow, conventionsscripts/README.md— pipeline tools (23 scripts + 18 npm aliases)org-context/_template/README.md— multi-tenant onboarding checklistdocs/KNOWLEDGE_ARCHITECTURE.md— 3-tier SSOT governancedocs/DEPLOYMENT.md— self-hosted Hetzner deploy procedure, env, crons, migrationsdocs/DATABASE_SETUP.md— PostgreSQL + Drizzle local-dev setupdocs/AUDIT_REPORT.md— 2026-03 baseline codebase auditpublic/documents/README.md— anonymised source document library
Proprietary. © Revamp-IT. All rights reserved.
See LICENSE.