How Lamr works
Lamr tailors your resume and cover letter to a specific job with AI, then helps you track the application through to an offer. This page is the honest, technical version of what actually happens under the hood — written for developers, skeptics, and anyone who wants more than marketing copy before trusting a tool with their job search.
Overview
You paste (or link) a job description, Lamr tailors a resume and cover letter against your own master resume, and the application moves through a simple pipeline: draft → applied → interview → offer. Everything else in the product — screening, fit scoring, interview prep, application tracking — exists to make that one core loop faster and more honest.
The guiding rule behind almost every design decision below: optimize how something is said, never what actually happened. Wording, emphasis, and keyword coverage are fair game for AI to improve aggressively. Facts — job titles, dates, metrics, credentials — are not.
How tailoring works
Tailoring runs on Claude Sonnet 5. A separate, smaller pass (Claude Haiku 4.5) handles cheap, mechanical fixups — trimming a bullet that ran long, tightening a tagline — so the expensive model isn't re-invoked for small corrections.
The truth contract
The system prompt tells the model explicitly not to invent a number, employer, credential, or job title that isn't already in your master resume. That instruction alone isn't trusted — a separate, fully deterministic check (plain pattern matching, no AI involved) scans every generated summary and bullet afterward for any number that doesn't trace back to your own source material, and flags it if one shows up. Employment titles, dates, and education are restored from your original data after generation rather than left to the model's discretion.
What actually gets rewritten
Within those limits, tailoring is genuinely aggressive: bullets get reordered within a role to lead with what's most relevant to the posting, wording is rewritten to mirror the job description's own language, and a summary is written fresh for that specific role. You control how far this goes — a rewrite-intensity dial (light / balanced / aggressive), a summary-length preference, and an optional one-line-per-bullet formatting rule are all yours to set, and none of them change the truth contract.
Keyword coverage, measured not assumed
An instruction to "cover the job's key skills" is not the same as actually covering them. After generation, Lamr checks — deterministically — what fraction of the posting's extracted hard skills actually appear in the output, and will add back a skill that's provably true (present in your master resume) but got dropped, rather than just hoping the model included it.
Fit scoring
Asking a language model directly for a single 0–100 "how good is this fit" score produces a very narrow, unhelpful range in practice — most jobs cluster around the same middling number regardless of how different they actually are. Lamr avoids that by never asking for the number at all.
Instead, the model is asked to judge each individual requirement in the posting — met, partially met, or missing — and how critical that requirement is. The final score is then computed with ordinary arithmetic from that structured judgment, not generated by the model. A posting where you're missing one hard requirement scores meaningfully lower than one where you meet everything, and the gap is real and reproducible rather than a roll of the dice.
This same rubric powers the quick pre-generation "screen" (should I even bother tailoring for this one?) and the deeper fit report you get after a document is generated — both are the same honest judgment, at different points in the process.
Templates & PDFs
Generated content is structured JSON, not a Word template filled in by an AI — the model never writes a PDF directly. That JSON is rendered into a real, typeset PDF using Typst, a modern typesetting system, across three templates (Classic, Modern, Sidebar) and five accent themes.
A resume that reads perfectly to a human can still extract badly for the software that actually screens it first. Every template is tested by compiling it and reading the text layer back out with the same kind of tooling an applicant-tracking system would use — one subtle typography feature (letter-spacing between kerned character pairs) can silently split a name or job title into fragments for some PDF-text extractors, so it's disabled across every template rather than left as a cosmetic default. Content also auto-scales to fit one page where that's reasonable, and simply paginates normally instead of being crushed into unreadable type when a resume is genuinely long.
Stack & architecture
| Layer | Technology |
|---|---|
| Frontend | A single vanilla JavaScript SPA — no framework, no build step |
| Backend | FastAPI (Python) |
| Database & storage | Supabase (Postgres + object storage for PDFs) |
| Document rendering | Typst, compiled server-side in a sandboxed process |
| AI | Claude Sonnet 5 (tailoring, prep, answers) · Claude Haiku 4.5 (screening, quick fixes) |
| Auth | Supabase Auth (email/password and Google) |
| Billing | Stripe |
| Hosting | Vercel (frontend) · a managed Python host (backend) |
There's deliberately very little abstraction between these layers. One HTML shell, one JavaScript file, one stylesheet, one Python backend module per concern (auth, billing, document generation). It's not the architecture of a large team — it's the architecture of a small one that would rather read the whole system than navigate it.
Data & privacy
- Your data is isolated per account at both the database policy level and in every application query — nothing about your applications, resume, or generated documents is visible to another account.
- Generated PDFs are private by default. They live in a private storage bucket and are only ever served through an authenticated proxy, never a public link — there's no URL to leak in the first place.
- Job descriptions are imported honestly. A pasted or linked posting is read from the posting's own structured data (the same markup Google's job search reads) or the raw page — Lamr doesn't summarize or paraphrase a posting into something shorter before tailoring against it, since tailoring against a summary would mean tailoring against a worse copy of the truth.
- You can delete your account and its data from within the app, including the generated documents stored for you.
Accounts & auth
Lamr is invite-gated during this early, private stage of the product — there's no open self-serve signup — which is a deliberate choice to grow deliberately rather than an oversight. Sign-in itself is handled by Supabase Auth (email/password, or Google), and every request to the backend is authenticated with a short-lived signed token that's verified independently on the server, not simply trusted because a request claims to be logged in.
Billing & credits
Plans are simple tiers (Free, Pro, Max). Most of the app costs nothing to use — tracking applications, editing your resume, screening a posting for fit. A small set of AI-heavy actions (generating a tailored resume/cover letter, drafting interview prep, answering an employer's custom questions) cost a small number of credits, priced roughly at what they actually cost to run. Billing itself is handled by Stripe; Lamr never sees or stores your card details.
Agents & MCP
Lamr exposes an MCP server, so you can manage applications, tailor documents, and prep for interviews directly from Claude, ChatGPT, Codex, or any other MCP-compatible client — not just the web app. Connecting uses the same OAuth sign-in as everything else; an agent never gets a shared password or a permanently-valid key.
An agent doesn't get its own, less-checked code path. Every tool call runs through the exact same backend logic as a click in the browser — the same credit accounting, the same truth checks, the same per-account isolation. And every change an agent makes to an application is recorded with who made it (browser or agent), so if something changes unexpectedly, there's always a real answer for why.
Auto-apply & consent boundaries
Lamr can help resolve an employer's own application form — filling in fields it can answer confidently from your resume and profile. It's built to refuse far more than it guesses, because a wrong answer here is a false statement made to an employer under your name, not a rendering bug.
- Legal attestations are never answered automatically, under any circumstance.
- Demographic and voluntary self-identification questions (gender, race/ethnicity, veteran status, disability status) are answered only for the exact categories you've explicitly opted into sharing yourself — every other field in that category, and anything not opted into, stays refused.
- A bot-detection challenge on an employer's site is never solved or bypassed — Lamr stops and hands it back to you.
- Nothing is submitted without a record of exactly what was submitted and when, so there's always a real trail.
Security posture
A few of the practical measures in place, at a level meant to be genuinely informative without being a roadmap for anyone looking for a way in:
- All traffic runs over HTTPS, and access tokens are verified against Supabase's own published signing keys rather than trusted at face value.
- Every endpoint is rate-limited per account.
- Requests to fetch a job posting from a URL are checked against internal/private network ranges before being made, so the feature can't be used to reach infrastructure that was never meant to be public.
- Third-party scripts are pinned to an exact version rather than "latest," so an upstream compromise can't silently ship new code into a page holding your session.
Versioning & changelog
Every day something ships gets a real semantic version number (MAJOR.MINOR.PATCH) — a new feature bumps the minor version, a fix bumps the patch version, and once a version number is assigned it never changes retroactively. The full history, versioned and dated, is in the app itself: open the account menu (or Command-K) and choose What's new.
Questions
If something on this page doesn't match what you're seeing in the product, or you just want to ask something directly — hello@lamr.app, or use "Contact support" from the account menu inside the app.