Skip to content

Make CV route ATS-parseable by preventing PDF rasterization - #55

Draft
papotte with Copilot wants to merge 4 commits into
mainfrom
copilot/enhance-cv-route-for-ats
Draft

Make CV route ATS-parseable by preventing PDF rasterization#55
papotte with Copilot wants to merge 4 commits into
mainfrom
copilot/enhance-cv-route-for-ats

Conversation

Copilot AI commented Dec 16, 2025

Copy link
Copy Markdown
Contributor

ATS systems fail to parse CVs generated via window.print() when browsers rasterize content into images. This occurs when CSS uses transforms, filters, or when SVG icons are embedded.

Changes

Semantic HTML structure

  • <div class="header"><header>
  • <div class="section"><section> with ARIA labels
  • Section headings: <h3><h2> (proper hierarchy: H1 → H2)

Icon handling

<!-- Before -->
<p class="contact">
  {icon && <Icon name={icon} />}
  {label}
</p>

<!-- After -->
<p class="contact">
  <span class="icon-wrapper print:hidden" aria-hidden="true">
    {icon && <Icon name={icon} />}
  </span>
  <span class="contact-label">{label}</span>
</p>

Print media queries (src/styles/cv.scss)

  • Strip rasterization-inducing properties: transform, filter, backdrop-filter, mix-blend-mode
  • Force single-column layout (grid → block/inline)
  • Hide all SVGs: svg { display: none !important; }
  • Set print-color-adjust: exact for text selectability
  • Page break optimization: prevent section/heading splits

Layout for print

  • Header: flexbox column (left-aligned for reading order)
  • Sections: simplified flexbox (was grid)
  • Blocks: inline date + information (was 2-column grid)
  • Multi-column descriptions: forced to single column

Result

PDFs generated via print dialog contain selectable text in logical reading order with no embedded SVGs or rasterized elements. Screen layout unchanged.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/papotte.github.io/papotte.github.io/node_modules/.bin/astro build (dns block)
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/papotte.github.io/papotte.github.io/node_modules/.bin/astro dev --host 0.0.0.0 --port 4321 ub.io/node_modules/.bin/git ame (dns block)
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/papotte.github.io/papotte.github.io/node_modules/.bin/astro build git conf�� (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Enhance CV route to be auto-parsed by ATS scanners</issue_title>
<issue_description>You’ve run into a very real ATS (Applicant Tracking System) problem, and you’re right about the core issue:
window.print() itself is not the enemy — how the page is rendered is.

The good news: you can keep your Astro + JS/TS CMS workflow and still generate an ATS-parsable CV, without falling back to Word or LaTeX.

Below is a practical, production-grade breakdown, ordered from most important to nice-to-have.

  1. Understand what ATS scanners actually need

Most ATS systems don’t do OCR unless they have to. They expect:

✅ Real text, not images
✅ Logical reading order
✅ Simple layout (single column preferred)
✅ Standard fonts
✅ Semantic structure

When scanners fail with print() PDFs, it’s usually because:

Text is rendered as SVG / Canvas / background images

CSS positioning breaks reading order

Fonts are embedded in a way that flattens glyphs

The PDF lacks tags

  1. Audit why your current PDF becomes images

Common culprits in modern web CVs:

❌ CSS that causes rasterization

Avoid:

transform: scale(); filter: blur(); backdrop-filter; mix-blend-mode;

Browsers will flatten the entire page into images if these appear in the print context.

❌ Icon fonts & SVG-only text

Font Awesome icons

SVG-based headings

Inline elements

ATS often ignores or misreads these.

  1. Create a print-specific ATS-safe layout (critical)

In Astro, add a dedicated print stylesheet:

@media print { * { transform: none !important; filter: none !important; box-shadow: none !important; } body { font-family: "Times New Roman", Arial, sans-serif; font-size: 11pt; line-height: 1.4; } a::after { content: " (" attr(href) ")"; font-size: 9pt; } }

Key principles:

One column

No grids or absolute positioning

No icons

No decorative separators

  1. Use semantic HTML (this helps ATS a lot)

This is where your CMS really shines.

✅ Do this

Firstname Lastname

Senior Frontend Engineer

Experience

Company – Role

2021–2024
  • Built X using Y

❌ Avoid

Experience
...

ATS systems do parse headings, lists, and articles.

  1. Fonts: boring is good

Use:

Times New Roman

Arial

Helvetica

Georgia

Avoid:

Variable fonts

Custom web fonts in print

Icon fonts

In print CSS:

@media print { body { font-family: Arial, sans-serif; } }

  1. Stop using browser print → use a PDF renderer instead (important)

Browsers are inconsistent. Instead, generate PDFs using a headless renderer that preserves text.

Best options

✅ Puppeteer (recommended for JS/TS stacks)

await page.pdf({ format: "A4", printBackground: false, preferCSSPageSize: true, tagged: true });

Why this works:

Preserves text layers

Generates selectable text

Can produce tagged PDFs

✅ Playwright (similar benefits)

❌ Avoid

html2canvas

jspdf with canvas

Screenshot-based exporters

  1. Create a dedicated /cv-print route

This is a pro move.

Example:

/cv → styled portfolio version /cv-print → ATS-safe version

In Astro:

--- const isPrint = Astro.url.pathname.includes("cv-print"); ---

Then conditionally:

Disable icons

Switch layout

Simplify styles

  1. Tagged PDFs (optional but excellent)

Some ATS systems read PDF tags (structure tree).

If you use:

Puppeteer

PrinceXML (paid)

WeasyPrint (via CI)

You can generate fully tagged PDFs, similar to LaTeX output.

This is why Overleaf works so well.

  1. Test your output like an ATS

Before sending:

Open PDF

Try:

Select text

Copy → paste into plain text editor

Upload to:

Indeed resume parser

LinkedIn resume upload

Jobscan.co

If it pastes cleanly → you’re good.

  1. Reality check (important)

ATS-friendly ≠ visually impressive

That’s why even FAANG candidates often submit:

One boring PDF

One beautiful portfolio

Your CMS approach is actually better than Word/LaTeX — you just need two outputs.

TL;DR (what to do next)

Keep your stack. Change the export.

✅ Semantic HTML
✅ Print-only ATS stylesheet
✅ No transforms, SVG text, or icons
✅ Generate PDF with Puppeteer/Playwright
✅ Separate /cv-print route

If you want, I can:

Review your existing CV markup and point out ATS-breaking parts

Give you a Puppeteer PDF export script tailored to Astro

Help design a clean ATS-only layout that auto-syncs with your CMS

Just tell me which you want.

</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel

vercel Bot commented Dec 16, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
cv Ready Ready Preview, Comment Dec 17, 2025 7:59pm

Copilot AI and others added 4 commits December 17, 2025 20:58
Co-authored-by: papotte <21336477+papotte@users.noreply.github.com>
Co-authored-by: papotte <21336477+papotte@users.noreply.github.com>
…ing structure

Co-authored-by: papotte <21336477+papotte@users.noreply.github.com>
@papotte
papotte force-pushed the copilot/enhance-cv-route-for-ats branch from bd3545d to c09f7c9 Compare December 17, 2025 19:59
@papotte

papotte commented Dec 17, 2025

Copy link
Copy Markdown
Owner

@copilot I've updated the icons, can you update this PR?

Copilot AI commented Dec 17, 2025

Copy link
Copy Markdown
Contributor Author

@copilot I've updated the icons, can you update this PR?

The PR is already compatible with the updated icons. I've verified that:

  • All icons use the new format (ic:round-* and logos:* instead of mdi:*)
  • The icon wrapping for print compatibility works correctly with the new icon set
  • Build, lint, and all tests pass successfully ✓

The changes properly hide all SVG icons in print view while maintaining screen display functionality with the updated icon library.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/papotte.github.io/papotte.github.io/node_modules/.bin/astro build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance CV route to be auto-parsed by ATS scanners

2 participants