The Vision: Beyond Spreadsheets for Job Hunting
Tracking dozens of job applications across static spreadsheets, notes, and emails quickly deteriorates into chaos. When I built CareerTrack, my goal was to engineer a high-performance full-stack workflow system combining interactive Kanban pipelines, resume versioning, interview prep banks, and multi-provider AI assistance (OpenAI, Claude, and Gemini).
"Modern web applications aren't just CRUD interfaces with nice CSS. They demand type-safe full-stack pipelines, deterministic data mutation patterns, and sub-100ms UI responsiveness across complex client interactions."
Full-Stack Type Safety
CareerTrack leverages TypeScript end-to-end: from PostgreSQL tables defined in Prisma schema to React Server Actions and optimistic client state hooks.
CareerTrack platform interface: pipeline tracking, AI JD matching, and full-stack application lifecycle management.
Critical Problems Faced & Bottlenecks
1. Cascading SQL Re-indexing on Drag
Using integer order indexes (1, 2, 3) caused dragging an item to the top of a 200-application column to trigger 200 individual SQL UPDATE queries, spiking database CPU.
2. 6-Second Blocking LLM Latency
Standard REST POST requests for job description gap analysis forced users to stare at a frozen spinner for 5 to 7 seconds while the LLM generated complete JSON schemas.
3. Multi-Tenant API Key Security
Allowing users to connect their own OpenAI/Anthropic/Gemini keys required zero-knowledge cryptographic storage to guarantee no credentials could be leaked or logged.
4. Mobile Drag-and-Drop Glitches
Standard HTML5 drag-and-drop failed completely on mobile touch screens, causing cards to get stuck midway and trigger accidental page reloads.
How I Solved Them: Fractional Indexing & AI Streaming
1. O(1) Fractional Order Indexing
I switched order indexes from integer arrays to floating point values: newOrder = (prev.order + next.order) / 2. Dropping a card between items requires only 1 single atomic SQL query regardless of how many thousands of applications exist in the column.
2. Vercel AI SDK Token Streaming (SSE)
I refactored the JD analysis endpoint into a streaming Route Handler using Server-Sent Events. Initial tokens appear in under 280ms, making the AI analysis feel instant and dynamic.
3. AES-256-GCM Secure Key Isolation
Custom user LLM keys are encrypted using symmetric AES-256-GCM keys tied to user Clerk tokens. Decryption occurs strictly in-memory during request execution and is never written to disk logs.
The Kanban board: optimistic status updates, salary benchmarks, and tag filtering with fractional indexing.
Building the Drag-and-Drop Kanban Pipeline
"use server";
import { z } from "zod";
import { prisma } from "@/lib/prisma";
import { auth } from "@clerk/nextjs/server";
import { revalidatePath } from "next/cache";
const UpdateStageSchema = z.object({
applicationId: z.string().cuid(),
newStatus: z.enum(["APPLIED", "SCREENING", "INTERVIEWING", "OFFER", "REJECTED"]),
prevOrder: z.number().optional(),
nextOrder: z.number().optional(),
});
export async function updateApplicationStage(data: z.infer) {
const { userId } = await auth();
if (!userId) throw new Error("Unauthorized");
const validated = UpdateStageSchema.parse(data);
// Compute fractional order index to avoid cascading row updates
let newOrder: number;
if (validated.prevOrder !== undefined && validated.nextOrder !== undefined) {
newOrder = (validated.prevOrder + validated.nextOrder) / 2;
} else if (validated.prevOrder !== undefined) {
newOrder = validated.prevOrder + 1000;
} else if (validated.nextOrder !== undefined) {
newOrder = validated.nextOrder / 2;
} else {
newOrder = 1000;
}
const updated = await prisma.jobApplication.update({
where: { id: validated.applicationId, userId },
data: { status: validated.newStatus, orderIndex: newOrder },
});
revalidatePath("/applications");
return { success: true, item: updated };
}
Multi-Provider AI Assistant Integration
AI provider settings: model selection, custom temperature parameters, and encrypted API key management.
Data Modeling with Prisma and PostgreSQL
The relational schema connects User, JobApplication, InterviewStage, Note, and ResumeSnapshot with composite indexes on [userId, status] for instant sub-5ms filtering across heavy datasets.
New Skills & Production Insights Gained
1. Optimistic UI Mutations
I mastered optimistic state reconciliation in React 19: updating the visual DOM immediately while server actions reconcile asynchronously in the background.
2. End-to-End Type Contracts
Coupling Prisma database schemas directly with Zod validators eliminated an entire class of runtime regressions before code ever hit production.
Building CareerTrack proved that thoughtful full-stack engineering transforms a tedious process into an empowering, lightning-fast experience.

