Applog AI: A Job Tracker That Updates Itself

The data was already in my inboxโ€ฆ I just stopped copying it by hand.

Applog AI: A Job Tracker That Updates Itself

The data was already in my inboxโ€ฆ I just stopped copying it by hand.

AppLog AI grew out of a constant everyday frustration in my job search process, and a desire to save time, work smarter, and build my AI skills in the process.

Why the need from 2D -> 3D?

Skills

UX & Systems design

AI-assisted development

Full-stack build

Iterative testing

My Role

Solo designer, researcher, builder

Tools

Frontend: React, Vite, Tailwind CSS

Backend: Node.js, Express

Infrastructure: Supabase (Postgres), Render, GitHub Actions (CI/CD)

AI integration: Claude, Model Context Protocol (MCP), Gmail API

Industry

Personal productivity tool

Problem

After hundreds of job applications, my tracking spreadsheet had become its own part-time job.

Tools like Excel, Google Sheets, Teal, Huntr organize beautifully, but I still either enter or update everything by hand.

Existing tools meant to give me clarity had become another chore.

Existing tools meant to give me clarity had become another chore.

My motivation for this project

Personal frustration

No automation meant I had to manually track application data -> extremely time-consuming.

I wanted to maximize my application volume. Each day.

And learning how to build with AI.

So I made a betโ€ฆ

ONE guiding principle, ONE thing I'd measure every decision against:

A tracker is only worth building if it updates itself. Otherwise it's just a spreadsheet.

A tracker is only worth building if it updates itself. Otherwise it's just a spreadsheet.

Terminal CLI triggers run

AppLog portal receives live updates

So, what is AppLog AI?

A smart, LLM-powered tracker I built to read the job-application emails that matter โ€” confirmations, interviews, rejections, or the silence of being ghosted. Instead of manually checking and updating each one, I type a single command and it reads my inbox and updates everything itself.

Almost like a personal assistant who watches my inbox and manages the tracking.

On the ambiguous cases โ€” a merge that isn't clear-cut โ€” it pauses and asks me to make the call.

One command

CLI

Reads my inbox

Gmail API

Extracts details

LLM parser

Asks me when unsure

human-in-the-loop review

Stores data

Supabase / Postgres

Updates live

React portal

Constraints

Why the need from 2D -> 3D?

These came before the process, because they were the lens on it.

Solo, by design

No engineer co-parts. I was designer, builder, and tester at once.

The ceiling

No system can extract a company name that appears in none of the emails. Some applications are genuinely unrecoverable by machine โ€” a limit I had to design around, not engineer away.

Real data == real stakes

A wrong merge wasn't a bug, it was a job I'd never know I lost.

The Process

Swipe -> to view the timeline of this project

Build a MVP.

Test with real data.

Then iterate.

Repeat.

I made a scrappy version fast.

Rough kanban portal, containing:

LocalStorage: application data on my computer only.

Columns to sort applications by where each one stood.

The email parser

Pulled company, role, and status out of my Gmail โ€” the piece meant to replace manual data entry.

Database setup via Supabase

The permanent home for every application row, so the data could live somewhere real instead of one browser.

Express API on Render

The middleman that let the portal and the parser read from and write to that database.

Backups + approval gates

A safety net so I could break things and roll back without fear โ€” built in first, before anything risky.

332 real application emails.

I was my own user: n=1, I learned by building.

It was the usability test.

Then it brokeโ€ฆ

It "failed" in the most useful way.

120+ applications came back blank, and others came back confidently wrong

How it broke

What the parser saw

Input

Globalhr@myworkday.com

(No employer anywhere in email)

Sender display name: "System System"

The raw signals it tripped on

What it returned (wrong)

Output

Globalhr

Unspecified

System System

not the company

employer unidentified

sender scraps

The junk it produced

Why?

Why the need from 2D -> 3D?

The parser I designed read the "envelope", not the "letter".

Email domains were parsed as company names.

Sender fragments (AI-generated) were also read as employers.

This informed my next step

It became clear to me that I needed to address the gap between how I designed the labeling and how the system actually behaved. Two fixes mattered the most.

It became clear to me that I needed to address the gap between how I designed the labeling and how the system actually behaved. Two fixes mattered the most.

Iteration #1

The reqID veto

Finding

My dedup logic saw 2 different roles at the same company as identical and silently merged them, with no flags raised.


After investigating, the only thing telling them apart was a requisition ID buried in the job listing.

Decision

For my parser moving forward, I made the reqID a deciding factor: different IDs = "separate applications, never merge".


The reqID now has vetoing power to override the previous parser logic.

Why this design

A tracker that quietly hides a real data point loses my trust.


I'd rather err toward keeping 2 rows that might be duplicates (which I can clean up later), than merging 2 that can cause invisible loss.

Before - merged into one row

After - all 3 rows preserved

Iteration #2

Hitting the parser ceiling

Finding

Some emails name no employer anywhere (not in subject, sender, or email body).


Parser cannot extract what isn't there. I'd hit a limit that more engineering couldn't cross.

Decision

Creating a watermark / an improved parser that runs a complete pipeline:


  1. Have LLM flag the few ceiling cases ->

  2. I hand-review and correct them ->

  3. Only new mail syncs moving forward.

Why this design

The improved parser runs efficiently, with my approval on the calls that matter, and never re-fights corrections I've already made.

Before - parser hit the ceiling

There was nothing to extract - employer is named nowhere in the email

After - corrected by hand

The watermark keeps the parser from ever overwriting it

Reflections

This is an ongoing project (summer '26), but the payoff has been tremendous.

Learned how to build

Beyond UX design, but to think in layers. Frontend, backend, database, pipeline. How each depends on another and the way an engineer scopes a system before touching code.

Built a tool I'll actually use

It saves real time in my job search, and the systems thinking transfers to any team where I'm the designer working alongside engineers.

Learned to stop at "trustworthy," not "perfect"

Chasing the last few unrecoverable rows would've cost days for no real gain. Having the discipline to stop is its own skill.

Did the bet pay off?

You betcha! I initiate the portal via CLI, and the data's immediately synced.

You betcha! I initiate the portal via CLI, and the data's immediately synced.

Let's link up

Drop a DM here ๐Ÿ‘‡๐Ÿผ

Designed with intent, curiosity, and liters of Genmaicha

2026 Jessica Yu

Let's link up

Drop a DM here ๐Ÿ‘‡๐Ÿผ

Designed with intent, curiosity, and liters of Genmaicha

2026 Jessica Yu

Let's link up

Drop a DM here ๐Ÿ‘‡๐Ÿผ

Designed with intent, curiosity, and liters of Genmaicha

2026 Jessica Yu