Import the server image reader with its explicit TypeScript extension so tsx does not resolve it as a native addon. Use the workspace automatic JSX configuration for the dev server so shared PDF components do not fall back to React.createElement.
Porygon lays the resume out as a ruled form after the Japanese résumé
form (rirekisho). The header is a block of bordered field cells framed
in the accent color with the photo in a cell of its own, and every
section is a table with a solid title bar over one ruled cell per
entry. Touching cells share one tinted rule.
Smeargle sets the resume like a magazine feature: the headline as an
uppercase kicker over a display name, the summary as an italic
standfirst, and italic section headings at the user's heading size.
Both are one-column and ATS-safe. Register them in the schema, renderer,
semantic manifests and gallery, add gallery and docs previews, extract
the new descriptions, regenerate the API spec, and list them wherever
the docs enumerate templates.
Forme's Text draws no background, border or padding of its own. A block
text carrying any of them is now wrapped in a box that paints them, the
way texts inside rows already were.
Section headings rendered as filled bars or underlined titles vanished
whenever section icons were hidden (Kakuna, Meowth, Rhyhorn, Chikorita,
Leafish, Gengar, Ditgar, Glalie and Pikachu lost their heading rules), and
text-only contact links lost their box styles. The 1pt gap between a
section icon and its title, already requested by the shared heading code,
now takes effect too.
Resource-oriented REST aliases cover file imports (PDF text layer, JSON
Resume, Reactive Resume v4/current, LinkedIn), PDF/DOCX/Markdown/JSON
exports for resumes and cover letters, editor content checks, job-term
matching and a public PDF readability checker. Collection endpoints accept
limit/offset with X-Total-Count headers, and PATCH routes cover partial
updates. Existing routes and response shapes stay unchanged.
The OpenAPI spec marks public operations with `security: []`, the REST
surface gets a 40 MiB body limit, and Better Auth publishes its own
OpenAPI schema. Cookie sessions are rejected for cross-origin requests.
DOCX export parses HTML with node-html-parser so it runs on the server,
and PDF line extraction moves to @reactive-resume/import for reuse.
The Lingui Vite plugin transforms macros itself, so the Babel preset and
its plugin dependency go. TanStack Router's split-route query hides the
`.tsx` extension, so the parser is told to read TSX explicitly.
Glalie's contact box let long emails and links run past its border: the
converter dropped a link's lone text into a shared inline run, losing its
box styles, so Forme sized it to its full width. A lone text now converts
as its own block, and Glalie's contact text takes the rest of the row so
Forme wraps it inside the box.
Section heading icons sat at the top of the title's line box, above the
text. The icon now moves down by half the leftover line height and never
exceeds the line, so it stays level with the title in every template.
Keep manual preparation available without provider credentials.
Share bounded search and reading across Applications and the assistant
with one selected Firecrawl, Tavily, or Exa connection.
Backfill encrypted Firecrawl credentials without decrypting or removing
legacy rows. Add nullable posting-source metadata to applications.
* fix(dsh-plugin): accept the DSH 0.2 host line in peer ranges
The Harness peer ranges pinned `^0.1.0-rc.6`, which the 0.2.0-rc.2 host
rejects, so a profile on the new core refused to load the plugin:
Plugin dsh-plugin-reactive-resume@0.1.0 is incompatible with dsh 0.2.0-rc.2
The host decides that with
`semver.satisfies(runtime, range, { includePrerelease: true })`. Under that
mode the upper bound is what fails: `^0.1.0-rc.6` expands to
`>=0.1.0-rc.6 <0.2.0-0`, and `0.2.0-rc.2` sorts above `0.2.0-0` because the
numeric identifier `0` precedes `rc`.
npm's default mode, which the plugin market's checker uses, is stricter: a
prerelease only satisfies a comparator set that pins the same
major.minor.patch tuple with a prerelease of its own. There the bare
`^0.1.0-rc.6` admits only `0.1.0-rc.6` through `0.1.0-rc.8`;
`>=0.1.0-rc.6 <0.3.0-0` still admits only those three, and `*` admits none of
the 29 published releases. An explicit union is the only form both modes
accept, so the MCP bridge peer and the prompt peer both become
`^0.1.0-rc.6 || ^0.2.0-rc.1`.
The union is additive: everything the old range admitted is still admitted.
`devDependencies` move to `^0.2.0-rc.2` so the package develops against the
core it now claims.
No source change was needed. `dsh-mcp-client@0.2.0-rc.2` keeps its `Config`
union, its `apply(ctx, config)` signature, and the
`mcp__<serverName>__<rawName>` public tool name, while
`dsh-system-prompt@0.2.0-rc.2` keeps `section({ name, order, text })`. The
0.2 additions to the bridge — MCP resource publishing and a
server-instructions prompt section — are additive and scoped to
`ctx.inject(["mcpResources"])` and `ctx.inject(["systemPrompt"])`, neither of
which this package depends on.
The README records the two comparison modes, since the prerelease rule makes
the obvious alternatives silently wrong.
* fix(dsh-plugin): refresh DSH 0.2 lockfile
---------
Co-authored-by: ddddd-ren <ddddd-ren@users.noreply.github.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
Fix authentication recovery, account imports, application tracking, resume
editing and exports, sharing, API contracts, provider selection, and private
local attachments. Preserve authored content during PDF pagination.
Update guides, generated OpenAPI output, and translation catalogs to match
verified behavior and documented constraints.
Validation: 1,019 tests passed; 12 database/OAuth integration tests skipped.
Ten affected package typechecks, production build, Biome, and package
boundaries passed.
Every scrolled frame repainted the whole sticky stage: the fading title, contact sheet, labels and caption painted into it, and the template wipe animated clip-path over full pages. Android Chromium could not raster that during a fling and showed blank tiles.
Give each scroll-driven element its own layer, fade the contact sheet once instead of per thumbnail, and wipe by sliding clipped layers and moving the divider with a transform. Raster work across the scene drops about sevenfold in an emulated Pixel 7 trace.
Rewrite every guide for the redesigned app, add guides for new features (documents, editor modes, check, cover letters, assistant, applications, self-hosting upgrade and environment reference), remove v5-only pages with redirects, and replace every screenshot.
The unanchored screenshots pattern in .vercelignore also matched
apps/web/public/screenshots, so the manifest's screenshots 404ed on Vercel.
Anchor it to the root and replace the screenshots with the redesigned app.
Forme 0.25 stretches the last box of a splitting column down to the page's
end, so Azurill's timeline dot grew into a pill. A plain box around the dot
now takes the stretch.
Replace the Type presets with five traditional resume faces: EB Garamond,
Tinos, Source Serif 4 with Source Sans 3, Carlito and Lato. Presets now set
body text in Regular and Bold (400/700), which every one of them ships.
Add a Custom row under the presets. It shows the resume's own fonts when they
match no preset, and opens Advanced (even when collapsed) at the Typography
editor, focusing the body font picker. On phones it switches the Design sheet
to the Page tab first.
The mobile editor body now clips instead of hiding overflow, so scrolling
inside the lowered Design sheet can no longer shift the sheet itself.
Forme hyphenates every language it has patterns for, so drop the German-only
gate on soft-hyphen decoding and the "Currently supports German" schema note.
Vercel now deploys Reactive Resume as two services in one project:
`frontend` serves the static Vite build from apps/web/dist, and
`backend` runs the Hono server Function from apps/server. Top-level
rewrites send server-owned paths (/api, /uploads, /mcp, /.well-known,
robots.txt, sitemap.xml, llms.txt, schema.json, index.html) and every
path without a file extension to `backend`, so HTML shells keep their
injected SEO metadata. Paths with a file extension go to `frontend`.
The service builder needs a few accommodations:
- apps/server/vercel.mjs replaces api/index.mjs as the entrypoint,
because a service entrypoint must exist before the build runs.
- `outputDirectory: "."` stops the builder from using the Docker
entrypoint in dist/ as the Function handler.
- The builder loads external CommonJS dependencies through pnpm links
that it leaves out of the Function. ioredis and react-reconciler are
now bundled with their dependencies, and bcrypt is replaced with
bcryptjs, which reads and writes the same $2b$ hashes.
The Vercel compatibility workflow now builds with the services
framework and loads a copy of the backend Function outside the
checkout, so a dependency missing from the Function fails CI. The stale
PDFKit trace checks are removed.
Existing Vercel installations must set Framework Preset to Services
before redeploying; the self-hosting guide documents this.
- Add a Questions section to the homepage: eight answers as folded paper
notes that unfold from their crease, with a pencil circle and underline
drawn on open, a new doodle, and FAQPage structured data rendered from
the same localized answers.
- Prerender /ats-checker per locale alongside the homepage
(dist-prerender/<page>/<locale>.html) and add a "What it checks"
section; PDF.js and the importers now load only once a file is chosen.
- Make the server the single owner of SEO head tags: canonical, hreflang,
social cards with og:locale and the page's localized title, and JSON-LD
with an Organization entity. The router now sets only the title,
description and robots tags, so nothing is duplicated after startup and
the ATS checker keeps its structured data.
- Add hreflang alternates to the sitemap, expand llms.txt, and delete the
stale v5 robots.txt and sitemap.xml from public/.
- Draw decorative heading and typed-text layers as generated content, so
page text holds each heading once.