src/lib/resume-templates.ts
Rama main · réplica de lectura del repositorio original.
/**
* The six templates, in one place.
*
* They were written out by hand in four places that had no reason to agree:
* `get_resume_format`'s handler, the Design popover's select, the new-resume
* dialog's cards, and `PHOTO_TEMPLATES` in resume-paper.tsx. Four lists, one
* subject — the same shape LINES_PER_PAGE and LETTER_LABEL each cost this
* codebase once.
*
* PURE and client-safe, beside resume-text.ts and for the same reason: the
* editor and the paper are client components, and the tool handler is not.
*
* `template` is a plain String column on Resume with a default of "harvard",
* NOT part of the resume document contract in resume-schema.ts. Adding a value
* here touches no zod schema and no saved `Resume.data`.
*/
export type ResumeTemplate = {
key: string;
/** What the picker calls it. */
name: string;
/** One clause, for the card in the new-resume dialog. */
hint: string;
/** The paragraph get_resume_format hands an assistant choosing one. */
description: string;
/** False where the format's own convention forbids one: harvard, ats. */
takesPhoto: boolean;
/** False where the template ignores `accent` and prints black: ats. */
takesAccent: boolean;
};
export const DEFAULT_TEMPLATE = "harvard";
export const RESUME_TEMPLATES: readonly ResumeTemplate[] = [
{
key: "harvard",
name: "Harvard",
hint: "Dense, black and white, the academic standard",
description:
"DEFAULT. The Harvard OCS format: Times-metric serif, everything one size, name and section headings centred over full-width rules, each entry two justified lines (organisation/location, then role/dates). Dense, black-and-white, maximally ATS-safe. Use this unless asked otherwise.",
// The format's own convention has no photograph on it.
takesPhoto: false,
takesAccent: true,
},
{
key: "classic",
name: "Classic",
hint: "Serif headings, centred",
description:
"Serif headings, centred header. Timeless, ATS-safe. Takes a photo, centred above the name.",
takesPhoto: true,
takesAccent: true,
},
{
key: "modern",
name: "Modern",
hint: "Sans-serif, accent rules",
description:
"Sans-serif, accent rules, left-aligned header. Takes a photo, beside the name.",
takesPhoto: true,
takesAccent: true,
},
{
key: "compact",
name: "Compact",
hint: "Tight leading, fits the most",
description:
"Tight leading, two-column skills. Fits the most content. Takes a photo, beside the name.",
takesPhoto: true,
takesAccent: true,
},
{
key: "editorial",
name: "Editorial",
hint: "Large display name, generous space",
description:
"Large display name, generous whitespace, magazine feel. Takes a photo, squared off beside the name.",
takesPhoto: true,
takesAccent: true,
},
{
key: "ats",
name: "Plain (ATS)",
hint: "One column, black, every link printed as its URL",
description:
"Plain, single column, black on white, no accent colour and no photo. Conventional headings, dates as ordinary text, real list markers, and every link printed as its URL rather than as a label with the address hidden in the markup. Reach for it when a portal is going to parse the file rather than a person read it, or when somebody asks for something 'ATS-friendly' — and say plainly that this is a smaller difference than the internet claims. What it does change: harvard and the others print a labelled link as its label, so a text extractor sees the label and never the address; here every address is on the page.",
takesPhoto: false,
takesAccent: false,
},
];
const byKey = new Map(RESUME_TEMPLATES.map((template) => [template.key, template]));
export const TEMPLATE_KEYS: string[] = RESUME_TEMPLATES.map((template) => template.key);
/** Unknown keys fall through to the default's answer, which is the safe one. */
export function templateTakesPhoto(key: string): boolean {
return byKey.get(key)?.takesPhoto ?? byKey.get(DEFAULT_TEMPLATE)!.takesPhoto;
}
export function templateTakesAccent(key: string): boolean {
return byKey.get(key)?.takesAccent ?? true;
}