Описание проблемы
Для меня всегда был острым вопрос поддержания резюме в актуальном состоянии. Казалось бы, задача простая, но на самом деле она достаточно сложная, ведь резюме — это не только список мест работы, но и достижения, детали проектов, стек технологий, актуальные навыки и т. п.
Все это очень важно, чтобы простой листок бумаги хорошо отображал мой опыт и не возникало необходимости вспоминать всё по памяти на интервью с HR и не только.
Резюме нужно не только для HR
На технических интервью меня часто просили указать проекты, на которых работал, перечислить технологии и занимаемую позицию (backend, frontend, fullstack). Актуализированное резюме помогало и здесь выстроить структурированный ответ.
1. Проблема: Стилизация и содержание
Раньше я поддерживал резюме в Notion, но мне не нравилось, что я постоянно менял стили, разметку, цвета и думал, как это лучше выглядит. Дизайнер из меня так себе 😅
Еще больше мне не нравилось, что в момент верстки я думал над содержанием, а это ведь самое важное. Как лучше написать достижения, какие слова использовать, измеримо ли это достижение или просто "вода" — все эти вопросы постоянно висели в воздухе и добавляли неуверенности в том, что делаешь.
2. Проблема: Большой опыт
Можно сделать резюме и перечислить последние 5 лет опыта, но я не хотел выбрасывать свой релевантный опыт просто ради того, чтобы уместить всё резюме на одной странице. Описанный более "древний" опыт мне нужен, чтобы отвечая на вопросы о проектах и интересных/сложных задачах/релевантном опыте, мучительно не вспоминать, а что именно я делал на проекте, допустим, 6 лет назад. Я хочу иметь эту информацию в быстром доступе.
За десять лет я сменил шесть компаний, в некоторых работал над разными проектами, с разным стеком. Писал несколько лет на Java, Scala, JavaScript (потому что frontend) и последние три года пишу на TypeScript.
Мне без разницы, на каком языке программирования писать код, главное чтобы работа была интересной. Важно, чтобы резюме отображало весь релевантный опыт, открывая возможности для вакансий, даже если они ещё не опубликованы.
3. Проблема: Нужно иметь несколько вариантов резюме
Я полностью согласен с тем, что резюме не должно быть одним для всех возможных вакансий, а быть нацеленным на определенную группу.
Еще можно указывать сопроводительное письмо к вакансии, мне кажется, это как минимум поднимет настроение HR 😅
Все это приводит к тому, что нужно иметь несколько актуальных резюме. Что еще больше добавляет сложности к задаче. 🫤
Поиск решений
Я не рассматривал платные приложения для создания резюме, потому что в таком случае появляется зависимость от сервиса. Не всегда понятно, что и в каком виде ты получишь на выходе за свои деньги. Зачастую, нет гибкости шаблона, который может не устраивать по тем или иным причинам.
На просторах интернета я нашел много постов людей, которые искали решение на мою проблему. Одни предлагали хранить резюме в markdown, а потом через конвертеры переводить в PDF. Решение других мне понравилось больше, оно было про хранение резюме в JSON и его дальнейший рендеринг через шаблонизатор.
JSON Resume
Есть такой проект, JSON Resume. Он предлагает следующую идею: пишем свой опыт в JSON документа, выбираем шаблон, рендерим наш опыт в шаблон и получает HTML страницу.
Минусы этого проекта для меня следующие:
сложно найти шаблон, многие устаревшие, все разбросано в NPM JS репозитории
некоторые рендер функции шаблонов не соответствуют схеме JSON объектов (на выходе отображается не все)
есть JSON схема, но нет TypeScript типов 🤦♂️. Пришлось использовать кодогенератор.
Плюсы:
хорошая идея, позволяющая разделить момент написания содержания резюме от представления. Эта идея решает одну из главных моих проблем, описанных вначале статьи.
Решение и подготовка требований
Вдохновившись идей JSON Resume, я решил написать свое решение, которое будет удобным в использовании и полностью закрывать проблему создания резюме.
Главное требование - дать пользователю песочницу, в которой можно быстро создать свое резюме и сфокусироваться на его содержании.
Важное условие - не загружать пользователя дополнительными действиями в виде регистрации, поиска шаблонов и другими "плясками" 😂
JSON-объект, описывающий резюме и его JSON схема
Главная причина, по которой я выбрал формат JSON для описания резюме, это возможность проверки JSON-объекта по JSON-схеме.
Пока я остановился на том, чтобы JSON объект состоял из трех свойств:
Me (персональная информация типа имени, контакты, профили соц сетей...)
EmploymentHistory (в каких компаниях работал, какие проекты были, какую роль на проекте выполнял..)
Technologies (это справочник технологий, с которыми работал. id этих технологий можно использовать в секции EmploymentHistory)
Создать JSON схему совсем не сложно, ведь в Effect можно описать схему через TypeScript и сгенерировать JSON версию.
Часть схемы описанной через Effect
import { Schema as S } from "effect"
export class Me
extends S.Class<Me>("Me")({
name: S.NonEmptyString,
coverLetter:
S.Struct({
position: S.NonEmptyString,
content: S.NonEmptyString.pipe(S.NonEmptyArray)
}).pipe(S.optional),
expertise: S.NonEmptyString.pipe(S.NonEmptyArray),
location: S.NonEmptyString.pipe(S.optional),
phone: S.NonEmptyString.pipe(S.optional),
email: S.NonEmptyString,
profiles:
S.Struct({
url: S.NonEmptyString.pipe(S.pattern(httpsRegex)),
icon: S.NonEmptyString
}).pipe(
S.NonEmptyArray
),
expertSummary:
S.NonEmptyString.pipe(
S.NonEmptyArray
)
}) { }
export class ResumeObject
extends S.Class<ResumeObject>("ResumeObject")({
$schema: S.NonEmptyString.pipe(S.optional),
me: Me,
technologies: ProjectTechnology.pipe(S.NonEmptyArray),
employmentHistory: EmploymentRecord.pipe(S.NonEmptyArray),
}) { };
Интерфейс
Определиться с тем, какие UI элементы должны быть на странице, оказалось не сложно. Я представил сценарий пользователя, который хочет написать свое резюме. Нужно предоставить следующее:
Редактор кода для JSON-объекта
Переход в режим просмотра для сохранения отрендереного резюме в PDF
Редактор JSON (Editor вкладка)
Работать с большим JSON объектом не очень удобно. Поэтому, для решения этой проблемы я решил дать возможность пользователю использовать удобный редактор Monaco Editor (он используется в VSCode), проверять JSON по схеме (чтобы были подсказки от редактора).
Скриншот режима редактирования

Еще, я решил добавить в интерфейс выпадающий список "Current section", который позволяет сужать JSON объект по определенной секции, чтобы сделать навигацию по большим JSON объектам более удобной.
Скриншот с выпадающим списком секций

Режим просмотра (View вкладка)
В режиме просмотра можно распечатать резюме или сохранить в PDF. Есть плавающая кнопка "Print", для быстрого вызова окна печати.
Скриншот режима просмотра

В режиме редактирования и просмотра можно менять варианты резюме из выпадающего списка.
Скриншот с выдадающим списком резюме

Техническая реализация
В качестве UI библиотеки я использовал AlpineJS.
Как я уже сказал, для редактора я подключил Monaco Editor. Для интегрирования этого редактора в браузере есть отличная библиотека Monaco-Loader.
Я большой фанат декларативного подхода и поэтому использовал Tailwind, для того чтобы в html сразу указать еще и стиль элементов, без необходимости писать CSS в отдельных местах.
Ну и естественно TypeScript 😀
Подведем итоги
я сделал инструмент, который доступен в использовании по ссылке
инструмент работает в браузере пользователя, все варианты резюме сохраняются в local storage браузера (в будущем можно сделать PWA, чтобы выглядело как отдельное приложение)
инструмент позволяет сфокусироваться на написании содержимого резюме, а не на представлении
я не выкинул свой опыт, описал все в JSON, а в представлении показываю развернуто позиции, на которых я работал последние 5 лет. Остальные компании, "схлопываются". Но информация для меня не теряется.
Схлопнутые проекты компаний

Ссылки
Сам инструмент: CV Maker.
Исходный код можно найти тут.
Буду рад обратной связи, отвечу на вопросы в комментариях, спасибо что прочли статью.