fix(career): public CV deep links work on direct load, refresh, and shared links
CI and Deploy / test (push) Failing after 1m55s
CI and Deploy / deploy (push) Has been skipped

Phase 4.5 (priority 4). The app is a React Router SPA behind Next static
export, which only generated `/` — so a hard load of any deep path (/cv/{slug},
/login, /career/builder/…) hit Next's client not-found before React Router
could route it. Replace the single app/page.tsx with an optional catch-all
app/[[...slug]] (server page + client shell so generateStaticParams stays
server-only) that matches every path; nginx already serves index.html for
unknown paths (try_files), so React Router now owns routing on direct load.

Also: PublicCvPage shows a friendly 404 empty state and sets the document
title. Verified live — /login and /cv/{slug} both resolve on direct navigation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-18 10:34:56 +02:00
parent 17edf19f89
commit 585047da9e
4 changed files with 37 additions and 15 deletions
+9 -3
View File
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { api, getApiErrorMessage } from "../api";
import { api } from "../api";
// Anonymous read-only public CV at /cv/:slug. Renders the server-produced HTML in a sandboxed
// iframe. noindex is enforced server-side (X-Robots-Tag) and reinforced with a meta tag here.
@@ -18,8 +18,14 @@ export default function PublicCvPage() {
let alive = true;
api.get<{ html: string; name: string }>(`/public-cv/${slug}`)
.then((r) => { if (alive) setHtml(r.data.html); })
.catch((err) => { if (alive) setError(getApiErrorMessage(err, "This CV is not available.")); });
.then((r) => { if (alive) { setHtml(r.data.html); if (r.data.name) document.title = `${r.data.name} — CV`; } })
.catch((err) => {
if (!alive) return;
// 404 = unknown slug or the owner made it private again. Anything else is a transient error.
setError(err?.response?.status === 404
? "This CV isnt available. The link may be wrong, or the owner has made it private."
: "This CV cant be loaded right now. Please try again in a moment.");
});
return () => {
alive = false;