Skip to content
Duku Constantin

Case study / 2026

Nyra

A small business tracked job candidates in spreadsheets and email, and someone copied each CV by hand.

I built one tool where CVs are uploaded and read automatically.

Every candidate shows up in one table or board, with notes, search and export.

Duplicates are caught, every change is logged, and personal data is kept only as long as the business decides and erased on request.

Role
Designed and built the application.
  • Next.js
  • TypeScript
  • Supabase
  • Python
  • FastAPI
  • LlamaParse
Private repositorynyra.joben.eu ↗
Nyra homepage
  1. Problem
  2. What was missing
  3. How I investigated
  4. What I built
  5. Result

01

Problem

A small business tracked job candidates in spreadsheets and email. CVs arrived as files. Someone opened each one and copied the details by hand.

02

What was missing

There was no single place for candidates. The same person could show up twice. Nobody could see who changed a record.

Candidate data is personal data. The business needs to control how long it keeps that data and to erase it on request.

03

How I investigated

I started from how the business works: one company, a small team, and a first version that had to stay simple.

Reading CVs is the risky part, because it depends on an outside service that can be slow or fail. I kept it apart from the rest of the application so a failure there stays contained.

04

What I built

The tool reads each uploaded CV and fills in the contact details and work history.

When something looks wrong, it marks the candidate for review. A person's edits are never overwritten.

Duplicate candidates are matched, and an admin merges them without losing notes or tags.

Every change is logged, and the log cannot be edited, even by admins. The business sets how long personal data is kept, and any candidate can be exported or erased.

+ Technical details

Parsing runs as a separate Python service. A job is claimed once, retried three times with backoff, and a sweeper picks up jobs that got stuck.

Extracted fields are checked and normalized. Anomalies mark the candidate for review. Fields a person edited are not overwritten when a CV is reprocessed.

Duplicates match on file hash, email or phone. A merge runs in one database transaction that keeps experiences, notes and tags.

The audit log is append-only and written by database triggers. It masks personal data. Each organization sets a retention period, and expired candidates are purged.

Data is separated per organization from the first migration, and the interface serves one organization.

Database tests run on Postgres compiled to WASM with every migration applied. CI runs lint, types, database tests, the build and the parser tests.

05

Result

A candidate table and board with keyword search, notes, CSV export and an inline CV viewer.

The repository is private.

← All work