Rebranding zu NextJobs (nextjobs.cc)

- Markenname 'Bewerbungs-Tracker' -> 'NextJobs' im gesamten UI,
  Footer (incl. nextjobs.cc Copyright), Login, Wortmarke in der
  Top-Navi (Next + Jobs-Gradient), Favicon, Swagger/OpenAPI-Titel,
  CalDAV-PRODID, Browser-Erweiterung (manifest, content, background),
  Runner-Log und Doku.
- Funktionale Begriffe (Bewerbungsunterlagen, -datum etc.) bleiben.
- Docker-Registry (git.hackner.dev) als Infrastruktur unberuehrt.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-14 01:40:26 +02:00
co-authored by Claude
parent cc2df90653
commit bf789af62a
18 changed files with 30 additions and 30 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
# Bewerbungs-Tracker # NextJobs
Ein professioneller Job Application Tracker für Jobcenter Grundsicherung Monatsberichte. Ein professioneller Job Application Tracker für Jobcenter Grundsicherung Monatsberichte.
@@ -23,7 +23,7 @@ Ablauf:
Standard-Anschreiben und den Lebenslauf als Text einfügen. Diese Basis-Unterlagen Standard-Anschreiben und den Lebenslauf als Text einfügen. Diese Basis-Unterlagen
sind die Faktengrundlage; die KI erfindet nichts hinzu. sind die Faktengrundlage; die KI erfindet nichts hinzu.
2. **Stelle importieren** Mit der Browser-Erweiterung (`extension/`) auf Indeed den 2. **Stelle importieren** Mit der Browser-Erweiterung (`extension/`) auf Indeed den
Button **„An Bewerbungs-Tracker senden"** klicken. Button **„An NextJobs senden"** klicken.
3. **Automatische Verarbeitung** Der Tracker legt die Bewerbung mit Status 3. **Automatische Verarbeitung** Der Tracker legt die Bewerbung mit Status
**Entwurf** an und generiert im Hintergrund über die **Ollama Cloud API** **Entwurf** an und generiert im Hintergrund über die **Ollama Cloud API**
zugeschnittene Bewerbungsunterlagen, die als PDF-Anhänge an der Bewerbung hängen. zugeschnittene Bewerbungsunterlagen, die als PDF-Anhänge an der Bewerbung hängen.
@@ -289,7 +289,7 @@ MIT
## Autor ## Autor
Bewerbungs-Tracker für Jobcenter Grundsicherung NextJobs für Jobcenter Grundsicherung
--- ---
+4 -4
View File
@@ -1,14 +1,14 @@
# Bewerbungs-Tracker Indeed Import (Browser-Erweiterung) # NextJobs Indeed Import (Browser-Erweiterung)
Chromium-Erweiterung (Manifest V3), die auf Indeed einen Button **direkt neben der Chromium-Erweiterung (Manifest V3), die auf Indeed einen Button **direkt neben der
Stellenbeschreibung** einfügt. Ein Klick sendet alle Stelleninformationen an den Stellenbeschreibung** einfügt. Ein Klick sendet alle Stelleninformationen an den
Bewerbungs-Tracker. Dort wird die Stelle als **Entwurf** angelegt und die KI NextJobs. Dort wird die Stelle als **Entwurf** angelegt und die KI
erstellt automatisch zugeschnittene Bewerbungsunterlagen (auf Basis der hinterlegten erstellt automatisch zugeschnittene Bewerbungsunterlagen (auf Basis der hinterlegten
Vorlagen). Vorlagen).
## Installation (Entwicklermodus) ## Installation (Entwicklermodus)
1. Bewerbungs-Tracker starten (Standard: `http://localhost:3000`). 1. NextJobs starten (Standard: `http://localhost:3000`).
2. In Chrome/Edge/Brave `chrome://extensions` öffnen. 2. In Chrome/Edge/Brave `chrome://extensions` öffnen.
3. **Entwicklermodus** oben rechts aktivieren. 3. **Entwicklermodus** oben rechts aktivieren.
4. **Entpackte Erweiterung laden** klicken und diesen `extension/`-Ordner auswählen. 4. **Entpackte Erweiterung laden** klicken und diesen `extension/`-Ordner auswählen.
@@ -23,7 +23,7 @@ Mit **Verbindung testen** prüfen, ob der Tracker erreichbar ist.
1. Auf `indeed.com` eine Stelle öffnen. 1. Auf `indeed.com` eine Stelle öffnen.
2. Neben der Überschrift **„Vollständige Stellenbeschreibung"** erscheint der grüne 2. Neben der Überschrift **„Vollständige Stellenbeschreibung"** erscheint der grüne
Button **„An Bewerbungs-Tracker senden"**. Button **„An NextJobs senden"**.
3. Klicken → die Stelle wird als Entwurf angelegt, die Unterlagen werden im 3. Klicken → die Stelle wird als Entwurf angelegt, die Unterlagen werden im
Hintergrund generiert. Über den Link „Entwurf öffnen" gelangst du direkt zur Hintergrund generiert. Über den Link „Entwurf öffnen" gelangst du direkt zur
Bewerbung im Tracker. Bewerbung im Tracker.
+2 -2
View File
@@ -1,4 +1,4 @@
// Service worker: performs the cross-origin POST to the Bewerbungs-Tracker. // Service worker: performs the cross-origin POST to the NextJobs.
// Routing the request through the background worker (instead of the content // Routing the request through the background worker (instead of the content
// script) keeps it independent of the Indeed page's Content-Security-Policy. // script) keeps it independent of the Indeed page's Content-Security-Policy.
@@ -56,7 +56,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
sendResponse({ sendResponse({
ok: false, ok: false,
error: error:
'Konnte den Bewerbungs-Tracker nicht erreichen. Läuft er, und ist die ' + 'Konnte den NextJobs nicht erreichen. Läuft er, und ist die ' +
'Adresse in den Erweiterungs-Einstellungen korrekt? (' + String(err.message) + ')', 'Adresse in den Erweiterungs-Einstellungen korrekt? (' + String(err.message) + ')',
}); });
} }
+3 -3
View File
@@ -1,4 +1,4 @@
// Content script: injects an "An Bewerbungs-Tracker senden" button next to the // Content script: injects an "An NextJobs senden" button next to the
// Indeed job description, scrapes the job details and forwards them to the // Indeed job description, scrapes the job details and forwards them to the
// tracker's import API (via the background service worker). // tracker's import API (via the background service worker).
@@ -103,7 +103,7 @@
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.type = 'button'; btn.type = 'button';
btn.className = 'bt-import-btn'; btn.className = 'bt-import-btn';
btn.innerHTML = ICON_SEND + '<span>An Bewerbungs-Tracker senden</span>'; btn.innerHTML = ICON_SEND + '<span>An NextJobs senden</span>';
const status = document.createElement('div'); const status = document.createElement('div');
status.className = 'bt-import-status'; status.className = 'bt-import-status';
@@ -147,7 +147,7 @@
setStatus(status, '', ''); setStatus(status, '', '');
chrome.runtime.sendMessage({ type: 'IMPORT_JOB', payload: payload }, (resp) => { chrome.runtime.sendMessage({ type: 'IMPORT_JOB', payload: payload }, (resp) => {
btn.innerHTML = ICON_SEND + '<span>' + (originalLabel || 'An Bewerbungs-Tracker senden') + '</span>'; btn.innerHTML = ICON_SEND + '<span>' + (originalLabel || 'An NextJobs senden') + '</span>';
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {
btn.disabled = false; btn.disabled = false;
+3 -3
View File
@@ -1,8 +1,8 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Bewerbungs-Tracker Stellen-Import", "name": "NextJobs Stellen-Import",
"version": "1.1.0", "version": "1.1.0",
"description": "Erfasst Stellen von jeder Webseite (nicht nur Indeed) über das Erweiterungs-Popup und sendet sie an den Bewerbungs-Tracker, der automatisch zugeschnittene Bewerbungsunterlagen erstellt.", "description": "Erfasst Stellen von jeder Webseite (nicht nur Indeed) über das Erweiterungs-Popup und sendet sie an den NextJobs, der automatisch zugeschnittene Bewerbungsunterlagen erstellt.",
"permissions": ["storage", "scripting", "activeTab"], "permissions": ["storage", "scripting", "activeTab"],
"host_permissions": [ "host_permissions": [
"*://*.indeed.com/*", "*://*.indeed.com/*",
@@ -24,6 +24,6 @@
}, },
"action": { "action": {
"default_popup": "popup.html", "default_popup": "popup.html",
"default_title": "Bewerbungs-Tracker" "default_title": "NextJobs"
} }
} }
+1 -1
View File
@@ -1,4 +1,4 @@
// Third-party REST API (v1) for the Bewerbungs-Tracker. // Third-party REST API (v1) for the NextJobs.
// //
// Mounted under /api/v1 in server.js. All endpoints except /health require an // Mounted under /api/v1 in server.js. All endpoints except /health require an
// API key sent in the X-API-Key header. The key is per-user: it is the // API key sent in the X-API-Key header. The key is per-user: it is the
+1 -1
View File
@@ -160,7 +160,7 @@ function buildICS(evt) {
const lines = [ const lines = [
'BEGIN:VCALENDAR', 'BEGIN:VCALENDAR',
'VERSION:2.0', 'VERSION:2.0',
'PRODID:-//Bewerbungs-Tracker//Kalender//DE', 'PRODID:-//NextJobs//Kalender//DE',
'CALSCALE:GREGORIAN', 'CALSCALE:GREGORIAN',
'BEGIN:VEVENT', 'BEGIN:VEVENT',
'UID:' + uid, 'UID:' + uid,
+1 -1
View File
@@ -36,7 +36,7 @@ function buildOpenApiSpec(baseUrl = '') {
return { return {
openapi: '3.0.3', openapi: '3.0.3',
info: { info: {
title: 'Bewerbungs-Tracker REST-API', title: 'NextJobs REST-API',
version: '1.0.0', version: '1.0.0',
description: description:
'REST-API für Drittanbietersoftware zum Lesen und Verwalten von ' + 'REST-API für Drittanbietersoftware zum Lesen und Verwalten von ' +
+1 -1
View File
@@ -1,5 +1,5 @@
/* ============================================ /* ============================================
Bewerbungs-Tracker - Custom Styles NextJobs - Custom Styles
============================================ */ ============================================ */
/* Base styles */ /* Base styles */
+1 -1
View File
@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Bewerbungs-Tracker"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="NextJobs">
<defs> <defs>
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"> <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#38bdf8"/> <stop offset="0" stop-color="#38bdf8"/>

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 632 B

+2 -2
View File
@@ -1,5 +1,5 @@
// ============================================ // ============================================
// Bewerbungs-Tracker - Client-side JavaScript // NextJobs - Client-side JavaScript
// ============================================ // ============================================
// DOM Elements // DOM Elements
@@ -693,4 +693,4 @@ document.getElementById('currentYear').textContent = new Date().getFullYear();
// Initialize // Initialize
// ============================================ // ============================================
console.log('Bewerbungs-Tracker initialized'); console.log('NextJobs initialized');
+1 -1
View File
@@ -48,7 +48,7 @@ cd "$PROJECT_DIR" || exit 1
# API-Erreichbarkeit prüfen — ohne den Tracker kann der Agent nichts importieren. # API-Erreichbarkeit prüfen — ohne den Tracker kann der Agent nichts importieren.
if ! curl -fsS --max-time 10 http://localhost:4327/api/v1/health >/dev/null 2>&1; then if ! curl -fsS --max-time 10 http://localhost:4327/api/v1/health >/dev/null 2>&1; then
echo "$(date -Is) FEHLER: Bewerbungs-Tracker (localhost:4327) nicht erreichbar Lauf übersprungen." >> "$LOG" echo "$(date -Is) FEHLER: NextJobs (localhost:4327) nicht erreichbar Lauf übersprungen." >> "$LOG"
exit 1 exit 1
fi fi
+2 -2
View File
@@ -3665,7 +3665,7 @@ initializeDatabase().then(async () => {
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Bewerbungs-Tracker API-Dokumentation</title> <title>NextJobs API-Dokumentation</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" /> <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" />
<style> <style>
html { box-sizing: border-box; overflow-y: scroll; } html { box-sizing: border-box; overflow-y: scroll; }
@@ -3678,7 +3678,7 @@ initializeDatabase().then(async () => {
</head> </head>
<body> <body>
<div class="topbar"> <div class="topbar">
<strong>Bewerbungs-Tracker REST-API</strong> <strong>NextJobs REST-API</strong>
<span style="opacity:.7">Drittanbieter-Schnittstelle v1</span> <span style="opacity:.7">Drittanbieter-Schnittstelle v1</span>
<span style="margin-left:auto">Authentifizierung: Header <code>X-API-Key</code></span> <span style="margin-left:auto">Authentifizierung: Header <code>X-API-Key</code></span>
<a href="/">← zur App</a> <a href="/">← zur App</a>
+1 -1
View File
@@ -13,7 +13,7 @@
<svg class="w-12 h-12 text-blue-600 dark:text-blue-400 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-12 h-12 text-blue-600 dark:text-blue-400 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg> </svg>
<h1 class="text-xl font-bold text-gray-800 dark:text-white">Bewerbungs-Tracker</h1> <h1 class="text-xl font-bold text-gray-800 dark:text-white">NextJobs</h1>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">Bitte anmelden</p> <p class="text-sm text-gray-500 dark:text-gray-400 mt-1">Bitte anmelden</p>
</div> </div>
+1 -1
View File
@@ -1,7 +1,7 @@
<footer class="mt-12 border-t border-gray-200/80 dark:border-white/5"> <footer class="mt-12 border-t border-gray-200/80 dark:border-white/5">
<div class="container mx-auto px-4 py-8 text-center"> <div class="container mx-auto px-4 py-8 text-center">
<p class="text-xs text-gray-400 dark:text-slate-500"> <p class="text-xs text-gray-400 dark:text-slate-500">
Bewerbungssystem · &copy; hackner.dev <span id="currentYear"><%= new Date().getFullYear() %></span> NextJobs · &copy; nextjobs.cc <span id="currentYear"><%= new Date().getFullYear() %></span>
</p> </p>
</div> </div>
</footer> </footer>
+1 -1
View File
@@ -1,7 +1,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#2563eb"> <meta name="theme-color" content="#2563eb">
<title>Bewerbungs-Tracker</title> <title>NextJobs</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/favicon.svg">
<!-- Apply the dark class before first paint to avoid a light-mode flash (FOUC). <!-- Apply the dark class before first paint to avoid a light-mode flash (FOUC).
Theme follows the browser/OS setting (prefers-color-scheme) — no manual toggle. --> Theme follows the browser/OS setting (prefers-color-scheme) — no manual toggle. -->
+1 -1
View File
@@ -42,7 +42,7 @@
</svg> </svg>
</span> </span>
<span class="whitespace-nowrap text-[15px] font-semibold leading-none tracking-tight"> <span class="whitespace-nowrap text-[15px] font-semibold leading-none tracking-tight">
<span class="text-gray-900 dark:text-white">Bewerbungs</span><span class="bg-gradient-to-r from-sky-500 to-blue-600 bg-clip-text text-transparent">Tracker</span> <span class="text-gray-900 dark:text-white">Next</span><span class="bg-gradient-to-r from-sky-500 to-blue-600 bg-clip-text text-transparent">Jobs</span>
</span> </span>
</a> </a>
+1 -1
View File
@@ -91,7 +91,7 @@
<label for="webseite" class="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Webseite</label> <label for="webseite" class="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Webseite</label>
<input type="text" id="webseite" name="webseite" <input type="text" id="webseite" name="webseite"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-800 dark:text-white" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-800 dark:text-white"
placeholder="z. B. hackner.dev" value="<%= settings.webseite || '' %>"> placeholder="z. B. nextjobs.cc" value="<%= settings.webseite || '' %>">
</div> </div>
<div> <div>
<label for="geburtsdatum" class="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Geburtsdatum</label> <label for="geburtsdatum" class="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Geburtsdatum</label>