- TypeScript 99.1%
- JavaScript 0.6%
- Dockerfile 0.2%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| assets | ||
| drizzle | ||
| e2e | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc.json | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| eslint.config.mjs | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.mts | ||
Ferienwohnung
Web-App für eine Familie zum Belegen einer gemeinsamen Ferienwohnung: Kalender mit Zimmern, Buchungen und Sperren, Benachrichtigungen in der App und per Push, Admin-Modus für Änderungen an Einträgen anderer. Oberfläche auf Deutsch, installierbar als PWA.
Technik: Next.js 16 (App Router), React 19, TypeScript, Drizzle ORM mit SQLite, Vitest, Playwright.
Voraussetzungen
- Node.js 22
Entwicklung
npm install
npm run dev
Beim ersten Start wird das Konto admin angelegt (siehe ADMIN_START_PASSWORT und TESTPHASE).
Prüfen
npm run check
Führt Formatprüfung, ESLint, Typprüfung, Unit-Tests und E2E-Tests aus. Die E2E-Tests starten einen eigenen Server auf
E2E_PORT (Standard 3100); der Port muss frei sein, z. B. E2E_PORT=3100 npm run test:e2e.
Nur in der Container-Umgebung dieses Projekts muss zusätzlich LD_LIBRARY_PATH für Playwright
gesetzt sein; sonst weglassen.
Betrieb
npm run build
npm run start:standalone
Das Skript kopiert statische Dateien und Migrationen in .next/standalone und startet den Server.
Die Datenbank liegt standardmäßig in data/app.db.
Hosting auf onk.style
Die App läuft als Web-Container auf onk.style unter https://glashuette.ollo2012.web.onk.style.
- Pull Requests durchlaufen den Gate-Job
web / gate: dietest-Stufe imDockerfile(Format, Lint, Typprüfung, Unit-Tests, Build und Starttest mitscripts/smoke.mjs) und der Bau des Images. Die E2E-Tests laufen lokal (npm run check) vor dem Merge. - Ein Merge auf
mainist ein Deployment:.forgejo/workflows/web.yamlveröffentlicht das Image alsgit.ziemlichoptimal.de/web/ollo2012/glashuette:main. Ein Revert ist ein Rollback. - Der Container läuft als Nutzer 1000 mit schreibgeschütztem Dateisystem. Datenbank und Sicherungen liegen
im Volume
/data(DATABASE_PATH=/data/app.db). Die Plattform prüftGET /healthz. - Umgebungsvariablen (z. B.
ADMIN_START_PASSWORTfür den ersten Start) werden im Concierge (https://concierge.onk.style) beim Container gesetzt, nie im Repo.TESTPHASEbleibt dort ungesetzt.
Sicherung
- Die laufende App legt täglich automatisch eine Sicherung an, in
data/backupsbzw. inBACKUP_DIR. Sicherungen der letzten 14 Tage bleiben erhalten, ältere werden gelöscht. - Im Gefahrenbereich der Einstellungsseite (Admin-Modus und Recht „Gefahrenbereich“) lässt sich jede
Sicherung herunterladen und bei laufender App zurückspielen. Vorher wird der aktuelle Stand als
…-vor-wiederherstellunggesichert, danach sind alle abgemeldet. npm run backuperstellt sofort eine Sicherung.npm run restore -- <datei>spielt eine Sicherung zurück (nur ein Dateiname bezieht sich auf den Sicherungsordner; ohne Argument werden die vorhandenen aufgelistet). Die App dafür vorher stoppen. Der bisherige Stand wird als Sicherung…-vor-wiederherstellungabgelegt.
Umgebungsvariablen
| Variable | Bedeutung | Standard |
|---|---|---|
DATABASE_PATH |
Pfad der SQLite-Datei | data/app.db |
BACKUP_DIR |
Ordner der Sicherungen | backups neben der Datenbank |
TESTPHASE |
1: Startpasswort des ersten Kontos ist admin, wenn ADMIN_START_PASSWORT fehlt |
nicht gesetzt |
ADMIN_START_PASSWORT |
Startpasswort des Kontos admin; nötig beim ersten Start ohne TESTPHASE=1, muss beim Login geändert werden |
– |
VAPID_PUBLIC_KEY |
Öffentlicher VAPID-Schlüssel für Push (mit dem privaten zusammen) | wird erzeugt und in der DB gespeichert |
VAPID_PRIVATE_KEY |
Privater VAPID-Schlüssel für Push | wie oben |
VAPID_SUBJECT |
Kontakt für Push-Dienste (mailto: oder https:) |
mailto:fun@olejancke.com |
PORT |
Port des Servers | 3000 |
HOSTNAME |
Adresse, an die der Server sich bindet | alle Adressen |