Commit Graph
71 Commits
Author SHA1 Message Date
Amruth Pillai 48b27802fd test: remove redundant cases and repeated setup 2026-09-29 23:17:30 +02:00
Amruth Pillai 8a2fa26451 ci: run the database-backed suites and drop coverage from the unit step
The cover-letter and MCP OAuth flow suites were gated on environment variables
CI never set, so they never ran. Point them at the job's PostgreSQL. The
cover-letter suite works in its own schema; the OAuth suite gets a database of
its own because it writes signing keys under its own secret, which the e2e
server can't decrypt.

Nothing reads the unit step's coverage report, so test:ci no longer collects it.
2026-09-29 22:31:56 +02:00
Amruth Pillai c0c7984712 test: keep only the tests that guard real breakage
Prune the unit and e2e suites to what protects security, user data, public
contracts and past regressions. Drop what slowed development without catching
bugs: markup and label assertions, wrappers that only proved Base UI works,
copied inventories and snapshots, mock call-shape checks, permutation matrices
across templates, fonts and locales, and env-gated suites that never ran in CI.

- Unit: 4749 tests in 421 files become 1212 in 227. PDF tests that rendered or
  rasterized every template, font and locale combination go; one render per
  template stays and now checks that every visible section reaches a page,
  which a blank page used to pass.
- E2E: 55 tests in 35 specs become 11 in 9, one journey per severe area: sign-up
  and sign-in, autosave, a failed save during navigation, JSON export and import,
  public and password-protected sharing, slug redirects, OAuth consent for MCP
  clients, and the assistant.
- Tests a coverage review found to be the only guard of a contract were kept or
  restored, each checked by breaking the code it guards.
- Remove exports, tooling and dev dependencies that only the pruned tests used.
- The Semantic CSS guide check now reads indented code fences, so the guide
  example it skipped is compiled too.
2026-09-29 22:31:45 +02:00
Amruth Pillai 03c3a88841 fix(schema): case the present label by its language only
page.locale accepts any string. A malformed tag such as "de-DE-" made toLocaleUpperCase throw a RangeError, so parseResumeData failed and the resume could not load. The language code always comes from the parser's word list, so it is a valid tag.
2026-09-29 22:10:14 +02:00
Amruth Pillai a325232a09 refactor(pdf): render every resume with semantic css and drop the legacy styler
Now that the API hands out every resume with its legacy style rules
converted, the renderer runs one styling system: the stylesheet mode,
the per-slot legacy rule hooks in the template primitives and the
section style provider are gone, and the Custom Styles editor loses its
legacy draft banner and Activate step. The converter stays (the API
uses it), with its fixtures now checked by rendering the converted
stylesheets.
2026-09-29 15:25:44 +02:00
Amruth Pillai db97381b3d feat(api): convert legacy style rules to semantic css on every read and save
Resumes from before Semantic CSS carry legacy style rules that only the
old renderer understood. The API now converts them (with the existing,
parity-tested converter) whenever resume data is read or written, so
everything it hands out uses a Semantic CSS stylesheet and the database
catches up on the next save. The rules stay stored for rollback, and a
draft typed in the old editor but never activated is kept, commented
out, after the conversion. New resumes start with an empty stylesheet.
2026-09-29 15:09:57 +02:00
Amruth Pillai 2506509538 feat: make cover letters documents of their own
Resumes no longer hold cover-letter sections. A migration saves every
letter a resume carried as a letter linked to that resume's details and
design, hands a resume's only letter to its only letter-less application,
then removes the sections from resumes and their layouts. rollback.sql
puts them back.

Every resume write on the server moves any letter it still carries into
a saved letter in the same transaction, so stale tabs, older files, API
clients and restored versions keep working without duplicating letters.

The resume editor no longer adds or imports letters, the resume download
drops its Cover letter tab, and resume PDF downloads (API, signed links,
MCP) no longer take a cover-letter target. copy_embedded_cover_letter and
POST /cover-letters/from-resume are removed.
2026-09-29 09:30:07 +02:00
Amruth Pillai cbc76b03b1 refactor!: contract the redesign's legacy fields
The expand steps of the redesign kept older app versions and API clients
working. This removes those compatibility paths:

- Entry date text (period/date) is written from the structured dates on
  every save; an edit to the text alone is overwritten.
- application.archived is dropped; archived rows close first. CSV import
  still reads the flag from older exports.
- resume_version.label is dropped; versions are named by kind and name.
- rejected is no longer accepted as a stage; remaining rows and history
  close first. CSV import still maps it to closed.

BREAKING CHANGE: older app versions and API clients that read or write
archived, version labels, the rejected stage or date text alone no
longer work. migrations/20260929063245_contract_redesign_legacy_fields
has a rollback.sql that restores the dropped columns.
2026-09-29 08:34:27 +02:00
Amruth Pillai 098df60230 feat: choose which side the sidebar sits on
Two-column templates take a sidebarSide from the layout (left or right).
Without one, each template keeps its own side and right-to-left pages
mirror it. The PDF templates reverse only their columns, header band
and sidebar background, and the DOCX export follows the same choice.
Design's Sidebar panel offers Left and Right.
2026-09-29 08:00:33 +02:00
Amruth Pillai c0bf1aebaf feat(pdf): remove react-pdf and move every consumer to forme
The web preview, downloads, template gallery, server export and public
PDF render through Forme. react-pdf, react-pdf-html, the react-pdf
hyphenation package, the Phosphor react-pdf icons and the four patches
are gone. Hyphenation now follows the page language for every language
Forme has patterns for.

Semantic CSS keeps its language; declarations Forme can't draw raise an
ENGINE_UNSUPPORTED warning in the editor. The page map rebuilds blocks
Forme leaves out of its layout when they break across pages, and a
render that misplaces a box is repeated with nested rows kept whole.

Tests move to a small shim with the react-pdf calls they were written
against; tests of react-pdf internals are dropped. Forme limits are
recorded as expected failures (RTL line order, characters above
U+FFFF).
2026-09-29 07:11:40 +02:00
Amruth Pillai fdad39c632 feat(api): structured letters with live links, versions and a streaming draft 2026-09-28 23:08:04 +02:00
Amruth Pillai ce0b4c606a feat(api): a closed stage with reasons, what was sent, posting requirements and a posting reader
- Applications end in a `closed` stage with a reason (not selected, withdrew,
  accepted another offer, no response). The migration moves `rejected` to
  closed + not selected and archived applications to closed, rewrites
  `rejected` in their stage history, and ships rollback.sql for older
  versions. `archived` stays, deprecated; `rejected` is still accepted as
  input and means closed.
- Once an application with a linked resume reaches Applied, the resume is
  saved as a "sent" version named after the company, and the application keeps
  its id and the resume's Check score then.
- New columns: closed_reason, cover_letter_id (backfilled where exactly one
  letter was written for the application), sent_resume_version_id,
  sent_check_score and requirements.
- applications.ai.parsePosting reads a pasted link or posting. Links are
  fetched on the server: https only, public addresses checked at connect time,
  three redirects, 2 MB and 10 s at most. A page's JobPosting data fills the
  fields without AI; with a provider, the model reads role, company,
  location, salary and requirements.
- MCP application tools take closedReason and coverLetterId.
2026-09-28 21:44:55 +02:00
Amruth Pillai e26ce08fc5 feat(resume): check categories, stable issue keys, ignores and a two-column rule
- Every live check has a category (contact details, dates, layout, section
  headings, writing). Reports score the applicable rules, per category too.
- Findings carry a key that uses entry ids instead of array indexes, so it
  survives reordering. Keys in the new metadata.check.ignored set findings
  aside without counting them against the score.
- TWO_COLUMN_LAYOUT flags a two-column template that prints a sidebar.
- Full-width pages print no sidebar, so sections placed only there are now
  reported as never printing instead of passing as main-column content.
- metadata.check also holds job-posting terms hidden as not true; public
  viewers don't receive it.
- ats-pdf exports the job-description matcher, spelling variants and the
  semantics reader for the editor's job match and parser view.
2026-09-28 21:33:11 +02:00
Amruth Pillai 85352ee11b feat(schema): describe template layouts in one place
Columns, sidebar side, header placement and ATS safety for every template
now live in templateLayouts. The template gallery metadata and the layout
editor read it, and a DOCX test checks the two-column configurations
against it.
2026-09-28 19:04:03 +02:00
Amruth Pillai bda01febd5 feat(schema): structured resume dates with a read-time upgrade and dual write
Dated entries and roles carry dates (start, end, present, and raw when the
text couldn't be read exactly). The parser moves to the schema package and
reports how each date was written; parseResumeData fills dates, infers the
date format from how dates were typed and rewrites the legacy period/date
text from them, so older clients and API readers keep working. API writes
sync against the stored data, so an edit to the text alone is read back
into dates.

getById and getBySlug return upgraded data, ATS date rules and sorting read
dates, JSON Resume and LinkedIn imports map their dates directly, entry
titles may be empty (drafts aren't printed), and the MCP schema resource is
generated live in place of the stale schema.json.
2026-09-28 18:20:18 +02:00
Amruth Pillai 0f934bd849 feat(ui): adopt Desk & Paper tokens, fonts, System theme and restyled primitives
Replace the achromatic shadcn palette with the Desk & Paper tokens (warm
neutrals, one moss accent, danger, warn and info), exposed to Tailwind
under their spec names; the previous names resolve to the new tokens
until every screen is rebuilt. Hard-coded palette classes become semantic
tokens and stage colors follow the spec.

Fonts move to Newsreader, Hanken Grotesk and JetBrains Mono. The theme
gains a System option that follows the operating system live, applied
before first paint, and Base UI now receives the locale's direction.

Primitives follow the component spec: button variants primary,
secondary, ghost, danger and link with a loading state, accent focus
rings on inputs, SwitchRow, semantic badges, segmented and underline
tabs, restyled menus, dialogs, sheets, tooltips and command bar, and a
single bottom-center toast with an Undo action. New: IconButton,
SegmentedControl, RadioGroup and NativeSelect.
2026-09-28 16:29:30 +02:00
FalconSpyClaude Opus 5.5Amruth Pillaiautofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1b78e546e2 feat(applications): schedule interviews and view them on a calendar (#3539)
* feat(applications): schedule interviews and view them on a calendar

Interviews (screening, technical, behavioral, onsite, other) are stored as
"interview" entries on an application's activity timeline, so an application
can have any number of them and they show in its timeline without a
migration. Each interview has a start date-time (timezone-aware), duration,
and optional location and notes.

- schema: interview timeline entry type, interviewDetailsSchema, INTERVIEW_KINDS
- api: addInterview / updateInterview procedures (delete via timeline entry);
  generic timeline updates now only edit text on note entries
- web: Calendar view on the Applications page (month grid, type legend,
  upcoming list grouped by day, schedule button with application picker,
  per-day "+" and "+N more" popover), Interviews section and interview
  dialog in the application detail panel, interview rows in the timeline
  and CSV export
- mcp: add_application_interview / update_application_interview tools
- i18n: extract new strings into all locale catalogs (English fallback)
- docs: MCP tool table, scheduling guide section, resume-builder skill

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(applications): keep interview dates in local time and guard generic timeline edits

- Format the timeline date chip for interview entries in the viewer's local
  timezone so it matches the interview's date-time label; stage and note
  entries still render in UTC.
- Reject interview entries in the generic updateTimelineEntry path. A
  day-granular date edit kept the UTC time of day and could move an interview
  to the wrong local day; callers are pointed to updateInterview
  (update_application_interview). The MCP tool description now says so, and
  a service test covers the rejection.
- Associate each interview dialog label with its control via useId/htmlFor.
- Drop the duplicate onInput handler on the date-time input; onChange covers
  controlled inputs.
- Give the calendar's per-day schedule button an accessible name that
  includes the date, and update the extracted locale catalogs for the new
  message.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-09-28 08:57:25 +02:00
Amruth Pillai 96c7142fbc chore: update dependencies 2026-09-16 18:36:50 +02:00
Amruth Pillai dc8f9787a4 chore: update dependencies 2026-09-09 23:57:37 +02:00
Amruth Pillai 368858a56f feat(resume): add per-section heading visibility (#3477) 2026-09-05 20:34:21 -07:00
Amruth Pillai 870388192e feat(resume): add skill keyword list presentation (#3469)
* feat(resume): add skill keyword list presentation

* test(schema): refresh generated references
2026-09-05 19:41:14 -07:00
Amruth Pillai ab67831e4b feat: add cover and contain picture fitting (#3461)
* feat: add picture fit options

* fix: harden picture fit regressions

* fix: address picture fit review findings
2026-09-05 18:33:35 -07:00
Amruth Pillai 1d4194a207 feat: manage cover letters in a shared library (#3423)
* feat: add shared cover-letter library with resume styling

* fix: retain required sanitizer dependency in CI

* fix(cover-letters): prevent concurrent AI draft requests

* chore(codacy): exclude generated migrations

* fix(applications): keep Lingui macro out of callback dependencies
2026-09-05 10:01:22 -07:00
Emanuele TonelloandAmruth Pillai 1f0844b39c feat(applications): add contact email and phone (#3396)
* feat(applications): add contact email and phone

* fix(applications): validate imported contact emails

* fix(applications): validate all imported contact fields

* fix(applications): preserve data when contact validation fails

* test(applications): complete contact export fixture

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-05 09:51:21 -07:00
Diego Vega CentenoandAmruth Pillai 8df1b25550 feat(skills): add inline layout option for skill items (#3358)
* feat(skills): add inline layout option for skill items

* fix: restore default skills layout (regressed by inline feature)

- Restore metrics rowGap style for default layout
- Only render LevelDisplay inside the row for inline layout, not default

* refactor(pdf):  Extract inline skills style logic from JSX to reusable function

* test(pdf): add test coverage for inline skills item layout

- Add test suite SkillsSectionInlineFormat to verify isInlineSkillsItem and getSkillsItemStyle behavior

* test(pdf): add comprehensive test coverage for inline skills item style logic

- Test combinations of proficiency, level, and keywords fields (0, 1, 3 fields)

* test(schema): add test coverage for column equals 1 when layout is inline

* test(web): add component-level tests for inline and columns layouts

* test(import): add v4 parser-level test for missing skills layout

* docs: regenerate skills layout references

* test(docx): include skills layout in section fixtures

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-09-05 09:51:14 -07:00
Amruth Pillai 779ea5cb4a fix(resume): reject invalid submitted write values (#3413) 2026-09-05 08:51:55 -07:00
Amruth Pillai 7d809da6f8 feat(pdf): add opt-in German hyphenation (#3435) 2026-09-05 08:29:22 -07:00
Amruth Pillai 84645f122b chore: update dependencies 2026-09-04 11:05:22 +02:00
Amruth Pillai c288675b16 Release v5.2.9 (#3382)
* feat(ats): add ATS checker and replace resume analysis

Adds a public, browser-only ATS checker at /ats-checker and an ATS Check
section in the builder's right sidebar. PDFs are parsed locally: text
extraction, reading order, contact and date recovery, section detection,
and file-level readability are scored deterministically, with evidence
cited per finding and skipped checks reported rather than counted as
passes.

Removes the AI-scored resume analysis it supersedes: the resume_analysis
table (dropped via migration), the get_resume_analysis MCP tool, and
POST /ai/analyze-resume. The replacement, POST /ai/ats-review, reviews
extracted resume text and returns qualitative feedback with no score.

Also bumps the version to 5.2.9 and adds the changelog entry.

* chore(deps): bump workspace dependencies

* fix(ats-checker): keep negation inside each 'what this does not do' bullet

The three bullets were bare fragments whose negation came from the
section heading, which translators never see. A dozen locales rendered
them as affirmative assertions or imperatives, so the page claimed the
checker enforces a one-page rule and predicts rejection -- the opposite
of the source, and directly contradicted by the sentence beside it.

Each bullet now carries its own negation, so the polarity cannot be
lost in translation. Re-extracted and refilled across all 53 target
locales.
2026-08-27 03:37:01 +02:00
Amruth Pillai 3c195dc3f8 Release v5.2.8 (#3375)
Upgrades to Better Auth 1.7, expands Custom Styles coverage of item headers, and adds a human-approval step to the AI agent's resume edits.

Breaking for self-hosters using a custom OAuth provider: the callback path changes from /api/auth/oauth2/callback/custom to /api/auth/callback/custom, and installs using OAUTH_DISCOVERY_URL need one additional UPDATE after upgrading. Both are documented in docs/self-hosting/sso.mdx.

- Better Auth 1.7, with the account issuer migration and the jwks alg/crv columns the 1.7 jwt plugin requires
- Agent edits gated behind an approval step, with crash-safe runs and context pruning
- item-header now covers every section header row on every template; adds the item-header-row part
- Fixes provider unlinking, auth error messages, and version conflicts on freshly created resumes
- New /auth/error page, translated across all 53 target locales
- DeepSeek Harness plugin moved into packages/dsh-plugin
- Dependency bumps across the workspace
2026-08-24 21:44:16 +02:00
Amruth Pillai 9509b5bc2e refactor(stylesheet): move Semantic CSS to the browser (#3329) 2026-08-16 16:50:27 +02:00
Amruth PillaiandCursor Agent d2ffbf9618 feat: add semantic CSS stylesheets (#3274)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-07-30 12:39:15 +02:00
4ac19f81b3 fix: clamp page margin values to [0, 100] to prevent crash on paste (#3277)
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-07-29 18:13:42 +02:00
Amruth Pillai 9110e86997 refactor: ponytail audit 2026-07-27 20:26:16 +02:00
Diego Vega CentenoandAmruth Pillai 689e7e24d4 Filter invalid style intents to preserve valid custom styles (#3241)
* Filter invalid style intents to preserve valid custom styles

* fix: preserve valid custom style rules

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-07-09 15:50:34 +02:00
Amruth Pillai 18d0c14aa1 feat: add application timeline history (#3237)
* feat: add application timeline history

* fix: address application timeline review

* fix: keep application tracker e2e stable

* fix: use stable timeline e2e selector

* fix: target timeline note input in e2e
2026-07-09 00:36:45 +02:00
Amruth Pillai 90105cb148 chore: integrate improve-integration 2026-07-08 19:08:31 +02:00
Amruth Pillai b404dbd42a Add application tracker (#3220)
* feat(applications): job application tracker with AI copilot

Add an Applications module at /dashboard/applications: pipeline board
(dnd-kit), table view with bulk actions, Insights (fit tiles, funnel,
sources, shareable funnel-flow SVG), campaigns, tags, CSV import, and
Add/Edit/Detail slide-overs. Each application links a live Reactive
Resume.

AI "Application Copilot" (applications.ai.*): job-posting autofill,
resume↔job match score (fit ring), resume tailoring, and cover-letter /
follow-up drafting — via the user's configured provider.

Board cards + table rows get context menus (edit / move / archive /
delete). Charts are CSS/SVG (no new chart dep); adds a UI Checkbox.

Also includes local TanStack devtools setup and toolchain bumps.

Claude-Session: https://claude.ai/code/session_01TEeRHnEayw2MFCShFRyL5f

* feat(applications): close follow-up gaps + squash migrations

Finish the deferred/open items on the applications tracker:

- Cover-letter upload re-enabled. Fix the storage blocker by deriving the
  key extension from content type (buildFileKey/EXTENSION_BY_CONTENT_TYPE)
  instead of hardcoding .jpeg, so PDFs serve correctly and non-JPEG image
  avatars keep working under FLAG_DISABLE_IMAGE_PROCESSING. Add
  coverLetterUrl/coverLetterName columns + Documents-section upload/remove.
- Contacts editor in the detail sheet (add/edit/remove, keyed per app).
- Board caps rendered cards per column (COLUMN_PAGE_SIZE=50 + "Show more").
- Extract new Lingui messages across locales.
- Guard coverLetterUrl to http(s)/relative at the API boundary.

Squash the five branch-only application-table migrations (create -> +tags
-> +cover-letter -> drop -> re-add) into a single clean CREATE TABLE via
drizzle-kit generate.

Claude-Session: https://claude.ai/code/session_01TEeRHnEayw2MFCShFRyL5f

* chore: update dependencies

* fix(web): address React Doctor findings — compiler, purity, query, component structure

prefer-module-scope-pure-function: hoist buildSubtitle, getDecimalPlaces,
handleLocaleChange, onLocaleChange, stop, listContent/groupedListContent to
module scope so they aren't rebuilt on every render.

react-compiler-todo (??=): rewrite draft.metadata.styleRules ??= [] to the
non-assignment form to unblock auto-memoization.

set-state-in-effect: derive updatedAtLabel at render time instead of syncing
it through useState + useEffect.

query-destructure-result: destructure useQuery results at call site in
resume-analysis and resume-thumbnail to follow TanStack Query v5 convention.

only-export-components: extract non-component exports to sibling .ts files so
Fast Refresh can preserve component state:
  - getNextWeights → typography/get-next-weights.ts
  - detectJsonImportType + ImportType → dialogs/resume/import.utils.ts
  - getLocaleOptions → features/locale/locale-options.tsx
  - preview helpers + DEFAULT_PDF_PAGE_SIZE → preview.shared.utils.ts
  - resolveHighlightToolbarState + defaultHighlightColor → rich-input.utils.ts
  - computeDelta + getSparklinePoints → statistics.utils.ts

no-multi-comp: split multi-component files into focused companions:
  - ResumePane + ToolbarButton → routes/agent/-components/resume-pane.tsx
  - DesktopBuilderShell → builder/$resumeId/-components/desktop-builder-shell.tsx
  - MobileBuilderShell + helpers → builder/$resumeId/-components/mobile-builder-shell.tsx
  - setBuilderLayout/getBuilderLayout moved to -store/sidebar.ts

fix(tests): add Resume type import to section-builder mocks and cast partial
mock data as unknown as Resume to satisfy stricter type checking; fix
noExplicitAny Biome errors in the same mocks.

* feat(applications): improve performance

* chore: fix knip issues

* perf(builder): halve per-keystroke render cost

Section-form fields called `form.handleSubmit()` on every keystroke, which
re-validated the whole form and toggled submit state — firing the render
cascade twice per character (~6809 renders/keystroke, FPS dropping to 9).

Persist via a form-level `listeners.onChange` instead and drop the per-field
`handleSubmit()` (basics, custom-fields, design). Narrow header/dock resume
subscriptions to metadata slices so they no longer re-render on content edits.

Cuts renders 6809 -> 3403 per keystroke (50%), 0 frame drops. Save, preview,
and design controls verified working; 449/449 web tests pass.

* perf(home): eliminate hero CLS from unreserved video box

The hero <section> is `flex items-center` (shrink-to-fit), so the video
wrapper's width depended on the video's intrinsic size, which only resolves
after the media loads. aspect-ratio couldn't reserve height without a definite
width, so the video grew from ~190px to ~563px after first paint and shoved the
centered hero text down ~373px (CLS ~0.095).

Give the wrapper a definite width (w-full + mx-auto on the CometCard) and set an
explicit aspect ratio + width/height on the video so its box is reserved before
load. CLS 0.095 -> 0; hero stays visually centered at max-w-4xl.

* docs: add application tracker guides

* chore(db): squash application migrations

* fix(email): import React in auth template for server-side rendering compatibility

* chore(release): v5.2.1

* Refactor resume rendering and builder workflows

* fix: address application tracker review findings
2026-07-05 23:44:04 +02:00
Amruth Pillai 7e35e8b657 chore(schema): delete tautology test, add helpers, collapse styleRuleSlots
- Delete templates.test.ts: re-tests z.enum semantics with a hardcoded
  fixture that duplicates the template list in templates.ts.
- default.ts: add 2-line section(icon) helper; 12 repeated 7-field blocks
  collapse to one-liners. Output is byte-identical.
- data.ts: add 2-line itemSection<T> factory; 12 baseSectionSchema.extend()
  blocks collapse to one-liners. Inferred types unchanged.
- data.ts: replace 15-field hand-listed styleRuleSlotsSchema with
  z.partialRecord(styleSlotSchema, styleIntentSchema); parse behaviour and
  TypeScript type are equivalent (unknown keys still rejected).

Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa
2026-07-04 19:38:01 +02:00
Amruth Pillai d87c6758ab chore: update dependencies 2026-07-04 19:06:31 +02:00
Amruth Pillai 57e9c8c487 v5.2.0: undo/redo, version history, embedded AI assistant, mobile builder & more (#3205) 2026-07-04 14:57:25 +02:00
Amruth Pillai a4999c04af refactor: remove dead code, unused exports and redundant dependencies
- drop dotenv (Node 24 process.loadEnvFile) and dompurify (only used by dead code)
- delete unused ui components/hooks (card, progress, checkbox, use-confirm, use-prompt)
- delete dead sanitizeHtml/sanitizeCss, url-security helpers, patch-resume tool,
  schema/page, createResumePatches, patch-proposal preview builder, fonts fallback helpers
- inline single-caller wrappers (flags service, auth getSession, pdf renderer passthrough)
- deduplicate template color helpers into shared/color-helpers
- unexport 50+ internal-only symbols, remove dead export-map entries
- replace hand-rolled unique()/useIsMobile with Set spread and usehooks-ts
2026-07-03 20:04:36 +02:00
Amruth Pillai d3735ebe27 chore: update dependencies 2026-06-29 09:09:00 +02:00
Amruth Pillai 37faf592b7 chore: update dependencies 2026-06-17 10:40:23 +02:00
Amruth Pillai 042d076efa chore: update dependencies 2026-06-05 23:35:23 +02:00
Amruth Pillai 5fb4976ec9 feat: add hide link underline option to resume settings, resolves #3134 2026-06-01 15:30:49 +02:00
JamesGoslingscoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>Amruth Pillai
b932711f08 feat: add section heading icons to PDF templates (#3127)
* feat: add section heading icons to PDF templates

Add customizable Phosphor icons before section titles in PDF output.
Users can toggle visibility globally via a new "Hide section heading icons"
switch (independent of item-level icons) and customize individual section
icons through the builder sidebar icon picker.

- Add `icon` field to `baseSectionSchema` and `summarySchema`
- Add `hideSectionIcons` to `pageSchema` (defaults to true for backward compat)
- Implement `SectionHeadingIcon` component with heading font-size scaling
- Support "none" sentinel for per-section icon hiding
- Fallback to sensible defaults (briefcase, graduation-cap, etc.) for legacy data
- Add icon picker to builder sidebar sections and custom section dialogs

Closes #2632

* test: add unit tests for section heading icons

- Add tests for getResumeSectionIcon() covering built-in sections,
  summary, custom sections, "none" sentinel, and default fallbacks
- Add schema tests for baseSectionSchema icon field, summarySchema icon,
  and pageSchema hideSectionIcons default behavior

* refactor: minor updates to icon display

* Update apps/web/locales/es-ES.po

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-06-01 14:02:42 +02:00
Amruth Pillai 8e72311bc6 Merge branch 'main' of github.com:amruthpillai/reactive-resume 2026-06-01 10:31:53 +02:00
Amruth Pillai 0df7f21130 feat: implement download_resume_pdf mcp tool 2026-06-01 10:26:28 +02:00
Amruth PillaiandCursor Agent 1414fecade fix(pdf): apply custom style fontSize to icons and level indicators (#3120) and
* fix(pdf): apply custom style fontSize to icon and level indicator sizes

Map fontSize from Icon and Level Indicator custom style slots to Phosphor
icon size and level indicator dimensions, since react-pdf icons ignore
fontSize in favor of the size prop.

* fix: separate global icon and scoped level indicator font sizes

Icon slot fontSize now drives all resume icons plus level display
decorations. Level indicator fontSize overrides only within level display.
Shared sizing logic lives in schema; design sidebar preview uses global rules.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-05-29 00:41:21 +02:00