Skip to content

Feat/personalized download filenames#727

Open
JherrerasPY wants to merge 3 commits intosrbhr:devfrom
JherrerasPY:feat/personalized-download-filenames
Open

Feat/personalized download filenames#727
JherrerasPY wants to merge 3 commits intosrbhr:devfrom
JherrerasPY:feat/personalized-download-filenames

Conversation

@JherrerasPY
Copy link
Copy Markdown

@JherrerasPY JherrerasPY commented Mar 24, 2026

Pull Request Title

personalize PDF download filenames with applicant name and company

Related Issue

Description

Currently, both the resume and cover letter PDFs are downloaded using the AI-generated title as the filename (e.g. Business Systems Analyst @ Torch Professional Services Pty Ltd.pdf). This has a few problems:

  • The @ character is problematic on some filesystems
  • Both the resume and cover letter get the same filename, making it impossible to distinguish them in a downloads folder
  • The filename is not immediately recognizable to recruiters who receive many files

This PR changes the download filename to a personal, professional format:

  • Resume: John Smith - Resume - Torch Professional Services.pdf
  • Cover Letter: John Smith - Cover Letter - Torch Professional Services.pdf

The applicant's name is read from resumeData.personalInfo.name and the company is parsed from the existing AI-generated title (splitting on @). Fallbacks are handled gracefully — if the company is unavailable the format becomes John Smith - Resume.pdf, and if neither name nor company is available it falls back to the existing UUID-based naming.

Type

personalize PDF download filenames with applicant name and company

  • Bug Fix
  • Feature Enhancement
  • Documentation Update
  • Code Refactoring
  • Other (please specify):

Proposed Changes

  • Added buildResumeFilename() utility function in apps/frontend/lib/utils/download.ts that constructs {Name} - {Type} - {Company}.pdf with graceful fallbacks
  • Added getCompanyFromTitle() helper in resume-builder.tsx to extract the company name from the AI-generated "Role @ Company" title string
  • Updated handleDownload and handleDownloadCoverLetter in resume-builder.tsx to use the new naming function, so resume and cover letter downloads now have distinct, personalized filenames

Screenshots / Code Snippets (if applicable)

Before:
Business Systems Analyst @ Torch Professional Services Pty Ltd.pdf ← resume
Business Systems Analyst @ Torch Professional Services Pty Ltd.pdf ← cover letter (identical)

After:
John Smith - Resume - Torch Professional Services Pty Ltd.pdf
John Smith - Cover Letter - Torch Professional Services Pty Ltd.pdf

Fallback chain:
Both name + company → John Smith - Resume - Acme Corp.pdf
Name only → John Smith - Resume.pdf
Neither → resume_.pdf (existing behaviour)

How to Test

  1. Open a tailored resume in the Resume Builder (/builder?id=...)
  2. Click Download — verify the file is named {Your Name} - Resume - {Company}.pdf
  3. Navigate to the Cover Letter tab and click its download button — verify the file is named {Your Name} - Cover Letter - {Company}.pdf
  4. Open a master resume (one with no AI-generated title) and download — verify it falls back to {Your Name} - Resume.pdf
  5. Temporarily clear personalInfo.name in the editor and download — verify it falls back to the previous title-based or UUID-based filename

Checklist

  • The code compiles successfully without any errors or warnings
  • The changes have been tested and verified
  • The documentation has been updated (if applicable)
  • The changes follow the project's coding guidelines and best practices
  • The commit messages are descriptive and follow the project's guidelines
  • All tests (if applicable) pass successfully
  • This pull request has been linked to the related issue (if applicable)

Additional Information

The buildResumeFilename() function reuses the existing sanitizeFilename() utility for Unicode normalization and invalid-character stripping, so all existing safety guarantees (handling of /, \, *, ?, etc. and multi-byte character truncation) apply to the new format as well.


Summary by cubic

Personalized PDF download filenames for resumes and cover letters using the applicant’s name and company. Files are now clear, distinct, and free of problematic characters.

  • New Features
    • Naming format: "{Name} - {Type} - {Company}.pdf" (sanitized).
    • Fallbacks: name+company → name only → company only ("{Type} - {Company}") → previous title-based or resume_<uuid>.pdf.
    • Added buildResumeFilename() and switched download handlers; company parsing now uses lastIndexOf(' @ ') to handle titles with multiple @.

Written for commit 3063bf6. Summary will update on new commits.

} else if (cleanName) {
raw = `${cleanName} - ${typeLabel}`;
} else {
return sanitizeFilename(cleanCompany, fallbackId, type);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Inconsistent fallback behavior when name is missing but company exists

When cleanName is falsy but cleanCompany has a value, this returns a filename like Acme Corp.pdf without indicating the document type (Resume/Cover Letter). This differs from the documented fallback chain in the PR description.

The current behavior:

  • Name + Company → John Smith - Resume - Acme Corp.pdf
  • Name only → John Smith - Resume.pdf
  • Company only → Acme Corp.pdf (no type indicator)
  • Neither → resume_<uuid>.pdf

Consider whether the "company only" case should include the type label for consistency:

Suggested change
return sanitizeFilename(cleanCompany, fallbackId, type);
return sanitizeFilename(cleanCompany ? `${typeLabel} - ${cleanCompany}` : null, fallbackId, type);


const getCompanyFromTitle = (title: string | null | undefined): string | null => {
if (!title) return null;
const atIdx = title.indexOf(' @ ');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Consider handling multiple @ occurrences in title

If a title contains multiple @ patterns (e.g., "Senior Dev @ Startup @ Subsidiary"), this will return "Startup @ Subsidiary" as the company name. While edge case, you may want to use lastIndexOf instead to capture only the company name:

Suggested change
const atIdx = title.indexOf(' @ ');
const atIdx = title.lastIndexOf(' @ ');

Alternatively, if the current behavior is intentional (taking everything after the first @), consider adding a comment documenting this design decision.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Mar 24, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Previous Issues - Now Resolved ✅

Both issues from the previous review have been addressed in commit 3063bf6:

Previous Issue Resolution
WARNING: Filename lacked type indicator when only company was present Fixed - now produces Resume - Company.pdf or Cover Letter - Company.pdf
SUGGESTION: Use lastIndexOf for ' @ ' parsing Fixed - changed from indexOf to lastIndexOf
Positive Observations
  • Clean separation of filename building logic into a dedicated utility function
  • Proper type safety with string | null | undefined handling
  • Good use of existing sanitizeFilename function for consistency
  • Complete fallback chain now handles all scenarios consistently:
    • Name + Company → John Smith - Resume - Acme Corp.pdf
    • Name only → John Smith - Resume.pdf
    • Company only → Resume - Acme Corp.pdf (now includes type label)
    • Neither → resume_<uuid>.pdf
  • No API-breaking changes or security concerns
  • No LiteLLM or prompt flow changes in this PR
Files Reviewed (3 files)
  • apps/frontend/lib/utils/download.ts - No issues (new buildResumeFilename utility with fixed fallback)
  • apps/frontend/components/builder/resume-builder.tsx - No issues (download handlers with fixed company extraction)
  • apps/frontend/components/tailor/diff-preview-modal.tsx - No issues (Prettier formatting only)

Reviewed by claude-4.5-opus-20251124 · 197,614 tokens

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/frontend/lib/utils/download.ts">

<violation number="1" location="apps/frontend/lib/utils/download.ts:84">
P2: When name is missing but company is present, the filename omits the document type, so resume and cover letter downloads both become `<company>.pdf` and collide.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- Include document type label (Resume/Cover Letter) in filename when
  only company is present, preventing ambiguity between downloads
- Use lastIndexOf(' @ ') instead of indexOf to correctly extract
  company from titles with multiple @ occurrences
- Fix Prettier formatting in diff-preview-modal.tsx

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

2 participants