Leonard Surac

Back to the start page

Live · since 2026

surac.dev

A CV does not show how I work. So I built this website as a work sample: open in the code, with application links and a CV PDF from the same data.

ASP.NET Core 10 · EF Core · Angular 22 SSR · PostgreSQL · QuestPDF · Playwright · Docker

Problem

When I apply, I send a PDF, and it says nothing about how I build software. I wanted a page a recruiter takes in within half a minute and that shows an engineer in the code how it was built.

My role

I did everything myself: concept, test-driven development with AI agents under written rules, operations with staging and production.

Case study

My solution

One website for two readers: at the top what recruiters look for (role, stack, CV, contact), below it the depth for engineers. I render the CV from the same data as a PDF so two versions never drift apart.

  • Application links with three audience profiles that change the order, never the content
  • Certificates and cover letters unlocked per link, the full PDF with phone and address only there
  • Statistics on views and response rate, without storing anything about visitors
  • German and English complete, maintained side by side in the admin

Implementation

Everything is built with ASP.NET Core, EF Core, PostgreSQL and Angular with server-side rendering; QuestPDF renders the CV. An application link is a capability URL: 128 random bits, only the hash is stored.

SuracDev.Api/Domains/Applications/Domain/ApplicationLink.cs
public static (string Token, string Hash) Generate()
{
  var token = Base64Url(RandomNumberGenerator.GetBytes(TokenBytes));
  return (token, Hash(token));
}

public static string Hash(string token)
  => Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(token)));

The rules the agents and I work by are in AGENTS.md; every decision with its trade-off in docs/decisions.md.

Decisions

DDD-light instead of ceremony
I organise by domain, entities protect their own rules, and value objects exist only where they prevent bugs. I left out repositories, MediatR and CQRS on purpose: for a handful of entities they would gain nothing.
A profile changes the order, never the content
Application links reorder the sections for recruiters or tech leads but never add or hide anything. I give up tailoring so that nothing looks manipulated when two readers compare.
I verify the PDF as text
Instead of a headless browser I use QuestPDF, and my tests compare the text an applicant tracking system reads from the PDF. Stable on every machine, but the layout is not checked.

Outcome

The repository is public with more than 90 % test coverage in the API. For every application I create a link of its own with a fitting order, see when it is opened and get reminded of open applications on Mondays. Lighthouse: accessibility and SEO 100.