A full-stack job application tracking system with multiple technology stack implementations.
- Overview
- Implementations
- 1. Vue + Nuxt + Drizzle
- 2. Next.js + Express + Prisma
- 3. React + Koa + PostgreSQL
- 4. Svelte + Hono + Drizzle
- 5. React + TanStack + NestJS + Drizzle
- 6. React SSR + TanStack Start + FastAPI
- 7. Angular + Go Gin + pgx/sqlc
- 8. Angular + Spring Boot + JPA/Hibernate
- 9. GraphQL Yoga + React Apollo
- 10. Lambda + DynamoDB (API only)
- 11. Lambda React UI + Lambda API + DynamoDB
- 12. Ruby on Rails API
- Core Features
- Database Architecture
- Service Communication
- Type Diagrams
- Repository Structure
- Getting Started
- Testing
- Development Tools
- License
This repository contains a complete job application tracker built with multiple full-stack implementations. Each provides the same core functionality and user experience, allowing you to compare technology stacks side by side.
| Implementation | Directories | UI Port | API Port | Notes |
|---|---|---|---|---|
| Vue + Nuxt + Drizzle | vue-ui/ + nuxt-api/ |
3020 | 5040 | PostgreSQL (vue_nuxt) |
| Next.js + Express + Prisma | ui/ + api/ |
3000 | 3001 | PostgreSQL (express_prisma) |
| React + Koa + PostgreSQL | react-ui/ + koa-api/ |
3010 | 5010 | Raw SQL (react_koa) |
| Svelte + Hono + Drizzle | svelte-ui/ + hono-api/ |
3030 | 5030 | PostgreSQL (svelte_hono) |
| React + TanStack + NestJS + Drizzle | tanstack-ui/ + nest-api/ |
3050 | 5050 | PostgreSQL (react_nestjs) |
| React SSR + TanStack Start + FastAPI | tanstack-start-ui/ + fastapi/ |
3040 | 5160 | PostgreSQL (python_fastapi) |
| Angular + Go Gin + pgx/sqlc | angular-ui/ + go-api/ |
3060 | 5070 | PostgreSQL (go_gin) |
| Angular + Spring Boot + JPA/Hibernate | angular-spring-ui/ + spring-api/ |
3070 | 8080 | PostgreSQL (java_spring) |
| GraphQL Yoga + React Apollo | react-apollo-ui/ + yoga-api/ |
3080 | 5080 | PostgreSQL (graphql_yoga) |
| Lambda + DynamoDB (API only) | lambda-api/ |
- | 5090 | DynamoDB (lambda_api_applications) |
| Lambda React UI + Lambda API + DynamoDB | lambda-react-ui/ + lambda-api/ |
3090 | 5090 | Zustand + React 19 + Vite, DynamoDB-backed |
| Ruby on Rails API | rails-api/ |
- | 5180 | PostgreSQL (ruby_rails) |
Directories: vue-ui/ + nuxt-api/
Stack:
- Frontend: Vue 3 + Pinia + TypeScript + Vite + Tailwind CSS
- Backend: Nuxt server routes
- Database: Drizzle ORM + PostgreSQL
- Event sourcing with Immer patches, undo/redo, history panel with diff view, patch-based restores, and checkpoint snapshots — see sequence diagram
Directories: ui/ + api/
Stack:
- Frontend: Next.js + React 19 + TypeScript + Tailwind CSS
- Backend: Express.js + Prisma ORM
- Database: PostgreSQL
Directories: react-ui/ + koa-api/
Stack:
- Frontend: React 19 + TypeScript + Vite + Tailwind CSS
- Backend: Koa.js + raw PostgreSQL (no ORM)
- Database: PostgreSQL with SQL migrations
Directories: svelte-ui/ + hono-api/
Stack:
- Frontend: Svelte 5 + SvelteKit + Tailwind CSS
- Backend: Hono (lightweight framework)
- Database: Drizzle ORM + PostgreSQL
Directories: tanstack-ui/ + nest-api/ + nest-history-api/
Stack:
- Frontend: React 19 + TanStack Query v5 + TanStack Router + TypeScript + Vite + Tailwind CSS
- Backend: NestJS with Fastify adapter; history delegated to
nest-history-apiover gRPC - Database: Drizzle ORM + PostgreSQL (
react_nestjs); history inreact_nestjs_history(Knex) - Snapshot-based history with field diffs and restore
- Service communication via Protocol Buffers + gRPC (
proto/history/v1/history.proto); types generated withbuf+ts-proto
Directories: tanstack-start-ui/ + fastapi/
Stack:
- Frontend: React 19 + TanStack Start (SSR) + TanStack Query v5 + TanStack Router + Tailwind CSS
- Backend: Python 3.14 + FastAPI + Pydantic v2
- Database: asyncpg (raw SQL, no ORM) via
python_fastapischema - Server-side rendering with route loaders and
createServerFnserver functions - Snapshot-based history with field diffs and restore
Directories: angular-ui/ + go-api/
Stack:
- Frontend: Angular 21 + standalone components + Angular Signals + Tailwind CSS 4.x — port 3060
- Backend: Go 1.24 + Gin framework + pgx v5 + sqlc for type-safe SQL — port 5070
- Database: PostgreSQL via
go_ginschema (raw SQL, no ORM) - Angular Signals for reactive state, CanDeactivate guard for unsaved changes
- Snapshot-based history with field diffs and restore
- testcontainers-go integration tests
Directories: angular-spring-ui/ + spring-api/
Stack:
- Frontend: Angular 21 + standalone components + Angular Signals + Tailwind CSS 4.x — port 3070
- Backend: Java 21 + Spring Boot 3.4.x + Spring Data JPA + Hibernate 6 + Flyway — port 8080
- Database: PostgreSQL via
java_springschema (JPA entities + Flyway migrations) - AttributeConverter classes for PostgreSQL enum types with hyphenated values
- Snapshot-based history with field diffs and restore
- Gradle 8.x (Kotlin DSL) build system
Directories: react-apollo-ui/ + yoga-api/
Stack:
- Frontend: React 19 + Apollo Client 3 + TanStack Router + TypeScript + Vite + Tailwind CSS — port 3080
- Backend: GraphQL Yoga 5 + Pothos schema builder + Prisma ORM — port 5080
- Database: PostgreSQL via
graphql_yogaschema (Prisma migrations) - GraphQL API with full query/mutation support for applications, stages, and history
- Snapshot-based history with field diffs and restore
Directory: lambda-api/
Stack:
- Backend: TypeScript + Hono + AWS Lambda + DynamoDB — port 5090 (local)
- Database: DynamoDB (single-table design,
lambda_api_applicationstable) — no PostgreSQL - Local development: Hono runs directly via
@hono/node-server; DynamoDB Local via Docker - Lambda deployment: same Hono app wrapped with
@hono/aws-lambdaadapter - Infrastructure: AWS CDK (TypeScript) at
lambda-api/cdk/— DynamoDB + Lambda + HTTP API Gateway v2 - First serverless, non-relational backend in the monorepo
Directories: lambda-react-ui/ + lambda-api/
Stack:
- Frontend: React 19 + TypeScript + Vite + Zustand + React Router — port 3090
- Backend: TypeScript + Hono + AWS Lambda-compatible runtime (local dev server) — port 5090
- Database: DynamoDB single-table design (
lambda_api_applications) vialambda-apiendpoints only - Includes responsive three-pane UI, context panel workflows, CSV import/export, history diff view, and shared E2E compatibility
Directory: rails-api/
Stack:
- Backend: Ruby 3.3+ + Rails API mode + ActiveRecord — port 5180
- Database: PostgreSQL via
ruby_railsschema (Rails migrations) - API-only first pass; UI parity and CSV import/export are deferred follow-ups
- Snapshot-based history with field diffs and restore
All implementations provide:
- Full CRUD operations for job applications
- Interview stage tracking
- Filtering by status, category, source, skills rating
- Sorting and pagination
- Archive/restore functionality
- Dark mode support
- Responsive design (desktop + mobile)
- Input validation and error handling
All implementations share a single PostgreSQL database (app_tracker) with separate schemas for isolation:
| Schema | Apps | ERD |
|---|---|---|
vue_nuxt |
Vue + Nuxt + Drizzle | schema docs |
express_prisma |
Next.js + Express + Prisma | schema docs |
react_koa |
React + Koa + PostgreSQL | schema docs |
svelte_hono |
Svelte + Hono + Drizzle | schema docs |
react_nestjs |
React + TanStack + NestJS + Drizzle | schema docs |
react_nestjs_history |
NestJS gRPC History Service | schema docs |
python_fastapi |
React SSR + TanStack Start + FastAPI | schema docs |
go_gin |
Angular + Go Gin API | schema docs |
java_spring |
Angular + Spring Boot + JPA | schema docs |
graphql_yoga |
GraphQL Yoga + React Apollo | schema docs |
ruby_rails |
Ruby on Rails API | schema docs |
DynamoDB (non-relational):
| Table | Apps | Notes |
|---|---|---|
lambda_api_applications |
Lambda + DynamoDB API + Lambda React UI | Single-table design with GSIs; no PostgreSQL — schema docs |
See docs/DATABASE_ARCHITECTURE.md for ORM setup and connection string patterns.
The React + TanStack + NestJS stack demonstrates microservice communication using gRPC and Protocol Buffers:
nest-api— public REST edge (port 5050); handles all HTTP requests from the browsernest-history-api— internal gRPC microservice (port 50051); owns thereact_nestjs_historyschema and all history persistence
History writes (create, restore) and reads flow from nest-api → gRPC → nest-history-api. The browser-facing REST contract is unchanged — the gRPC transport is entirely internal.
Proto contract: proto/history/v1/history.proto — governed by buf; TypeScript types generated via ts-proto.
npm run proto:lint # lint .proto files with buf
npm run proto:breaking # check for breaking changes against main
npm run proto:generate # regenerate TypeScript types from .protoMermaid class diagrams generated from TypeScript type definitions:
- nuxt-api - Vue + Nuxt (includes event sourcing types)
- ui - Next.js + Express
- react-ui - React + Koa
- koa-api - Koa API (partial - Zod-inferred types unresolved)
- svelte-ui - Svelte + Hono
- tanstack-ui - React + TanStack + NestJS
- nest-api - NestJS API
- tanstack-start-ui - React SSR + TanStack Start
- angular-ui - Angular + Go Gin
- angular-spring-ui - Angular + Spring Boot
- react-apollo-ui - React Apollo + GraphQL Yoga
- yoga-api - GraphQL Yoga API (service input/filter types)
- lambda-api - Lambda + DynamoDB API (hand-maintained —
ts-to-mermaiddoes not support zod)
Regenerate with npm run docs:types (all stacks except lambda-api, which is hand-maintained).
/
├── ui/ # Next.js + React UI
├── api/ # Express + Prisma API
├── react-ui/ # React + Vite UI
├── koa-api/ # Koa + PostgreSQL API
├── svelte-ui/ # SvelteKit UI
├── hono-api/ # Hono API
├── vue-ui/ # Vue + Vite UI
├── tanstack-ui/ # React + TanStack Query/Router UI
├── tanstack-start-ui/ # React SSR + TanStack Start UI
├── angular-ui/ # Angular 21 UI (Go Gin backend)
├── angular-spring-ui/ # Angular 21 UI (Spring Boot backend)
├── spring-api/ # Spring Boot 3.4 API
├── nest-api/ # NestJS + Fastify API
├── nest-history-api/ # NestJS gRPC History Microservice (port 50051)
├── nuxt-api/ # Nuxt server API
├── fastapi/ # Python FastAPI API
├── go-api/ # Go Gin API
├── lambda-api/ # AWS Lambda + DynamoDB API
├── rails-api/ # Ruby on Rails API
├── proto/ # Protocol Buffer definitions (buf + ts-proto)
├── specs/ # Feature specifications
├── docs/ # Documentation
├── .claude/ # Claude Code skills and commands
├── CLAUDE.md # Repository instructions for Claude Code
└── docker-compose.yml # Docker + PostgreSQL setup
- Node.js (v18+)
- Python 3.12+ and uv (for the FastAPI implementation)
- Go 1.24+ (for the Go Gin API implementation) — ensure
$(go env GOPATH)/bin(typically~/go/bin) appears in yourPATHbefore system package manager paths so locally-installed Go tools (govulncheck,gotestsum) take precedence - Java 21 (for the Spring Boot implementation) — Eclipse Temurin is recommended:
brew install --cask temurin@21 - Ruby 3.3+ and Bundler (for the Rails API implementation)
- Docker and Docker Compose (for PostgreSQL)
- tbls (optional, for regenerating schema docs):
brew install tbls
-
Clone the repository:
git clone https://github.com/WhatIfWeDigDeeper/application-tracker.git cd application-tracker -
Install dependencies for all implementations:
npm run ci:all
-
Start PostgreSQL:
docker-compose up -d postgres
-
Run database migrations for each implementation you intend to use:
npm run migrate:express # Express + Prisma npm run migrate:koa-api # Koa (raw SQL) npm run migrate:hono-api # Hono + Drizzle npm run migrate:nuxt-api # Nuxt + Drizzle npm run migrate:nest-api # NestJS + Drizzle npm run migrate:nest-history-api # NestJS gRPC History Service (Knex) npm run migrate:fastapi # FastAPI (asyncpg) npm run migrate:go # Go Gin API (raw SQL) npm run migrate:spring-api # Spring Boot API (Flyway — auto-run on startup too) npm run migrate:rails-api # Rails API (ActiveRecord migrations) # or all at once: npm run migrate:all
Each implementation can be run independently:
# Next.js + Express (UI 3000 + API 3001)
npm run dev:react-next-ui
npm run dev:express-api
# React + Koa (UI 3010 + API 5010)
npm run dev:react-ui
npm run dev:koa-api
# Vue + Nuxt (UI 3020 + API 5040)
npm run dev:vue-ui
npm run dev:nuxt-api
# Svelte + Hono (UI 3030 + API 5030)
npm run dev:svelte-ui
npm run dev:hono-api
# React + TanStack + NestJS (UI 3050 + API 5050 + gRPC History 50051)
npm run dev:nest-history-api # start gRPC history microservice first
npm run dev:nest-api
npm run dev:tanstack-ui
# React SSR + TanStack Start + FastAPI (UI 3040 + API 5160)
npm run dev:tanstack-start-ui
npm run dev:fastapi
# Angular + Go Gin (UI 3060 + API 5070)
npm run dev:go-api
npm run dev:angular-ui
# Angular + Spring Boot (UI 3070 + API 8080)
npm run dev:spring-api
npm run dev:angular-spring-ui
# Lambda + DynamoDB (API only — port 5090)
# Requires DynamoDB Local: docker compose up -d dynamodb-local
cp lambda-api/.env.example lambda-api/.env # sets DYNAMODB_ENDPOINT/local AWS creds for DynamoDB Local
npm run migrate:lambda-api # create/update DynamoDB table
npm run dev:lambda-api # start Hono server on port 5090
# Lambda React UI + Lambda API (UI 3090 + API 5090)
npm run dev:lambda-api
npm run dev:lambda-react-ui
# Ruby on Rails API (API only — port 5180)
npm run dev:rails-api
# CDK — synthesize / deploy (real AWS or LocalStack)
npm run cdk:synth # synthesize CloudFormation template (no AWS needed)
npm run cdk:deploy # deploy to real AWS
docker compose --profile localstack up -d localstack # start LocalStack (opt-in)
npm run cdk:deploy:local # deploy to LocalStackRegenerate database ERD docs after schema changes (requires tbls and a running PostgreSQL instance):
npm run docs:schemaThis generates Mermaid ERDs and per-table documentation under docs/schema/ for each implementation schema.
Run tests for individual implementations:
npm run test:express-api # Express + Prisma API tests
npm run test:react-next-ui # Next.js UI tests
npm run test:koa-api # Koa API tests
npm run test:react-ui # React UI tests
npm run test:svelte-ui # Svelte UI tests
npm run test:vue-ui # Vue UI tests
npm run test:nest-api # NestJS API tests
npm run test:tanstack-ui # TanStack UI tests
npm run test:tanstack-start-ui # TanStack Start UI tests
npm run test:fastapi # FastAPI pytest unit tests
npm run test:go-api # Go Gin API integration tests (testcontainers-go)
npm run test:angular-ui # Angular UI tests (Jest + @testing-library/angular)
npm run test:spring-api # Spring Boot API tests (JUnit 5)
npm run test:angular-spring-ui # Angular Spring UI tests (Jest + @testing-library/angular)
npm run test:lambda-api # Lambda + DynamoDB unit tests (vitest, no Docker needed)
npm run test:lambda-react-ui # Lambda React UI tests (Vitest + Testing Library)
npm run test:lambda-api-cdk # CDK assertions tests (vitest, no Docker needed)
npm run test:rails-api # Rails API tests (RSpec)Run all unit tests:
npm run test:all # Run all implementation testsCross-stack API tests run Jest integration tests against each REST API backend. Implementations are tested with a shared test suite covering CRUD, date formats, CSV import/export for CSV-capable stacks, history, and application status.
Run tests for a single API (requires the API server to be running):
npm run test:api:express-api # Express + Prisma API (port 3001)
npm run test:api:koa-api # Koa API (port 5010)
npm run test:api:nuxt-api # Nuxt server API (port 5040)
npm run test:api:hono-api # Hono API (port 5030)
npm run test:api:fastapi # FastAPI (port 5160)
npm run test:api:nest-api # NestJS API (port 5050)
npm run test:api:go-api # Go Gin API (port 5070)
npm run test:api:spring-api # Spring Boot API (port 8080)
npm run test:api:yoga-api # GraphQL Yoga REST API (port 5080)
npm run test:api:lambda-api # Lambda + DynamoDB API (port 5090)
npm run test:api:rails-api # Rails API (port 5180)Run all API tests with automatic server lifecycle management:
npm run test:api:all # Start all APIs, run tests, stop APIs
# or
bash scripts/run-api-tests.shE2E tests use Playwright and run against each implementation:
npm run test:e2e:react-next-ui # Next.js + Express (port 3000)
npm run test:e2e:react-ui # React + Koa (port 3010)
npm run test:e2e:vue-ui # Vue + Nuxt (port 3020)
npm run test:e2e:svelte-ui # Svelte + Hono (port 3030)
npm run test:e2e:tanstack-start-ui # React SSR + TanStack Start + FastAPI (port 3040)
npm run test:e2e:tanstack-ui # React + TanStack + NestJS (port 3050)
npm run test:e2e:angular-ui # Angular + Go Gin (port 3060)
npm run test:e2e:angular-spring-ui # Angular + Spring Boot (port 3070)
npm run test:e2e:lambda-react-ui # Lambda React UI + Lambda API (port 3090)
npm run test:e2e:all # Run all e2e testsTo clean up leftover test data from interrupted runs, see Test Data Cleanup.
To remove orphaned Docker containers left behind by Go test runs (TESTCONTAINERS_RYUK_DISABLED=true), run npm run cleanup:docker.
Build all implementations:
npm run build:all # Build all implementationsRun the full validation chain (install → audit → lint → build → migrate → test) for a single stack:
npm run validate:tanstack-ui # install → audit:ci → lint → build → migrate (--if-present) → test
npm run validate:express-api
npm run validate:nest-history-api
# ... validate:<stack> available for all stacksRun everything across all stacks:
npm run validate:allThe Claude Code Review workflow (claude-code-review) is triggered manually — it does not run automatically on pull requests. To run it, go to Actions → Claude Code Review → Run workflow and enter the PR number.
This repository includes Claude Code commands and skills for common development tasks:
/commit- Generate commit messages/pr- Create pull requests/fix-build- Fix build errors
Skills installed from WhatIfWeDigDeeper/agent-skills:
| Skill | Description |
|---|---|
js-deps |
Update npm dependencies and/or fix audit errors |
uv-deps |
Audit and update Python dependencies |
ship-it |
Branch, commit, push, and open a PR |
pr-comments |
Address review comments on a pull request |
vercel-react-best-practices |
React/Next.js performance optimization guidelines from Vercel Engineering |
mermaid-diagrams |
Generate Mermaid diagrams (flowcharts, sequence, ERD, C4, and more) |
Since npx skills check and npx skills update apparently do not work with the above repo at this time, you may force update all skills:
npx skills add -y https://github.com/whatifwedigdeeper/agent-skillsOther skills
npx skills add -y https://github.com/microsoft/playwright-cli --skill playwright-clinpx skills add -y https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practicesSee .claude/ for all available commands and skills.
.vscode/launch.json includes debug configurations for all API backends. Open the Run and Debug panel (Ctrl+Shift+D / Cmd+Shift+D) and select the server you want to debug:
| Configuration | Port |
|---|---|
| Express API | 5000 |
| Koa API | 5010 |
| Hono API | 5030 |
| Nuxt API | 5040 |
| NestJS API | 5050 |
| FastAPI | 5160 |
| Go Gin API | 5070 |
FastAPI debugging requires the Python extension. Go debugging requires the Go extension.
Claude Code hooks in .claude/settings.json send macOS notifications when Claude needs input (permission prompts, questions, idle). This requires terminal-notifier:
brew install terminal-notifierAfter installing, grant notification permissions so alerts appear:
System Settings → Notifications → terminal-notifier → Allow Notifications
No other configuration needed — the hooks are already in .claude/settings.json. If you don't install it, hooks fail silently with no impact.
MIT