This repository is a Spring Boot job application tracking system with both the backend API and a bundled server-served frontend. It lets a user manage the full lifecycle of a job search in one place: applications, resumes, cover letters, communications, reminders, interviews, attachments, skills, audit history, and reporting-ready metadata.
The repository now implements the documented core workflows, secured API surface, bundled frontend workspace, extended read models, and behavior-focused test suite. The remaining work is mostly operational hardening, browser-level UX polish, or future product expansion, not structural rework.
- User signup, login, session/token lifecycle, and profile management
- End-to-end job application tracking from draft to offer or rejection
- Reusable document library for resumes, cover letters, and attachments
- Communication history across email, phone, LinkedIn, and in-person touchpoints
- Scheduling and reminder workflows for interviews, assessments, and follow-ups
- Searchable metadata for sources, locations, and skills
- Auditable CRUD activity and administrator visibility into user/account state
- API-first design that can support additional web, mobile, or automation clients
- Bundled browser workspace compiled from a colocated React/Vite frontend
- docs/README.md: documentation index
- docs/SYSTEM_FEATURES.md: implemented feature set, expected results, and expansion areas
- docs/ARCHITECTURE.md: current architecture and package responsibilities
- HELP.md: developer quickstart and local setup
- CVREADME.md: concise architecture summary for portfolio or interview use
- frontend/README.md: frontend source layout and build workflow
- scripts/README.md: developer utility scripts
Package-level READMEs are also present under src/main/java/com/nick/job_application_tracker/... for controllers, DTOs, models, repositories, services, configuration, exceptions, handlers, and utilities.
- Java 17
- Spring Boot 3
- Spring Web
- Spring Security
- Spring Data JPA
- PostgreSQL
- Gradle Kotlin DSL
- React
- Vite
- OpenAPI / Swagger
- Logback with JSON logging
The browser workspace is authored in frontend/ and compiled into src/main/resources/static for Spring Boot to serve. It provides:
- authentication flows against the existing JWT API
- dashboard, analytics, recommendations, and calendar views
- an applications queue with sorting, paging, and creation workflows
- dedicated application workspaces with separate summary, activity, and asset tabs
- document library and account management views
- admin-only user and audit screens when the signed-in user has
ADMIN - hash-routed browser navigation for
#/overview,#/applications,#/applications/:id,#/library,#/calendar,#/account, and#/admin
Treat src/main/resources/static as generated output. Browser code should be changed in frontend/ and then rebuilt.
The codebase is organized around standard Spring backend layers:
controller: HTTP endpointsservice: business logic and orchestrationrepository: persistence access and ownership-aware query methodsmodel: JPA entities and enumsdto: request and response contractsconfig: security, JWT, OpenAPI, auditing, and filtersfrontend: React/Vite frontend source and build configsrc/main/resources/static: compiled frontend assets served by Spring Boothandler: centralized exception handlingscripts: utility scripts for development and coveragedocs: product and architecture documentation
See HELP.md for the full setup guide. At a minimum, local development expects:
- Java 17
- PostgreSQL
- Node.js 20+
- environment variables or a
.envfile for:SPRING_PROFILES_ACTIVEJWT_SECRETPOSTGRES_HOSTPOSTGRES_PORTPOSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORD
Typical commands:
./gradlew test
./gradlew bootRunFrontend commands:
cd frontend
npm install
npm run buildFor frontend-only iteration, you can run:
cd frontend
npm run devThe Vite dev server runs on http://localhost:5173/ and proxies /api requests to http://localhost:8081/.
Once the app is running, open http://localhost:8081/ to use the bundled frontend by default, or use the value of PORT if you override it.
For local non-test runs, set JWT_SECRET explicitly so tokens remain valid across restarts.
- Create a
.envfile in the repository root.
SPRING_PROFILES_ACTIVE=dev
JWT_SECRET=replace-with-at-least-32-bytes-or-base64
DDL_AUTO=create
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=jobtrackr
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres- Make sure PostgreSQL is running and the
POSTGRES_DBdatabase already exists.
If you are starting with a fresh database, DDL_AUTO=create is the simplest local option for the first run.
If you are pointing at an older pre-UUID database, do not use update: Hibernate cannot safely migrate the old integer/identity schema to UUID columns.
- Start the application.
./gradlew bootRun- Build the frontend bundle when you change browser code.
cd frontend
npm install
npm run build- Open the app in your browser.
http://localhost:8081/
- Optional: run the automated tests in a separate shell.
./gradlew testUseful local URLs:
http://localhost:8081/: bundled frontendhttp://localhost:8081/swagger-ui/index.html: Swagger UI
Legacy database note:
- If your local PostgreSQL database was created before the UUID refactor, either drop and recreate that database for local use or perform an explicit SQL migration.
- The app now defaults
DDL_AUTOtononewhen the variable is not set so it does not keep attempting invalid integer-to-UUID schema mutations on startup.
The system is more than a CRUD demo. It already operates as an end-to-end job-search workspace and is positioned for incremental expansion:
- a single source of truth for every application
- fewer missed follow-ups and deadlines
- consistent document reuse and version tracking
- cleaner historical records for reflection, analytics, and reporting
- a foundation for deeper dashboards, exports, and AI-assisted features