Commit graph

14 commits

Author SHA1 Message Date
5890f2bbf7 docs: rename to Job Tracker and add architecture + lifecycle diagrams
- Renamed the H1 from 'Job Agent' to 'Job Tracker' to match the published
  repo name.
- Added two Mermaid diagrams up front under 'How it works':
  - Architecture diagram: Next.js (RSC + API) ↔ Postgres+pgvector ↔
    Claude CLI ↔ local embedder, with HNSW cosine retrieval and the
    storage/ folder for uploads + generated PDFs.
  - Lifecycle diagram: end-to-end flow from profile setup → application
    creation → auto-indexing → generation (CV / cover letter / interview
    prep / emails) → review with ATS scoring → approve → pipeline tracking
    with unified feed, contacts, and per-company research → outcome →
    feedback loop that reindexes positive outcomes for future RAG
    retrieval.

Both Gitea and GitHub render Mermaid natively in markdown.
2026-05-24 20:59:58 +01:00
a0c37d4201 chore: ignore .claude/ workspace (Claude Code local state) 2026-05-24 20:56:31 +01:00
aaca118a11 docs: rewrite README to reflect current state (Postgres + pgvector, raio-x, contacts, AI suite)
Old README documented the pre-migration SQLite setup and was missing most
of the features added since: contacts CRUD with M:N junction, per-company
research, unified event feed, AI features (interview prep, email gen, ATS),
configurable system prompts, raio-x application detail view.

New README is bilingual at the top (EN+PT short description), then
English-only detailed sections: features by category, tech stack, quick
start with Docker, usage walkthrough, project structure, API reference,
RAG architecture, configurable prompts, data migration paths.
2026-05-24 20:50:22 +01:00
f212667b7d fix(db): drop deprecated contact.application_id from schema
The contact_application junction commit (1d0235a) had already dropped the
deprecated applicationId column from the live DB via migration 0001, but
schema.ts was left with the column declaration (it was put back temporarily
during commit preparation to keep schema.ts consistent with 0000_init.sql,
then never re-removed for the junction commit). This caused Drizzle to
generate INSERTs against a non-existent column when creating contacts.

Schema.ts now matches the live DB; no migration needed (0001 already
dropped the column).
2026-05-24 20:50:12 +01:00
86c8f0b255 feat(contacts): inline edit + company autocomplete (auto-creates new companies)
- Pencil icon on each contact card opens inline edit reusing the same field
  set as the create form (extracted ContactFields sub-component).
- Company field on the form is a free-text input backed by a <datalist> of
  existing companies (fetched from a new GET /api/companies endpoint). Pick
  an existing company or type a new name — the contacts API resolves
  companyName via findOrCreateCompany, so brand-new companies get created
  on the fly without needing to add a phantom application first.
2026-05-24 20:50:05 +01:00
86f06a44eb fix(ui): force light mode, add bg-white + text-zinc-900 to inputs, polish funnel
The globals.css had a dark-mode media query that flipped the body to a dark
background, but the rest of the UI was authored light-only — inputs without
an explicit bg-white inherited the dark background and the new text-zinc-900
made typed text invisible. Removed the dark-mode override, declared
color-scheme: light on :root to opt out of UA dark form styling, and added
bg-white + text-zinc-900 placeholder:text-zinc-400 explicitly to every
input/textarea/select.

Also bumped 45 label and section-heading patterns from text-zinc-700 to
text-zinc-800 (slightly stronger), and PageShell h1 / StatCard values to
text-zinc-900 for better hierarchy.

Funnel chart: replaced a brief SVG trapezoid experiment with the bar-chart
form (more legible at small sizes), but kept the new semaphore coloring for
conversion rates (green >=50%, amber 25-49%, red <25%).
2026-05-24 20:49:56 +01:00
48eab35ac6 feat: unified event feed + company research (API + raio-x UI)
The application detail page becomes a "raio-x" view of the role: one
timeline that mixes status changes, interview stages, free-form notes,
and contact interactions; plus per-company research notes and a list of
other applications at the same company so you can see your history with
each employer at a glance.

API:
- POST/PATCH/DELETE /api/applications/[id]/events for note / stage /
  contact_interaction events on the unified feed.
- POST/DELETE /api/applications/[id]/contacts to link an existing contact
  to an application (optionally with a per-application role).
- GET/POST /api/companies/[id]/research and PATCH/DELETE on the singular
  resource for per-company research notes (news, culture, tech_stack,
  glassdoor, interview_experience, compensation, general).
- getApplicationById extended to bundle contacts, companyResearch, and
  relatedApplications in the same response so the page loads in one fetch.

UI (src/app/applications/[id]/page.tsx):
- FeedPanel replaces the old timeline: per-type icons/colors, inline
  composer with type-specific fields (date+outcome for stages, contact
  picker for interactions).
- ContactsPanel lists linked contacts and lets you link more via the
  composer; pulls /api/contacts and excludes already-linked ones.
- ResearchPanel for per-company research entries (type chip, source URL,
  markdown content).
- RelatedAppsPanel showing other applications at the same company.
2026-05-24 11:33:53 +01:00
f931200f58 feat: contacts CRUD using contact_application junction
Contacts (recruiters, interviewers, hiring managers, referrers) live in
their own table with N:M to applications via contact_application, so the
same recruiter can be linked to every role they've put me in front of —
this is the foundation for a networking view across companies.

- /api/contacts: list / create / update / delete contacts (grouped by
  company on the UI side).
- Query layer adds linkContactToApplication (ON CONFLICT updates the
  junction role for re-links) and unlinkContactFromApplication.
- getContactsByApplication joins through the junction and surfaces both
  the contact's general role and the per-application junction role
  (e.g. someone could be a "Recruiter" in general but "Hiring manager"
  for a specific opening).
- /contacts page lists every contact grouped by company — the starting
  point for the networking graph.
2026-05-24 11:33:38 +01:00
b15c681092 feat: reminders, dashboard widgets, sidebar nav, reusable application form
- /api/reminders endpoint and reminder query layer: create due/upcoming
  follow-ups, mark complete/delete, plus createAutoReminders that fires
  the right reminder type when an application transitions to applied /
  interview / offer.
- Dashboard (src/app/page.tsx) shows due reminders, stale applications,
  drafts awaiting send, response-rate by job-board domain, time-in-stage,
  weekly velocity, CV performance — the data already flows from
  getDashboardStats.
- Sidebar gains Contacts and Settings entries.
- application-form.tsx extracted so /applications/new and the edit flow
  on the detail page share one form component instead of duplicating
  field/validation logic.
2026-05-24 11:33:25 +01:00
59eeba4643 feat: AI features — interview prep, email generation, ATS keyword analysis
- POST /api/applications/[id]/interview-prep generates STAR-format prep
  material from the candidate's experience.
- POST /api/applications/[id]/generate-email writes follow-up, thank-you,
  and withdrawal emails grounded in the application context.
- GET/POST /api/applications/[id]/keywords extracts ATS-relevant terms
  from the job description and scores a CV against them (TF-IDF style
  scoring, bigram detection, ATS compatibility scoring with formatting
  checks).
- generate-cv now feeds the top extracted keywords into the CV prompt so
  the output stays ATS-aligned, and returns the keyword analysis plus
  ATS score in the response.
- Configurable system prompts (per generation type) stored in the
  prompt_config table, editable via /settings; defaults shipped in
  src/db/queries/prompt-configs.ts and seeded on first read.
2026-05-24 11:33:09 +01:00
0fee844c7a chore(db): migrate from SQLite to Postgres with pgvector
Switch the persistence layer from better-sqlite3 to postgres-js (async),
rewrite the schema in drizzle-orm/pg-core, and add Docker + scripts to
spin up Postgres 16 with pgvector locally on port 5433.

Schema changes beyond the SQLite → PG dialect swap:
- embedding_chunk.embedding becomes vector(384) with an HNSW cosine index,
  enabling native similarity search via the `<=>` operator (no more
  JSON-serialized arrays + JS-side cosine).
- jsonb for previously-text JSON columns (achievements, content_structured,
  metadata).
- application_event generalised into a unified activity feed: adds
  event_type, title, contact_id, scheduled_at, completed_at, outcome.
- New tables: contact_application (M:N junction so a recruiter can appear
  in multiple applications) and company_research (per-company knowledge log).

Driver swap touches every query call site: all functions in src/db/queries
are now async, and all callers in src/app/api/**/*.ts and src/lib/{rag,claude}
await accordingly. SQLite-specific SQL (julianday, date('now', ...))
translated to Postgres equivalents (extract(epoch ...), current_date,
date_trunc('week', ...)).

Includes scripts/dump-sqlite.mjs and scripts/restore-postgres.mjs to migrate
existing data (run once: dump from old .db, then restore into the running
PG container).
2026-05-24 11:32:55 +01:00
1e52426347 feat: add RAG system, improve dashboard charts, and rewrite README
- Implement RAG (Retrieval-Augmented Generation) with local embeddings
  (all-MiniLM-L6-v2 via @huggingface/transformers) for semantic search
  over documents, experiences, job descriptions, and past generations
- Add embedding_chunk table with Drizzle migration
- Auto-index on document upload, experience CRUD, application creation,
  and positive feedback; manual reindex via API/UI
- Integrate RAG retrieval into CV/CL generation context builder with
  fallback to legacy concatenation when index is empty
- Redesign dashboard: application funnel, daily activity heatmap,
  weekly bar chart, stacked pipeline breakdown, avg response time card
- Add RAG index status panel and rebuild button to Knowledge Base page
- Rewrite README with full project documentation
2026-04-07 18:18:09 +01:00
Richard Nixon
1598949d17 feat: implement job application management system (phases 1-6)
Complete personal job application management system with:
- Profile management (education, experience, skills, documents)
- Application tracking with status workflow and timeline
- CV and cover letter generation via Claude CLI (claude -p)
- Knowledge base with feedback loop for generation improvement
- Interactive dashboard with stats, charts, and activity feed
- SQLite database with 13 tables via Drizzle ORM (WAL mode)
- File upload with PDF/DOCX/TXT parsing

Stack: Next.js 16, React 19, TypeScript, Tailwind CSS, shadcn/ui,
better-sqlite3, Drizzle ORM, @react-pdf/renderer, Zod validation.
2026-03-20 13:50:27 +00:00
Richard Nixon
59a2c0eafc Initial commit from Create Next App 2026-03-20 12:00:38 +00:00