Red Hat · System Architecture

One click in, one satirical resume out

The whole path a request took, from the persona picker in the browser down to the structured model call and back up as rendered markdown.

01Browser

React SPA web/dist

A single form: pick a persona, a domain, one or more inspiration themes, the struggles the applicant has heroically overcome, and contact details.

HTTPS
02Edge

nginx

TLS via certbot, reverse proxy to the app server. Nothing clever — it just had to not fall over at a birthday party.

proxy_pass
03API
FastAPI

Middleware — rate limit 5 req / 5 min per IP · security headers · request-id logging

GET /api/themes

Inspiration packs.

GET /api/challenges

Struggle options.

POST /api/resume/generate

The one that matters.

GET /{path}

SPA fallback to index.html; 404s under api/*.

generate
04Content
data/

themes/*.yaml

InspirationPack: label, brief, exemplars, keyword hints. Hand-written — this is where the actual joke lives.

challenges.yaml

The adversity catalogue.

load_themes → sample_content → ContentKit
05Generation
core/

Prompt assembly — split so the expensive half never changes

system prompt static

get_system_prompt_structured plus tone instructions from the dial. Identical on every request, so it sits at the front as a cacheable prefix.

user prompt dynamic

make_user_prompt_structured — persona, domain, sampled exemplars, struggles, contact.

StructuredResumeGenerator

chat.completions.parse with response_format=ResumeGenerationOutput — a schema, not a prose blob. Returns summary, skills, experience.

Model and reasoning settings come from config.py (there was a fast mode for the live demo).

educational_planner no LLM

build_education runs off a SHA-256 seeded RNG. Degrees, certifications and awards are deterministic — same inputs, same credentials, every time.

ResumeModel → render_markdown

Model output and planned credentials merge into one typed object, then render to markdown.

↯ fallback path

On a refusal, a length stop, a content filter, or a dead API, _create_fallback_resume builds one straight from the theme exemplars. The page never showed an error — it just got funnier and less specific.

Every call logged through log_openai_usage — model, tokens, duration, cost

Response
ResumeGenerateResponse structured resume + rendered markdown, back to the SPA
request path deterministic, no model call degraded / fallback cached or returned