Jordy HoogeveenandClaude Opus 5 081820dfd6 release.ps1 respecteert core.sshCommand bij de origin-controle
Het script zette GIT_SSH_COMMAND hard op "ssh", waarmee het de al
geconfigureerde core.sshCommand overschreef. Op Windows praat alleen de
OpenSSH van het systeem met de ssh-agent; Git's eigen ssh niet. Afhankelijk
van de PATH-volgorde faalde de controle daardoor met "Permission denied"
terwijl git zelf prima kon pushen.

Nu wordt core.sshCommand als basis gebruikt (met "ssh" als fallback) en
worden alleen BatchMode en ConnectTimeout toegevoegd.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 23:40:24 +02:00
2026-09-04 12:24:22 +02:00
2026-09-04 12:24:22 +02:00

💜 VibeFinance

Persoonlijk vermogensdashboard

Eigen vermogen · Schulden · Voortgang · Gebruikersbeheer

React Node.js PostgreSQL Docker Version Built with Claude


🤖 Gebouwd met Claude.ai

Deze applicatie is volledig ontworpen en ontwikkeld met behulp van Claude.ai — de AI-assistent van Anthropic. Van architectuur tot gebruikersinterface: alles is stap voor stap tot stand gekomen in samenwerking met Claude.


⚡ Quick Start

Vereisten: Docker Engine 24+ en Docker Compose v2+

De app draait in 2 containers: app (Express API + gebouwde frontend) en postgres (database).

.env — kopieer .env.example en vul in:

POSTGRES_USER=vibefinance
POSTGRES_PASSWORD=kies_een_sterk_wachtwoord
JWT_SECRET=minimaal_64_willekeurige_tekens
APP_PORT=3400
# Genereer een veilige JWT_SECRET
openssl rand -hex 64
cp .env.example .env    # en vul de waarden in
docker compose pull && docker compose up -d

Navigeer naar http://<server-ip>:3400 en registreer je account. De eerste geregistreerde gebruiker krijgt automatisch de Admin-rol.

De container luistert intern op poort 3001 en serveert daar zowel de frontend (op /) als de API (op /api). APP_PORT bepaalt de poort op de host.

Development (hot reload)

.\dev.ps1

Eén dev-container draait de API (node --watch) én de Vite dev-server samen:

Adres Wat
http://localhost de app in de browser (Vite, hot reload)
http://localhost:3001/api/health de API rechtstreeks

Vite proxyt /api naar de API in dezelfde container, dus je hebt geen CORS- uitzonderingen nodig. Handige acties:

.\dev.ps1 up -Target app     # alleen de app herbouwen en herstarten
.\dev.ps1 logs               # logs van de app volgen
.\dev.ps1 down               # stoppen én volumes wissen (dev-database weg)
.\dev.ps1 test               # testsuite draaien

.\dev.ps1 up laat de dev-database staan; alleen .\dev.ps1 down wist de volumes.

Testen

.\test.ps1              # dependency-check + backend-tests + build + smoketest
.\test.ps1 -Unit        # dependency-check + backend-tests
.\test.ps1 -NoSmoke     # zonder de stack te starten
.\test.ps1 -Strict      # faal als een dependency achterloopt
.\test.ps1 -SkipDeps    # dependency-check overslaan (bijv. offline)

Alles loopt in Docker — Node op de host is niet nodig. De backend-tests draaien zonder database via het test-target in de Dockerfile.

Stap 1 vergelijkt elke dependency in frontend/ en backend/package.json met de laatste versie in het npm-register, zodat je bij elke testronde ziet of er updates open staan. Pakketten die bewust achterblijven staan met reden in docker/update-exceptions.json en laten de check niet falen:

frontend/package.json (9 dependencies)
  [vast ] eslint    ^9.39.5 → 10.9.1   eslint-plugin-react ondersteunt nog geen ESLint 10
  actueel op de vastgezette versies na
backend/package.json (15 dependencies)
  alles actueel

Productie release

$env:GITEA_TOKEN = "<token met release-rechten>"
.\release.ps1

Draait de tests, bouwt het app-image voor amd64 + arm64 (Raspberry Pi), pusht naar de registry, zet de Git-tag en publiceert de Gitea-release.


🗂️ Functionaliteit

Scherm Wat het doet
📊 Dashboard Overzicht van totaal eigen vermogen, schulden en netto vermogen
💰 Eigen vermogen Vermogensposten per categorie beheren + geïnvesteerde fiat historiek
📉 Schulden Schulden bijhouden per blok met afbetalingsoverzicht
📈 Voortgang Grafieken en trends van EV en schuld over tijd (apart bij te houden)
👥 Gebruikers Accounts aanmaken, bewerken en beheren (Admin-rol vereist)

🏗️ Architectuur

vibefinance/
├── Dockerfile                  # Multi-stage: frontend build → app-image
├── .dockerignore
├── docker-compose.yml          # Productie: app + postgres
├── docker-compose.dev.yml      # Dev: app (API + Vite) + postgres
├── .env.example                # Kopieer naar .env en vul in
├── package.json                # Versienummer — single source of truth
├── dev.ps1 / dev.sh            # Dev script (bouwen, starten, logs, pushen)
├── test.ps1 / test.sh          # Testsuite (unit + build + smoketest)
├── release.ps1 / release.sh    # Release (test, push, tag, Gitea-release)
│
├── docker/
│   └── dev-entrypoint.sh       # Start API + Vite samen in de dev-container
│
├── frontend/                   # React / Vite SPA (build → dist)
│   ├── vite.config.js          # /api proxy naar de API in dezelfde container
│   └── src/
│       ├── App.jsx             # Root – wiring + idle-logout
│       ├── main.jsx
│       ├── constants/          # Kleuren, tabs, begindata
│       ├── utils/              # Formatters, helpers
│       ├── hooks/              # useTheme, useUpdateCheck
│       ├── context/            # AppContext (global state + API sync)
│       ├── components/
│       │   ├── ui/             # Primitieve UI (VCard, DonutChart…)
│       │   ├── LoginPage.jsx
│       │   ├── NavBar.jsx
│       │   ├── ProfielPopup.jsx
│       │   └── GebruikersBeheer.jsx
│       └── pages/
│           ├── DashboardTab.jsx
│           ├── EigenVermogenTab.jsx
│           ├── SchuldTab.jsx
│           └── VoortgangTab.jsx
│
└── backend/                    # Express REST API + statische frontend
    ├── test/                   # node --test integratietests
    └── src/
        ├── server.js           # Entry point: API op /api, SPA op /
        ├── db.js               # PostgreSQL pool + initDb() schema-migraties
        ├── config/             # Omgevingsvariabelen (incl. STATIC_DIR)
        ├── constants/          # Begindata (initialData.js)
        ├── middleware/         # auth.js, errorHandler.js
        ├── routes/             # auth, data, users, health, update-check
        └── stores/             # userStore, dataStore

Stack: React 19 · Vite 8 · Node.js 22 · Express 5 · PostgreSQL 18 · JWT · bcrypt · Docker Compose v2

Waarom 2 containers

De frontend werd eerder door een eigen nginx-container geserveerd. Voor self-hosting op een Raspberry Pi is dat een container te veel: de Express-app serveert de statische build nu zelf, dus er is geen aparte webserver en geen interne proxy meer nodig. Dat betekent ook: één origin, dus geen CORS tussen frontend en API.

Verzoek Wat de app doet
/api/... REST API (rate limited)
/assets/... Statische build, 1 jaar immutable gecached
al het overige index.html — fallback voor React-routing

🔌 API

Beveiligde endpoints vereisen Authorization: Bearer <token>. Rate limiting: 20 req/15 min op auth-routes, 200 req/15 min op de rest van /api (statische bestanden zijn uitgezonderd).

Route Methoden Omschrijving
/api/auth/register POST Account aanmaken (eerste user = Admin)
/api/auth/login POST Inloggen, JWT token terug
/api/auth/me GET, PATCH Profiel ophalen en bijwerken
/api/auth/me/password POST Wachtwoord wijzigen
/api/data GET, PUT, DELETE Financiële data per gebruiker
/api/users GET, POST, PATCH, DELETE Gebruikersbeheer (Admin only)
/api/health GET Status + uptime
/api/update-check GET Laatste release (voor de update-melding)

🗄️ Database

Tabel Omschrijving
users Accounts met bcrypt hash, rol, actief-vlag en aanmaakdatum
user_data Financiële data per gebruiker (JSON)
Omgeving Volume Mount pad
Productie vibefinance_pgdata /var/lib/postgresql
Development postgres_dev_data /var/lib/postgresql

PostgreSQL 18 gebruikt PGDATA=/var/lib/postgresql/18/docker — het volume is daarom gemount op /var/lib/postgresql (niet /data).

Het schema wordt bij het starten van de app aangemaakt/bijgewerkt via initDb() in backend/src/db.js.


⚙️ Omgevingsvariabelen

Variabele Standaard Omschrijving
POSTGRES_PASSWORD — Verplicht
JWT_SECRET — Verplicht — minimaal 64 tekens
POSTGRES_USER vibefinance Database gebruikersnaam
POSTGRES_DB vibefinance Database naam
JWT_EXPIRES 7d Geldigheidsduur token
CORS_ORIGIN http://localhost Externe domeinnaam (één origin, dus zelden nodig)
APP_PORT 3400 Poort op de host (container luistert op 3001)
PORT 3001 Poort binnen de container
STATIC_DIR /app/public Map met de frontend-build
UPDATE_CHECK_URL Gitea releases-API Bron update-melding (leeg = uit)
UPDATE_CHECK_TOKEN — Alleen voor een niet-publieke repo

🔐 Beveiliging

  • Wachtwoorden gehasht met bcrypt (cost factor 12)
  • JWT authenticatie met instelbare vervaltijd
  • Frontend en API op één origin — geen interne proxy, geen CORS-uitzonderingen
  • Content-Security-Policy via Helmet, toegespitst op wat de app laadt
  • Database bereikbaar alleen binnen het interne Docker netwerk
  • App-container draait als non-root
  • Rate limiting op /api (statische bestanden uitgezonderd)

🧪 Testen

Laag Wat Commando
Dependencies Staan package.json's op de laatste versies .\test.ps1 -Unit
Backend API-routes, SPA-fallback, cache- en security-headers .\test.ps1 -Unit
Build Vite-build + productie-image .\test.ps1 -NoSmoke
Integratie Smoketest op de echte app + postgres stack .\test.ps1

🛠️ Beheer

Zie BEHEER.md voor commando's voor lokale ontwikkeling, releases, logs en database-toegang.


Privé gebruik · gebouwd met Claude.ai

S
Description
No description provided
Readme
1.1 MiB
v1.0.13
Latest
2026-10-01 17:00:42 +02:00
Languages
JavaScript 83.3%
PowerShell 13.5%
Dockerfile 1.5%
Shell 1.2%
CSS 0.3%
Other 0.2%