Lokale Desktop-Anwendung zur Bewerbungsverwaltung — Local-First und verschlüsselt.
Alle Daten bleiben auf dem eigenen Rechner: kein Server, keine Cloud, kein Docker, kein offener Netzwerkanschluss, keine ausgehenden Verbindungen. Die Datenbank ist mit AES-256 verschlüsselt und ohne das Passwort nicht lesbar — auch nicht mit einem SQLite-Werkzeug. So gebaut, weil Bewerbungsunterlagen mit zum Persönlichsten gehören, was auf einem Rechner liegt.
Bewerbungen verwalten — Firma, Stelle, Ansprechpartner, Ort, Link und Notiz. Der Status (Entwurf, Abgeschickt, Absage, Erfolg) lässt sich direkt auf der Karte umstellen, und jede Änderung wird mit Datum festgehalten. Dadurch steht auf der Karte, was zählt:
| Status | Anzeige |
|---|---|
| Entwurf | „Entwurf seit 06.09.2026" |
| Abgeschickt | „Abgeschickt am 06.09.2026 · Nachfassen ab 20.09.2026" |
| Absage / Erfolg | das jeweilige Datum |
Unterlagen — Lebenslauf, Zeugnisse und Zertifikate einmal hinterlegen und mit Bewerbungen verknüpfen, das Anschreiben je Bewerbung. Alles mit PDF-Vorschau in der Anwendung.
PDF-Bündel — führt Anschreiben, Lebenslauf, Zeugnisse und Zertifikate in dieser Reihenfolge zu einer einzigen PDF zusammen (die übliche Reihenfolge einer deutschen Bewerbungsmappe). Wird bei jedem Herunterladen frisch erzeugt und kann deshalb nicht veralten.
Erinnerungen — an ein fehlendes Anschreiben, an liegengebliebene Entwürfe (Rhythmus je Bewerbung wählbar: täglich, wöchentlich, monatlich, aus) und ans Nachfassen nach dem Abschicken. Die Frist steht standardmäßig auf 14 Tagen und lässt sich je Bewerbung überschreiben. Fällige Bewerbungen erscheinen als eigene Kachel und lassen sich damit filtern.
Windows-Benachrichtigungen (abschaltbar) — Erinnerungen über den Infobereich, wahlweise mit Autostart. Beim Schließen des Fensters wird gefragt, ob die Anwendung im Infobereich weiterlaufen soll; nach einstellbarer Inaktivität sperrt sie sich dort von selbst wieder.
Markdown-Export — die gerade angezeigte Liste als Tabelle in eine .md-Datei; Suche und
Statusfilter wirken sich aus.
Markdown-Import — dieselbe Tabelle in der Gegenrichtung: Eine ausgefüllte .md-Datei wird
eingelesen und daraus werden Bewerbungen angelegt. Gedacht für eine Stellenrecherche, die
jemand anders erledigt — auch eine KI. Dafür gibt es „Vorlage für KI": eine Datei mit
leerer Tabelle und der Anweisung, welche Spalten hineingehören.
| Spalte | Beim Import |
|---|---|
| Firma, Stelle, Ort | Pflicht — ohne sie wird die Zeile abgewiesen |
| Ansprechpartner, E-Mail, Link | optional |
| Status, Entwurf seit, Abgeschickt, Abschluss | werden übernommen, wenn gefüllt |
| Nachfassen ab | überlesen — rechnet die Anwendung selbst aus |
Damit lässt sich auch eine anderswo geführte Liste einspielen, ohne dass jede Bewerbung zum Entwurf von heute wird: Steht in der Datei ein Absendedatum, steht es hinterher auch auf der Karte, und die Nachfassfrist rechnet vom richtigen Tag. Fehlen Status und Datum, entsteht ein Entwurf — eine gefundene Stelle ist ja noch keine abgeschickte Bewerbung.
Zeilen, deren Firma und Stelle es schon gibt, werden übersprungen — dieselbe Datei zweimal einzuspielen legt also nichts doppelt an. Eine unbrauchbare Zeile kippt nicht den ganzen Import, sondern steht hinterher mit ihrer Zeilennummer im Bericht.
Auf der Karte lässt sich jedes Datum anklicken und korrigieren, auch nachträglich. Link und E-Mail sind bedienbar: Ein Klick öffnet den Browser beziehungsweise das Mailprogramm, der Knopf daneben legt den Wert in die Zwischenablage.
Die Liste steht neueste zuerst, und die Kacheln filtern sie: Entwürfe, Abgeschickt, Absagen, Erfolge, Fällig — und ganz rechts Gesamt.
Die Anwendung merkt sich Größe, Position und den maximierten Zustand des Fensters.
- JavaFX 21 — Oberfläche
- Spring Boot — Dienste und JPA, ohne Web-Layer (
spring.main.web-application-type: none) - SQLite mit SQLCipher — eingebettete, verschlüsselte Datei-Datenbank, kein Datenbankserver
- PDFBox — Vorschau und Zusammenführen der Unterlagen
| Zugang | Datei | Inhalt |
|---|---|---|
| Demo- und Notfallzugang | ~/.bewerbungsmanager/demo.db |
nur Musterdaten |
| Eigenes Konto | ~/.bewerbungsmanager/data.db |
die echten Bewerbungsdaten |
Der Demo-Zugang (mkysarte / changeme) ist absichtlich fest und steht sichtbar im Login.
Er hat zwei Aufgaben: die Anwendung vor der Entscheidung ausprobieren, und ein Weg zurück
hinein, falls Passwort und Masterpasswort verloren gehen — dann muss niemand deinstallieren
und neu installieren.
An die echten Daten kommt er nicht heran. Beide Datenbanken haben eigene Schlüssel, und
der Demo-Zugang besitzt den zu data.db schlicht nicht. Die Trennung ist damit kryptografisch
erzwungen und nicht bloß in der Oberfläche geprüft. Pro Sitzung ist immer nur eine der beiden
Dateien geöffnet.
Es gibt genau ein echtes Konto — ein zweites lässt sich nicht anlegen.
Die Datenbank wird nicht mit dem Passwort verschlüsselt, sondern mit einem zufälligen
32-Byte-Schlüssel. Der liegt zweifach verpackt in keys.properties — einmal mit dem
Login-Passwort, einmal mit dem Masterpasswort. Ein Passwortwechsel schreibt deshalb nur die
Verpackung neu und lässt die Datenbank unangetastet; das Masterpasswort bleibt unabhängig
davon gültig.
Gehen Passwort und Masterpasswort beide verloren, sind die Daten endgültig weg. Das ist der Preis echter Verschlüsselung — eine Hintertür für den Nutzer wäre auch eine für jeden anderen.
Ausführlich, samt einer ehrlichen Liste dessen, wogegen das alles nicht schützt: SICHERHEIT.md
./mvnw javafx:runMit mkysarte / changeme anmelden, die Musterdaten ausprobieren, dann über
„Eigenes Konto einrichten" Benutzername und Passwort festlegen. Dabei entsteht die
Masterpasswort-PDF — bitte ausdrucken oder sicher ablegen. Das neue Konto startet leer; die
Musterdaten bleiben im Demo-Zugang zurück.
~/.bewerbungsmanager/
demo.db Musterdaten des Demo-Zugangs
data.db das eigene, verschlüsselte Konto
keys.properties der zweifach verpackte Datenbankschlüssel
fenster.properties zuletzt verwendete Fenstergröße
Nichts davon gehört ins Repository; die .gitignore schließt es aus. Ein Backup ist das
Kopieren dieses Ordners — die Anwendung vorher beenden, damit die WAL-Datei geschrieben ist.
./mvnw test131 Tests, ohne Datenbank oder Container. Überwiegend Unit-Tests mit Mockito, dazu drei, die sich lohnen zu kennen:
DemoSessionIntegrationTestfährt eine echte verschlüsselte Sitzung hoch und prüft an der fertigen Datei nach, dass weder der SQLite-Kopf noch Firmen- oder Personennamen im Klartext darin stehen.SchemaUpgradeTestlegt eine befüllte Datenbank im alten Schema an und startet den heutigen Code darüber — fängt Änderungen, die vorhandene Daten unlesbar machen würden.MasterPasswordPdfServiceTestliest die erzeugte PDF zurück und prüft, dass Umlaute ankommen und die Byte-Verweise im Dokument stimmen.
Erzeugt einen nativen Installer mit gebündelter JRE und den nativen SQLCipher-Bibliotheken. Auf dem Zielrechner ist weder Java noch sonst etwas nachzuinstallieren, und es wird nichts aus dem Netz geladen:
./mvnw -Pwindows clean package jpackage:jpackage # Windows: EXE
./mvnw -Pmac clean package jpackage:jpackage # macOS: DMG
./mvnw -Plinux clean package jpackage:jpackage # Linux: DEBErgebnis unter target/installer/.
Hinweis: jpackage kann nicht cross-kompilieren — jedes Paket muss auf seinem eigenen
Betriebssystem gebaut werden. Genau dafür gibt es die CI.
Sie liegen an zwei Stellen, weil es zwei verschiedene Verbraucher gibt:
| Ort | Wofür |
|---|---|
src/main/resources/icons/ |
Klassenpfad — Fenster, Taskleiste, Infobereich (tray.png) |
src/main/packaging/ |
Baueingabe — .ico für Windows, .icns für macOS, .png für Linux |
src/main/packaging/icon-master-1024.png ist die Quelle; alle übrigen Größen sind daraus
gerechnet. IconRessourcenTest prüft, dass jede Datei vorhanden ist und die Kantenlänge hat,
die ihr Name behauptet — sonst fiele ein vertippter Pfad erst beim nächsten Release auf.
Die Windows-Installation trägt eine feste Upgrade-Kennung (winUpgradeUuid in der pom.xml).
Sie darf sich nie ändern, sonst installiert sich eine neue Version neben die alte statt sie
zu ersetzen. Weil v1.0.0 noch ohne diese Kennung veröffentlicht wurde, muss sie einmalig von
Hand deinstalliert werden; ab der nächsten Version greift das Ersetzen.
Zwei Abläufe unter .github/workflows/:
tests.yml — läuft bei jedem Push und jedem Pull Request auf Linux und führt alle Tests
aus. Bewusst nur ein Läufer: Der Code ist plattformunabhängig, und Linux kostet ein Zehntel
eines macOS-Läufers.
release.yml — läuft nur, wenn eine Version markiert wird:
git tag v1.1.0
git push origin v1.1.0Dann laufen erst die Tests, danach bauen drei Läufer parallel die Installer für Windows, macOS und Linux, und die fertigen Dateien landen als GitHub-Release zum Herunterladen. Die Versionsnummer im Installer wird dabei aus der Marke übernommen.
Die Installer sind nicht signiert. Windows meldet beim Start „Der Computer wurde durch Windows geschützt", macOS „Entwickler nicht verifiziert" — beides lässt sich wegklicken, wirkt aber unseriös. Dagegen hülfen nur kostenpflichtige Zertifikate (Windows-Code-Signing, Apple Developer Program).
PolyForm Noncommercial License 1.0.0
| Erlaubt | Untersagt |
|---|---|
| benutzen, ändern, erweitern | verkaufen |
| weitergeben, auch die geänderte Fassung | im Unternehmen produktiv einsetzen |
| privat, in Schule, Hochschule, gemeinnütziger Arbeit | als bezahlten Dienst anbieten |
Wer eine Kopie weitergibt, muss den Lizenztext und den Vermerk aus LICENSE.md mitgeben.
Das ist ausdrücklich keine Open-Source-Lizenz im Sinne der OSI — die verbietet Einschränkungen des Einsatzzwecks, und genau eine solche steht hier drin. GitHub führt sie deshalb nicht als anerkannte Lizenz. Das ist so gewollt.
Die Lizenz gilt für den Code dieses Projekts. Die mitgelieferten Abhängigkeiten behalten
ihre eigenen Lizenzen — JavaFX steht unter GPLv2 mit Classpath-Ausnahme, Spring Boot und
Apache PDFBox unter der Apache License 2.0; das Bündeln durch jpackage ist dadurch gedeckt.