Skip to content

Fix hydration mismatch and update defaults#666

Open
simonsobran wants to merge 5 commits intosrbhr:mainfrom
simonsobran:codex/compact-defaults
Open

Fix hydration mismatch and update defaults#666
simonsobran wants to merge 5 commits intosrbhr:mainfrom
simonsobran:codex/compact-defaults

Conversation

@simonsobran
Copy link
Copy Markdown

@simonsobran simonsobran commented Feb 9, 2026

Pull Request Title

Related Issue

Description

Fixed hydration, added support for new gpt models with reasoning

Type

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

Proposed Changes

Screenshots / Code Snippets (if applicable)

How to Test

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

copilot:walkthrough


Summary by cubic

Fixes hydration mismatch by enabling drag-and-drop only after mount across resume sections and experience items, updates defaults (compactMode=true, top/bottom margins=5), and adds editable tailoring prompts with backend CRUD and a Prompts page (create/edit/delete, set default; Tailor lists custom options). Also sets reasoning_effort="medium" for OpenAI o1/o3/gpt-5 and fixes TipTap remounts to prevent flicker.

  • New Features
    • Drag-and-drop ordering for jobs; added optional jobDescription shown in previews and JD comparison.
    • Smarter PDF filenames for resume/cover letter using name, role, template, locale, and date.
    • Prompt templates validate placeholders; built-in prompts are read-only.

Written for commit cb1237a. Summary will update on new commits.

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.

No issues found across 3 files

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.

12 issues found across 18 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/frontend/components/builder/forms/generic-item-form.tsx">

<violation number="1" location="apps/frontend/components/builder/forms/generic-item-form.tsx:109">
P2: Prepending description entries while using index keys causes all existing items to shift keys. React will reuse RichTextEditor instances for different items, leading to state resets and performance issues. Use a stable key per description entry (e.g., store an id with each description) or avoid prepending if index keys are kept.</violation>
</file>

<file name="apps/backend/app/routers/config.py">

<violation number="1" location="apps/backend/app/routers/config.py:122">
P2: `string.Formatter().parse(prompt)` can raise `ValueError` for malformed format strings (e.g., unescaped `{`/`}`), and this exception is not caught. User-provided prompts with invalid braces will cause a 500 error instead of a 400 validation response.</violation>

<violation number="2" location="apps/backend/app/routers/config.py:457">
P2: update_prompt_template allows setting an empty prompt string, breaking the invariant enforced on creation and letting templates be saved with no prompt text.</violation>
</file>

<file name="apps/frontend/messages/zh.json">

<violation number="1" location="apps/frontend/messages/zh.json:45">
P3: Chinese locale file includes English strings for the new prompts feature, so users selecting zh will see untranslated UI text.</violation>
</file>

<file name="apps/backend/app/routers/resumes.py">

<violation number="1" location="apps/backend/app/routers/resumes.py:86">
P2: Synchronous TinyDB I/O was added inside _get_default_prompt_id(), which is called from async route handlers. This blocking DB call will freeze the event loop while reading prompt templates, reducing concurrency under load.</violation>
</file>

<file name="apps/frontend/messages/pt-BR.json">

<violation number="1" location="apps/frontend/messages/pt-BR.json:52">
P2: New pt-BR localization entries for the prompts feature are still in English, leading to a mixed-language UI for Portuguese users.</violation>
</file>

<file name="apps/frontend/messages/es.json">

<violation number="1" location="apps/frontend/messages/es.json:52">
P2: English strings were added to the Spanish locale file; these should be translated to Spanish to avoid mixed-language UI.</violation>
</file>

<file name="apps/backend/app/database.py">

<violation number="1" location="apps/backend/app/database.py:51">
P2: `reset_database` doesn’t clear the newly added `prompt_templates` table, so database resets leave custom prompts behind and can contaminate test/environment state.</violation>
</file>

<file name="apps/frontend/components/builder/forms/experience-form.tsx">

<violation number="1" location="apps/frontend/components/builder/forms/experience-form.tsx:67">
P2: Prepending new description items while rendering with `key={idx}` will shift all keys and cause RichTextEditor instances to be reused for the wrong content, risking state/cursor issues and unnecessary re-renders. Either append new items or use stable IDs for description entries.</violation>
</file>

<file name="apps/frontend/messages/ja.json">

<violation number="1" location="apps/frontend/messages/ja.json:51">
P2: The Japanese locale file adds a new `prompts` section with English strings, leaving UI labels untranslated for Japanese users.</violation>
</file>

<file name="apps/frontend/components/builder/forms/projects-form.tsx">

<violation number="1" location="apps/frontend/components/builder/forms/projects-form.tsx:68">
P2: Prepending description entries while using index keys forces React to remount all editors, causing state loss and unnecessary re-renders. Use stable keys or append instead of prepend.</violation>
</file>

<file name="apps/frontend/app/(default)/prompts/page.tsx">

<violation number="1" location="apps/frontend/app/(default)/prompts/page.tsx:76">
P2: Saving overwrites drafts with the server response even if the user edited the fields while the save request was in flight, so in-flight edits can be lost.</violation>
</file>

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

items.map((item) => {
if (item.id === id) {
return { ...item, description: [...(item.description || []), ''] };
return { ...item, description: ['', ...(item.description || [])] };
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: Prepending description entries while using index keys causes all existing items to shift keys. React will reuse RichTextEditor instances for different items, leading to state resets and performance issues. Use a stable key per description entry (e.g., store an id with each description) or avoid prepending if index keys are kept.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/components/builder/forms/generic-item-form.tsx, line 109:

<comment>Prepending description entries while using index keys causes all existing items to shift keys. React will reuse RichTextEditor instances for different items, leading to state resets and performance issues. Use a stable key per description entry (e.g., store an id with each description) or avoid prepending if index keys are kept.</comment>

<file context>
@@ -106,7 +106,7 @@ export const GenericItemForm: React.FC<GenericItemFormProps> = ({
       items.map((item) => {
         if (item.id === id) {
-          return { ...item, description: [...(item.description || []), ''] };
+          return { ...item, description: ['', ...(item.description || [])] };
         }
         return item;
</file context>
Fix with Cubic

Comment on lines +122 to +126
fields = {
field_name
for _, field_name, _, _ in string.Formatter().parse(prompt)
if field_name
}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: string.Formatter().parse(prompt) can raise ValueError for malformed format strings (e.g., unescaped {/}), and this exception is not caught. User-provided prompts with invalid braces will cause a 500 error instead of a 400 validation response.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/backend/app/routers/config.py, line 122:

<comment>`string.Formatter().parse(prompt)` can raise `ValueError` for malformed format strings (e.g., unescaped `{`/`}`), and this exception is not caught. User-provided prompts with invalid braces will cause a 500 error instead of a 400 validation response.</comment>

<file context>
@@ -67,7 +78,61 @@ def _mask_api_key(key: str) -> str:
+
+
+def _validate_prompt_template(prompt: str) -> None:
+    fields = {
+        field_name
+        for _, field_name, _, _ in string.Formatter().parse(prompt)
</file context>
Suggested change
fields = {
field_name
for _, field_name, _, _ in string.Formatter().parse(prompt)
if field_name
}
try:
fields = {
field_name
for _, field_name, _, _ in string.Formatter().parse(prompt)
if field_name
}
except ValueError as exc:
raise HTTPException(status_code=400, detail="Invalid prompt format string.") from exc
Fix with Cubic

prompt = request.prompt.strip()
if prompt:
_validate_prompt_template(prompt)
updates["prompt"] = prompt
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: update_prompt_template allows setting an empty prompt string, breaking the invariant enforced on creation and letting templates be saved with no prompt text.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/backend/app/routers/config.py, line 457:

<comment>update_prompt_template allows setting an empty prompt string, breaking the invariant enforced on creation and letting templates be saved with no prompt text.</comment>

<file context>
@@ -320,6 +385,117 @@ async def update_prompt_config(
+        prompt = request.prompt.strip()
+        if prompt:
+            _validate_prompt_template(prompt)
+        updates["prompt"] = prompt
+
+    if not updates:
</file context>
Fix with Cubic

config = _load_config()
option_ids = {option["id"] for option in IMPROVE_PROMPT_OPTIONS}
option_ids.update(
prompt.get("prompt_id") for prompt in db.list_prompt_templates() if prompt.get("prompt_id")
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: Synchronous TinyDB I/O was added inside _get_default_prompt_id(), which is called from async route handlers. This blocking DB call will freeze the event loop while reading prompt templates, reducing concurrency under load.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/backend/app/routers/resumes.py, line 86:

<comment>Synchronous TinyDB I/O was added inside _get_default_prompt_id(), which is called from async route handlers. This blocking DB call will freeze the event loop while reading prompt templates, reducing concurrency under load.</comment>

<file context>
@@ -82,6 +82,9 @@ def _get_default_prompt_id() -> str:
     config = _load_config()
     option_ids = {option["id"] for option in IMPROVE_PROMPT_OPTIONS}
+    option_ids.update(
+        prompt.get("prompt_id") for prompt in db.list_prompt_templates() if prompt.get("prompt_id")
+    )
     prompt_id = config.get("default_prompt_id", DEFAULT_IMPROVE_PROMPT_ID)
</file context>
Fix with Cubic

},
"prompts": {
"title": "Prompts",
"subtitle": "Manage tailoring intensity prompts",
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: New pt-BR localization entries for the prompts feature are still in English, leading to a mixed-language UI for Portuguese users.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/messages/pt-BR.json, line 52:

<comment>New pt-BR localization entries for the prompts feature are still in English, leading to a mixed-language UI for Portuguese users.</comment>

<file context>
@@ -42,10 +42,58 @@
   },
+  "prompts": {
+    "title": "Prompts",
+    "subtitle": "Manage tailoring intensity prompts",
+    "create": {
+      "title": "Create Prompt",
</file context>
Fix with Cubic

data.map((item) => {
if (item.id === id) {
return { ...item, description: [...(item.description || []), ''] };
return { ...item, description: ['', ...(item.description || [])] };
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: Prepending new description items while rendering with key={idx} will shift all keys and cause RichTextEditor instances to be reused for the wrong content, risking state/cursor issues and unnecessary re-renders. Either append new items or use stable IDs for description entries.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/components/builder/forms/experience-form.tsx, line 67:

<comment>Prepending new description items while rendering with `key={idx}` will shift all keys and cause RichTextEditor instances to be reused for the wrong content, risking state/cursor issues and unnecessary re-renders. Either append new items or use stable IDs for description entries.</comment>

<file context>
@@ -64,7 +64,7 @@ export const ExperienceForm: React.FC<ExperienceFormProps> = ({ data, onChange }
       data.map((item) => {
         if (item.id === id) {
-          return { ...item, description: [...(item.description || []), ''] };
+          return { ...item, description: ['', ...(item.description || [])] };
         }
         return item;
</file context>
Suggested change
return { ...item, description: ['', ...(item.description || [])] };
return { ...item, description: [...(item.description || []), ''] };
Fix with Cubic

"goToSettings": "設定へ"
},
"prompts": {
"title": "Prompts",
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: The Japanese locale file adds a new prompts section with English strings, leaving UI labels untranslated for Japanese users.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/messages/ja.json, line 51:

<comment>The Japanese locale file adds a new `prompts` section with English strings, leaving UI labels untranslated for Japanese users.</comment>

<file context>
@@ -42,10 +42,58 @@
     "goToSettings": "設定へ"
   },
+  "prompts": {
+    "title": "Prompts",
+    "subtitle": "Manage tailoring intensity prompts",
+    "create": {
</file context>
Fix with Cubic

data.map((item) => {
if (item.id === id) {
return { ...item, description: [...(item.description || []), ''] };
return { ...item, description: ['', ...(item.description || [])] };
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: Prepending description entries while using index keys forces React to remount all editors, causing state loss and unnecessary re-renders. Use stable keys or append instead of prepend.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/components/builder/forms/projects-form.tsx, line 68:

<comment>Prepending description entries while using index keys forces React to remount all editors, causing state loss and unnecessary re-renders. Use stable keys or append instead of prepend.</comment>

<file context>
@@ -65,7 +65,7 @@ export const ProjectsForm: React.FC<ProjectsFormProps> = ({ data, onChange }) =>
       data.map((item) => {
         if (item.id === id) {
-          return { ...item, description: [...(item.description || []), ''] };
+          return { ...item, description: ['', ...(item.description || [])] };
         }
         return item;
</file context>
Suggested change
return { ...item, description: ['', ...(item.description || [])] };
return { ...item, description: [...(item.description || []), ''] };
Fix with Cubic

}, [loadData]);

const handleDraftChange = (id: string, update: Partial<PromptDraft>) => {
setDrafts((prev) => ({
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P2: Saving overwrites drafts with the server response even if the user edited the fields while the save request was in flight, so in-flight edits can be lost.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/app/(default)/prompts/page.tsx, line 76:

<comment>Saving overwrites drafts with the server response even if the user edited the fields while the save request was in flight, so in-flight edits can be lost.</comment>

<file context>
@@ -0,0 +1,446 @@
+  }, [loadData]);
+
+  const handleDraftChange = (id: string, update: Partial<PromptDraft>) => {
+    setDrafts((prev) => ({
+      ...prev,
+      [id]: { ...prev[id], ...update },
</file context>
Fix with Cubic

"dashboard": "仪表板",
"builder": "简历生成器",
"tailor": "定制简历",
"prompts": "Prompts",
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 9, 2026

Choose a reason for hiding this comment

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

P3: Chinese locale file includes English strings for the new prompts feature, so users selecting zh will see untranslated UI text.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/messages/zh.json, line 45:

<comment>Chinese locale file includes English strings for the new prompts feature, so users selecting zh will see untranslated UI text.</comment>

<file context>
@@ -42,10 +42,58 @@
     "dashboard": "仪表板",
     "builder": "简历生成器",
     "tailor": "定制简历",
+    "prompts": "Prompts",
     "settings": "设置",
     "backToDashboard": "返回仪表板",
</file context>
Fix with Cubic

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.

5 issues found across 20 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/frontend/messages/ja.json">

<violation number="1" location="apps/frontend/messages/ja.json:362">
P3: The Japanese error message example uses the English term "Present" while the placeholder uses "現在", creating inconsistent guidance for users. Align the example with the localized term used elsewhere.</violation>
</file>

<file name="apps/frontend/components/builder/resume-builder.tsx">

<violation number="1" location="apps/frontend/components/builder/resume-builder.tsx:435">
P3: Download filename is built from placeholder resumeData before async fetch completes, so users can get incorrect filenames when downloading immediately after load.</violation>
</file>

<file name="apps/frontend/components/builder/forms/experience-form.tsx">

<violation number="1" location="apps/frontend/components/builder/forms/experience-form.tsx:76">
P2: Touched validation state persists across deletions and can be applied to newly added items when a deleted id is reused, causing the years validation warning to show prematurely.</violation>
</file>

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

<violation number="1" location="apps/frontend/lib/utils/filename.ts:9">
P2: Combining diacritic marks produced by NFKD normalization are treated as non-letter characters and replaced with underscores, so names like "Résumé" become "R_e_s_u_m_e_". If the intent is to remove accents, strip combining marks before replacing non-alphanumerics.</violation>

<violation number="2" location="apps/frontend/lib/utils/filename.ts:57">
P2: When the person name is missing, the filename contains duplicated "Cover_Letter" segments because it is used as both the fallback and the fixed second segment.</violation>
</file>

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

export const ExperienceForm: React.FC<ExperienceFormProps> = ({ data, onChange }) => {
const { t } = useTranslations();
const [isMounted, setIsMounted] = useState(false);
const [touchedYears, setTouchedYears] = useState<Record<number, boolean>>({});
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 10, 2026

Choose a reason for hiding this comment

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

P2: Touched validation state persists across deletions and can be applied to newly added items when a deleted id is reused, causing the years validation warning to show prematurely.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/components/builder/forms/experience-form.tsx, line 76:

<comment>Touched validation state persists across deletions and can be applied to newly added items when a deleted id is reused, causing the years validation warning to show prematurely.</comment>

<file context>
@@ -1,24 +1,116 @@
 export const ExperienceForm: React.FC<ExperienceFormProps> = ({ data, onChange }) => {
   const { t } = useTranslations();
+  const [isMounted, setIsMounted] = useState(false);
+  const [touchedYears, setTouchedYears] = useState<Record<number, boolean>>({});
+  const monthPattern = useMemo(
+    () =>
</file context>
Fix with Cubic


function sanitizeSegment(value: string): string {
return value
.normalize('NFKD')
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 10, 2026

Choose a reason for hiding this comment

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

P2: Combining diacritic marks produced by NFKD normalization are treated as non-letter characters and replaced with underscores, so names like "Résumé" become "R_e_s_u_m_e_". If the intent is to remove accents, strip combining marks before replacing non-alphanumerics.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/lib/utils/filename.ts, line 9:

<comment>Combining diacritic marks produced by NFKD normalization are treated as non-letter characters and replaced with underscores, so names like "Résumé" become "R_e_s_u_m_e_". If the intent is to remove accents, strip combining marks before replacing non-alphanumerics.</comment>

<file context>
@@ -0,0 +1,65 @@
+
+function sanitizeSegment(value: string): string {
+  return value
+    .normalize('NFKD')
+    .replace(/[^\p{L}\p{N}]+/gu, '_')
+    .replace(/^_+|_+$/g, '')
</file context>
Fix with Cubic

): string {
const name = getPersonName(resumeData);
const segments = [
name ? sanitizeSegment(name) : 'Cover_Letter',
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 10, 2026

Choose a reason for hiding this comment

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

P2: When the person name is missing, the filename contains duplicated "Cover_Letter" segments because it is used as both the fallback and the fixed second segment.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/lib/utils/filename.ts, line 57:

<comment>When the person name is missing, the filename contains duplicated "Cover_Letter" segments because it is used as both the fallback and the fixed second segment.</comment>

<file context>
@@ -0,0 +1,65 @@
+): string {
+  const name = getPersonName(resumeData);
+  const segments = [
+    name ? sanitizeSegment(name) : 'Cover_Letter',
+    'Cover_Letter',
+    locale ? sanitizeSegment(locale) : null,
</file context>
Fix with Cubic

"jobDescriptionOptional": "職務概要(任意)"
},
"errors": {
"yearsRequiresMonth": "月名を含めてください(例: Aug 2020 - Present)"
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 10, 2026

Choose a reason for hiding this comment

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

P3: The Japanese error message example uses the English term "Present" while the placeholder uses "現在", creating inconsistent guidance for users. Align the example with the localized term used elsewhere.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/messages/ja.json, line 362:

<comment>The Japanese error message example uses the English term "Present" while the placeholder uses "現在", creating inconsistent guidance for users. Align the example with the localized term used elsewhere.</comment>

<file context>
@@ -352,15 +352,21 @@
+          "jobDescriptionOptional": "職務概要(任意)"
+        },
+        "errors": {
+          "yearsRequiresMonth": "月名を含めてください(例: Aug 2020 - Present)"
         },
         "placeholders": {
</file context>
Suggested change
"yearsRequiresMonth": "月名を含めてください(例: Aug 2020 - Present"
"yearsRequiresMonth": "月名を含めてください(例: Aug 2020 - 現在"
Fix with Cubic

setIsDownloading(true);
const blob = await downloadResumePdf(resumeId, templateSettings, uiLanguage);
downloadBlobAsFile(blob, `resume_${resumeId}.pdf`);
downloadBlobAsFile(blob, buildResumeFilename(resumeData, templateSettings, uiLanguage));
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 10, 2026

Choose a reason for hiding this comment

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

P3: Download filename is built from placeholder resumeData before async fetch completes, so users can get incorrect filenames when downloading immediately after load.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/frontend/components/builder/resume-builder.tsx, line 435:

<comment>Download filename is built from placeholder resumeData before async fetch completes, so users can get incorrect filenames when downloading immediately after load.</comment>

<file context>
@@ -431,7 +432,7 @@ const ResumeBuilderContent = () => {
       setIsDownloading(true);
       const blob = await downloadResumePdf(resumeId, templateSettings, uiLanguage);
-      downloadBlobAsFile(blob, `resume_${resumeId}.pdf`);
+      downloadBlobAsFile(blob, buildResumeFilename(resumeData, templateSettings, uiLanguage));
       showNotification(t('builder.alerts.downloadSuccess'), 'success');
     } catch (error) {
</file context>
Fix with Cubic

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.

1 participant