design nosepass template, add tests, add template previews

This commit is contained in:
Amruth Pillai
2023-11-17 08:31:12 +01:00
parent 0b4cb71320
commit 34247f13b6
92 changed files with 24440 additions and 35518 deletions
+8 -1
View File
@@ -8,6 +8,7 @@ type PictureProps = {
export const Picture = ({ className }: PictureProps) => {
const picture = useArtboardStore((state) => state.resume.basics.picture);
const fontSize = useArtboardStore((state) => state.resume.metadata.typography.font.size);
if (!isUrl(picture.url) || picture.effects.hidden) return null;
@@ -15,11 +16,17 @@ export const Picture = ({ className }: PictureProps) => {
<img
src={picture.url}
alt="Profile"
className={cn("relative z-20 object-cover", className)}
className={cn(
"relative z-20 object-cover",
picture.effects.border && "border-primary",
picture.effects.grayscale && "grayscale",
className,
)}
style={{
maxWidth: `${picture.size}px`,
aspectRatio: `${picture.aspectRatio}`,
borderRadius: `${picture.borderRadius}px`,
borderWidth: `${picture.effects.border ? fontSize / 3 : 0}px`,
}}
/>
);
+2 -2
View File
@@ -1,5 +1,5 @@
import { SectionKey } from "@reactive-resume/schema";
import { pageSizeMap, TemplateKey } from "@reactive-resume/utils";
import { pageSizeMap, Template } from "@reactive-resume/utils";
import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useMemo, useRef } from "react";
import { ReactZoomPanPinchRef, TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
@@ -12,7 +12,7 @@ export const BuilderLayout = () => {
const transformRef = useRef<ReactZoomPanPinchRef>(null);
const format = useArtboardStore((state) => state.resume.metadata.page.format);
const layout = useArtboardStore((state) => state.resume.metadata.layout);
const template = useArtboardStore((state) => state.resume.metadata.template as TemplateKey);
const template = useArtboardStore((state) => state.resume.metadata.template as Template);
const Template = useMemo(() => getTemplate(template), [template]);
+2 -2
View File
@@ -1,5 +1,5 @@
import { SectionKey } from "@reactive-resume/schema";
import { TemplateKey } from "@reactive-resume/utils";
import { Template } from "@reactive-resume/utils";
import { useMemo } from "react";
import { Page } from "../components/page";
@@ -8,7 +8,7 @@ import { getTemplate } from "../templates";
export const PreviewLayout = () => {
const layout = useArtboardStore((state) => state.resume.metadata.layout);
const template = useArtboardStore((state) => state.resume.metadata.template as TemplateKey);
const template = useArtboardStore((state) => state.resume.metadata.template as Template);
const Template = useMemo(() => getTemplate(template), [template]);
+1 -1
View File
@@ -19,5 +19,5 @@
}
.wysiwyg {
@apply prose max-w-none text-current prose-headings:mt-0 prose-headings:mb-2 prose-p:mt-0 prose-p:mb-2 prose-ul:mt-0 prose-ul:mb-2 prose-li:mt-0 prose-li:mb-2 prose-ol:mt-0 prose-ol:mb-2 prose-img:mt-0 prose-img:mb-2 prose-hr:mt-0 prose-hr:mb-2 prose-p:leading-normal;
@apply prose max-w-none text-current prose-headings:mt-0 prose-headings:mb-2 prose-p:mt-0 prose-p:mb-2 prose-ul:mt-0 prose-ul:mb-2 prose-li:mt-0 prose-li:mb-2 prose-ol:mt-0 prose-ol:mb-2 prose-img:mt-0 prose-img:mb-2 prose-hr:mt-0 prose-hr:mb-2 prose-p:leading-normal prose-li:leading-normal;
}
+21 -21
View File
@@ -79,11 +79,11 @@ const Summary = () => {
return (
<section id={section.id}>
<div className="mb-2 hidden font-bold uppercase text-primary group-[.main]:block">
<div className="mb-2 hidden font-bold text-primary group-[.main]:block">
<h4>{section.name}</h4>
</div>
<div className="mb-2 hidden items-center gap-x-2 text-center font-bold uppercase text-primary group-[.sidebar]:flex">
<div className="mb-2 hidden items-center gap-x-2 text-center font-bold text-primary group-[.sidebar]:flex">
<div className="h-1.5 w-1.5 rounded-full border border-primary" />
<h4>{section.name}</h4>
<div className="h-1.5 w-1.5 rounded-full border border-primary" />
@@ -162,18 +162,18 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<div className="mb-2 hidden font-bold uppercase text-primary group-[.main]:block">
<div className="mb-2 hidden font-bold text-primary group-[.main]:block">
<h4>{section.name}</h4>
</div>
<div className="mx-auto mb-2 hidden items-center gap-x-2 text-center font-bold uppercase text-primary group-[.sidebar]:flex">
<div className="mx-auto mb-2 hidden items-center gap-x-2 text-center font-bold text-primary group-[.sidebar]:flex">
<div className="h-1.5 w-1.5 rounded-full border border-primary" />
<h4>{section.name}</h4>
<div className="h-1.5 w-1.5 rounded-full border border-primary" />
</div>
<div
className="grid gap-3 group-[.sidebar]:mx-auto group-[.sidebar]:text-center"
className="grid gap-x-6 gap-y-3 group-[.sidebar]:mx-auto group-[.sidebar]:text-center"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -193,19 +193,19 @@ const Section = <T,>({
className,
)}
>
<div className="leading-snug">{children?.(item as T)}</div>
<div>{children?.(item as T)}</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
<div className="absolute left-[-4.5px] top-px hidden h-[8px] w-[8px] rounded-full bg-primary group-[.main]:block" />
</div>
@@ -223,7 +223,7 @@ const Profiles = () => {
return (
<Section<Profile> section={section}>
{(item) => (
<div className="leading-snug">
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
@@ -258,7 +258,7 @@ const Experience = () => {
<div className="font-bold">{item.company}</div>
<div>{item.position}</div>
<div>{item.location}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -276,7 +276,7 @@ const Education = () => {
<div>{item.area}</div>
<div>{item.score}</div>
<div>{item.studyType}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -292,7 +292,7 @@ const Awards = () => {
<div>
<div className="font-bold">{item.title}</div>
<div>{item.awarder}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -308,7 +308,7 @@ const Certifications = () => {
<div>
<div className="font-bold">{item.name}</div>
<div>{item.issuer}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -349,7 +349,7 @@ const Publications = () => {
<div>
<div className="font-bold">{item.name}</div>
<div>{item.publisher}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -366,7 +366,7 @@ const Volunteer = () => {
<div className="font-bold">{item.organization}</div>
<div>{item.position}</div>
<div>{item.location}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -377,11 +377,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
@@ -399,7 +399,7 @@ const Projects = () => {
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
</div>
)}
@@ -438,7 +438,7 @@ const Custom = ({ id }: { id: string }) => {
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
<div>{item.location}</div>
</div>
</div>
+9 -9
View File
@@ -158,7 +158,7 @@ const Section = <T,>({
</div>
<div
className="col-span-4 grid gap-3"
className="col-span-4 grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -171,18 +171,18 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">
<div>
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
@@ -200,7 +200,7 @@ const Profiles = () => {
return (
<Section<Profile> section={section}>
{(item) => (
<div className="leading-snug">
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
@@ -384,11 +384,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div className="space-y-0.5">
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
+45 -37
View File
@@ -7,6 +7,7 @@ import {
Experience,
Interest,
Language,
Profile,
Project,
Publication,
Reference,
@@ -26,8 +27,6 @@ import { TemplateProps } from "../types/template";
const Header = () => {
const basics = useArtboardStore((state) => state.resume.basics);
const profiles = useArtboardStore((state) => state.resume.sections.profiles);
const fontSize = useArtboardStore((state) => state.resume.metadata.typography.font.size);
return (
<div className="grid grid-cols-3">
@@ -71,31 +70,6 @@ const Header = () => {
</div>
))}
</div>
{profiles.visible && profiles.items.length > 0 && (
<div className="flex items-center gap-x-3 gap-y-0.5">
{profiles.items
.filter((item) => item.visible)
.map((item) => (
<div key={item.id} className="flex items-center gap-x-2">
<Link
url={item.url}
label={item.username}
className="text-sm"
icon={
<img
className="ph"
width={fontSize}
height={fontSize}
alt={item.network}
src={`https://cdn.simpleicons.org/${item.icon}`}
/>
}
/>
</div>
))}
</div>
)}
</div>
</div>
</div>
@@ -109,7 +83,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold">{section.name}</h4>
<div
className="wysiwyg"
@@ -184,10 +158,10 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold">{section.name}</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -200,18 +174,18 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">
<div>
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
@@ -267,6 +241,38 @@ const Education = () => {
);
};
const Profiles = () => {
const section = useArtboardStore((state) => state.resume.sections.profiles);
const fontSize = useArtboardStore((state) => state.resume.metadata.typography.font.size);
return (
<Section<Profile> section={section}>
{(item) => (
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
label={item.username}
icon={
<img
className="ph"
width={fontSize}
height={fontSize}
alt={item.network}
src={`https://cdn.simpleicons.org/${item.icon}`}
/>
}
/>
) : (
<p>{item.username}</p>
)}
<p className="text-sm">{item.network}</p>
</div>
)}
</Section>
);
};
const Awards = () => {
const section = useArtboardStore((state) => state.resume.sections.awards);
@@ -381,11 +387,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div className="space-y-0.5">
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
@@ -457,6 +463,8 @@ const Custom = ({ id }: { id: string }) => {
const mapSectionToComponent = (section: SectionKey) => {
switch (section) {
case "profiles":
return <Profiles />;
case "summary":
return <Summary />;
case "experience":
+11 -11
View File
@@ -101,7 +101,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="mb-2 text-base font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 text-base font-bold">{section.name}</h4>
<div
className="wysiwyg"
@@ -173,10 +173,10 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="mb-2 text-base font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 text-base font-bold">{section.name}</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -193,21 +193,21 @@ const Section = <T,>({
className={cn("relative space-y-2 pl-4 group-[.sidebar]:pl-0", className)}
>
<div className="relative -ml-4 group-[.sidebar]:ml-0">
<div className="pl-4 leading-snug group-[.sidebar]:pl-0">
<div className="pl-4 group-[.sidebar]:pl-0">
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
<div className="absolute inset-y-0 -left-px border-l-[4px] border-primary group-[.sidebar]:hidden" />
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
@@ -227,7 +227,7 @@ const Profiles = () => {
return (
<Section<Profile> section={section}>
{(item) => (
<div className="leading-snug">
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
@@ -411,11 +411,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
+5 -2
View File
@@ -1,15 +1,16 @@
import { TemplateKey } from "@reactive-resume/utils";
import { Template } from "@reactive-resume/utils";
import { Azurill } from "./azurill";
import { Bronzor } from "./bronzor";
import { Chikorita } from "./chikorita";
import { Ditto } from "./ditto";
import { Kakuna } from "./kakuna";
import { Nosepass } from "./nosepass";
import { Onyx } from "./onyx";
import { Pikachu } from "./pikachu";
import { Rhyhorn } from "./rhyhorn";
export const getTemplate = (template: TemplateKey) => {
export const getTemplate = (template: Template) => {
switch (template) {
case "onyx":
return Onyx;
@@ -27,6 +28,8 @@ export const getTemplate = (template: TemplateKey) => {
return Bronzor;
case "pikachu":
return Pikachu;
case "nosepass":
return Nosepass;
default:
return Onyx;
}
+18 -18
View File
@@ -105,7 +105,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="mb-2 border-b border-primary text-center font-bold uppercase text-primary">
<h4 className="mb-2 border-b border-primary text-center font-bold text-primary">
{section.name}
</h4>
@@ -179,12 +179,12 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="mb-2 border-b border-primary text-center font-bold uppercase text-primary">
<h4 className="mb-2 border-b border-primary text-center font-bold text-primary">
{section.name}
</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -197,19 +197,19 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">{children?.(item as T)}</div>
<div>{children?.(item as T)}</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
);
})}
@@ -228,7 +228,7 @@ const Experience = () => {
<div className="font-bold">{item.company}</div>
<div>{item.position}</div>
<div>{item.location}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -246,7 +246,7 @@ const Education = () => {
<div>{item.area}</div>
<div>{item.score}</div>
<div>{item.studyType}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -262,7 +262,7 @@ const Awards = () => {
<div>
<div className="font-bold">{item.title}</div>
<div>{item.awarder}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -278,7 +278,7 @@ const Certifications = () => {
<div>
<div className="font-bold">{item.name}</div>
<div>{item.issuer}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -319,7 +319,7 @@ const Publications = () => {
<div>
<div className="font-bold">{item.name}</div>
<div>{item.publisher}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -336,7 +336,7 @@ const Volunteer = () => {
<div className="font-bold">{item.organization}</div>
<div>{item.position}</div>
<div>{item.location}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
)}
</Section>
@@ -347,11 +347,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
@@ -368,7 +368,7 @@ const Projects = () => {
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
</div>
)}
@@ -407,7 +407,7 @@ const Custom = ({ id }: { id: string }) => {
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
<div>{item.location}</div>
<div className="font-bold italic">{item.date}</div>
<div className="font-bold">{item.date}</div>
</div>
</div>
)}
+529
View File
@@ -0,0 +1,529 @@
import {
Award,
Certification,
CustomSection,
CustomSectionGroup,
Education,
Experience,
Interest,
Language,
Profile,
Project,
Publication,
Reference,
SectionKey,
SectionWithItem,
Skill,
URL,
Volunteer,
} from "@reactive-resume/schema";
import { cn, isEmptyString, isUrl } from "@reactive-resume/utils";
import get from "lodash.get";
import { Fragment } from "react";
import { Picture } from "../components/picture";
import { useArtboardStore } from "../store/artboard";
import { TemplateProps } from "../types/template";
const Header = () => {
const basics = useArtboardStore((state) => state.resume.basics);
return (
<div className="grid grid-cols-4 gap-x-6">
<div className="mt-1 space-y-2 text-right">
<p className="font-medium text-primary">Personal Information</p>
<Picture className="ml-auto" />
</div>
<div className="col-span-3 space-y-2">
<div>
<div className="text-2xl font-bold">{basics.name}</div>
<div className="text-base">{basics.headline}</div>
</div>
<div className="space-y-1 text-sm">
{basics.location && (
<div className="flex items-center gap-x-1.5">
<i className="ph ph-bold ph-map-pin text-primary" />
<div>{basics.location}</div>
</div>
)}
{basics.phone && (
<div className="flex items-center gap-x-1.5">
<i className="ph ph-bold ph-phone text-primary" />
<a href={`tel:${basics.phone}`} target="_blank" rel="noreferrer">
{basics.phone}
</a>
</div>
)}
{basics.email && (
<div className="flex items-center gap-x-1.5">
<i className="ph ph-bold ph-at text-primary" />
<a href={`mailto:${basics.email}`} target="_blank" rel="noreferrer">
{basics.email}
</a>
</div>
)}
<Link url={basics.url} />
</div>
<div className="flex flex-wrap gap-x-3 text-sm">
{basics.customFields.map((item) => (
<div key={item.id} className="flex items-center gap-x-1.5">
<i className={cn(`ph ph-bold ph-${item.icon}`, "text-primary")} />
<span className="text-primary">{item.name}</span>
<span>{item.value}</span>
</div>
))}
</div>
</div>
</div>
);
};
const Summary = () => {
const section = useArtboardStore((state) => state.resume.sections.summary);
if (!section.visible || isEmptyString(section.content)) return null;
return (
<section id={section.id} className="grid grid-cols-4 gap-x-6">
<div className="text-right">
<h4 className="font-medium text-primary">{section.name}</h4>
</div>
<div className="col-span-3">
<div className="relative">
<hr className="mt-3 border-primary pb-3" />
<div className="absolute bottom-3 right-0 h-3 w-3 bg-primary" />
</div>
<div
className="wysiwyg"
style={{ columns: section.columns }}
dangerouslySetInnerHTML={{ __html: section.content }}
/>
</div>
</section>
);
};
type LinkProps = {
url: URL;
icon?: React.ReactNode;
label?: string;
className?: string;
};
const Link = ({ url, icon, label, className }: LinkProps) => {
if (!isUrl(url.href)) return null;
return (
<div className="flex items-center gap-x-1.5">
{icon ?? <i className="ph ph-bold ph-link text-primary" />}
<a
href={url.href}
target="_blank"
rel="noreferrer noopener nofollow"
className={cn("inline-block", className)}
>
{label || url.label || url.href}
</a>
</div>
);
};
type SectionProps<T> = {
section: SectionWithItem<T> | CustomSectionGroup;
children?: (item: T) => React.ReactNode;
urlKey?: keyof T;
dateKey?: keyof T;
levelKey?: keyof T;
summaryKey?: keyof T;
keywordsKey?: keyof T;
};
const Section = <T,>({
section,
children,
urlKey,
dateKey,
summaryKey,
keywordsKey,
}: SectionProps<T>) => {
if (!section.visible || !section.items.length) return null;
return (
<section id={section.id} className={cn("grid", dateKey !== undefined && "gap-y-4")}>
<div className="grid grid-cols-4 gap-x-6">
<div className="text-right">
<h4 className="font-medium text-primary">{section.name}</h4>
</div>
<div className="col-span-3">
<div className="relative">
<hr className="mt-3 border-primary" />
<div className="absolute bottom-0 right-0 h-3 w-3 bg-primary" />
</div>
</div>
</div>
{dateKey !== undefined && (
<div className="grid grid-cols-4 gap-x-6 gap-y-4">
{section.items
.filter((item) => item.visible)
.map((item) => {
const url = (urlKey && get(item, urlKey)) as URL | undefined;
const date = (dateKey && get(item, dateKey, "")) as string | undefined;
const summary = (summaryKey && get(item, summaryKey, "")) as string | undefined;
const keywords = (keywordsKey && get(item, keywordsKey, [])) as string[] | undefined;
return (
<Fragment key={item.id}>
<div className="text-right font-medium text-primary">{date}</div>
<div className="col-span-3 space-y-1">
{children?.(item as T)}
{url !== undefined && <Link url={url} />}
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
</Fragment>
);
})}
</div>
)}
{dateKey === undefined && (
<div className="grid grid-cols-4 gap-x-6">
<div
className="col-span-3 col-start-2 grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
.filter((item) => item.visible)
.map((item) => {
const url = (urlKey && get(item, urlKey)) as URL | undefined;
const summary = (summaryKey && get(item, summaryKey, "")) as string | undefined;
const keywords = (keywordsKey && get(item, keywordsKey, [])) as
| string[]
| undefined;
return (
<div key={item.id}>
{children?.(item as T)}
{url !== undefined && <Link url={url} />}
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
);
})}
</div>
</div>
)}
</section>
);
};
const Profiles = () => {
const section = useArtboardStore((state) => state.resume.sections.profiles);
const fontSize = useArtboardStore((state) => state.resume.metadata.typography.font.size);
return (
<Section<Profile> section={section}>
{(item) => (
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
label={item.username}
icon={
<img
className="ph"
width={fontSize}
height={fontSize}
alt={item.network}
src={`https://cdn.simpleicons.org/${item.icon}`}
/>
}
/>
) : (
<p>{item.username}</p>
)}
<p className="text-sm">{item.network}</p>
</div>
)}
</Section>
);
};
const Experience = () => {
const section = useArtboardStore((state) => state.resume.sections.experience);
return (
<Section<Experience> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.company}</div>
<div>{item.position}</div>
<div>{item.location}</div>
</div>
)}
</Section>
);
};
const Education = () => {
const section = useArtboardStore((state) => state.resume.sections.education);
return (
<Section<Education> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.institution}</div>
<div>{item.area}</div>
<div>{item.studyType}</div>
<div>{item.score}</div>
</div>
)}
</Section>
);
};
const Awards = () => {
const section = useArtboardStore((state) => state.resume.sections.awards);
return (
<Section<Award> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.title}</div>
<div>{item.awarder}</div>
</div>
)}
</Section>
);
};
const Certifications = () => {
const section = useArtboardStore((state) => state.resume.sections.certifications);
return (
<Section<Certification> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.issuer}</div>
</div>
)}
</Section>
);
};
const Skills = () => {
const section = useArtboardStore((state) => state.resume.sections.skills);
return (
<Section<Skill> section={section} levelKey="level" keywordsKey="keywords">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
</div>
)}
</Section>
);
};
const Interests = () => {
const section = useArtboardStore((state) => state.resume.sections.interests);
return (
<Section<Interest> section={section} keywordsKey="keywords">
{(item) => <div className="font-bold">{item.name}</div>}
</Section>
);
};
const Publications = () => {
const section = useArtboardStore((state) => state.resume.sections.publications);
return (
<Section<Publication> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.publisher}</div>
</div>
)}
</Section>
);
};
const Volunteer = () => {
const section = useArtboardStore((state) => state.resume.sections.volunteer);
return (
<Section<Volunteer> section={section} urlKey="url" dateKey="date" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.organization}</div>
<div>{item.position}</div>
<div>{item.location}</div>
</div>
)}
</Section>
);
};
const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="level">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
</div>
)}
</Section>
);
};
const Projects = () => {
const section = useArtboardStore((state) => state.resume.sections.projects);
return (
<Section<Project>
section={section}
urlKey="url"
dateKey="date"
summaryKey="summary"
keywordsKey="keywords"
>
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
</div>
)}
</Section>
);
};
const References = () => {
const section = useArtboardStore((state) => state.resume.sections.references);
return (
<Section<Reference> section={section} urlKey="url" summaryKey="summary">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
</div>
)}
</Section>
);
};
const Custom = ({ id }: { id: string }) => {
const section = useArtboardStore((state) => state.resume.sections.custom[id]);
return (
<Section<CustomSection>
section={section}
urlKey="url"
dateKey="date"
summaryKey="summary"
keywordsKey="keywords"
>
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
<div>{item.location}</div>
</div>
)}
</Section>
);
};
const mapSectionToComponent = (section: SectionKey) => {
switch (section) {
case "profiles":
return <Profiles />;
case "summary":
return <Summary />;
case "experience":
return <Experience />;
case "education":
return <Education />;
case "awards":
return <Awards />;
case "certifications":
return <Certifications />;
case "skills":
return <Skills />;
case "interests":
return <Interests />;
case "publications":
return <Publications />;
case "volunteer":
return <Volunteer />;
case "languages":
return <Languages />;
case "projects":
return <Projects />;
case "references":
return <References />;
default:
if (section.startsWith("custom.")) return <Custom id={section.split(".")[1]} />;
return null;
}
};
export const Nosepass = ({ columns, isFirstPage = false }: TemplateProps) => {
const name = useArtboardStore((state) => state.resume.basics.name);
const [main, sidebar] = columns;
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<img alt="Europass Logo" className="h-[48px]" src="https://i.imgur.com/eRK005p.png" />
<p className="font-medium text-primary">Curriculum Vitae</p>
<p className="font-medium text-primary">{name}</p>
</div>
{isFirstPage && <Header />}
<div className="space-y-4">
{main.map((section) => (
<Fragment key={section}>{mapSectionToComponent(section)}</Fragment>
))}
{sidebar.map((section) => (
<Fragment key={section}>{mapSectionToComponent(section)}</Fragment>
))}
</div>
</div>
);
};
+10 -10
View File
@@ -110,7 +110,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="font-bold uppercase text-primary">{section.name}</h4>
<h4 className="font-bold text-primary">{section.name}</h4>
<div
className="wysiwyg"
@@ -182,10 +182,10 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="font-bold uppercase text-primary">{section.name}</h4>
<h4 className="font-bold text-primary">{section.name}</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -198,18 +198,18 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">
<div>
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
@@ -379,11 +379,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div className="space-y-0.5">
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
+14 -14
View File
@@ -34,8 +34,8 @@ const Header = () => {
className="summary group bg-primary px-6 pb-7 pt-6 text-background"
style={{ borderRadius: `calc(${borderRadius}px - 2px)` }}
>
<div className="col-span-2 space-y-4">
<div className="leading-tight">
<div className="col-span-2 space-y-2.5">
<div>
<h2 className="text-2xl font-bold">{basics.name}</h2>
<p>{basics.headline}</p>
</div>
@@ -102,7 +102,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="mb-2 text-base font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b border-primary text-base font-bold">{section.name}</h4>
<div
className="wysiwyg"
@@ -182,10 +182,10 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="mb-2 border-b border-primary text-base font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b border-primary text-base font-bold">{section.name}</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -198,18 +198,18 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">
<div>
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
@@ -227,7 +227,7 @@ const Profiles = () => {
return (
<Section<Profile> section={section}>
{(item) => (
<div className="leading-snug">
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
@@ -358,7 +358,7 @@ const Interests = () => {
const section = useArtboardStore((state) => state.resume.sections.interests);
return (
<Section<Interest> section={section} className="space-y-0" keywordsKey="keywords">
<Section<Interest> section={section} className="space-y-1" keywordsKey="keywords">
{(item) => <div className="font-bold">{item.name}</div>}
</Section>
);
@@ -411,11 +411,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div>
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
+12 -12
View File
@@ -82,7 +82,7 @@ const Summary = () => {
return (
<section id={section.id}>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold">{section.name}</h4>
<div
className="wysiwyg"
@@ -154,10 +154,10 @@ const Section = <T,>({
return (
<section id={section.id} className="grid">
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold uppercase">{section.name}</h4>
<h4 className="mb-2 border-b pb-0.5 text-sm font-bold">{section.name}</h4>
<div
className="grid gap-3"
className="grid gap-x-6 gap-y-3"
style={{ gridTemplateColumns: `repeat(${section.columns}, 1fr)` }}
>
{section.items
@@ -170,18 +170,18 @@ const Section = <T,>({
return (
<div key={item.id} className={cn("space-y-2", className)}>
<div className="leading-snug">
<div>
{children?.(item as T)}
{url && <Link url={url} />}
{url !== undefined && <Link url={url} />}
</div>
{summary && !isEmptyString(summary) && (
{summary !== undefined && !isEmptyString(summary) && (
<div className="wysiwyg" dangerouslySetInnerHTML={{ __html: summary }} />
)}
{level && level > 0 && <Rating level={level} />}
{level !== undefined && level > 0 && <Rating level={level} />}
{keywords && keywords.length > 0 && (
{keywords !== undefined && keywords.length > 0 && (
<p className="text-sm">{keywords.join(", ")}</p>
)}
</div>
@@ -199,7 +199,7 @@ const Profiles = () => {
return (
<Section<Profile> section={section}>
{(item) => (
<div className="leading-snug">
<div>
{isUrl(item.url.href) ? (
<Link
url={item.url}
@@ -317,7 +317,7 @@ const Skills = () => {
return (
<Section<Skill> section={section} levelKey="level" keywordsKey="keywords">
{(item) => (
<div className="leading-tight">
<div>
<div className="font-bold">{item.name}</div>
<div>{item.description}</div>
</div>
@@ -383,11 +383,11 @@ const Languages = () => {
const section = useArtboardStore((state) => state.resume.sections.languages);
return (
<Section<Language> section={section} levelKey="fluencyLevel">
<Section<Language> section={section} levelKey="level">
{(item) => (
<div className="space-y-0.5">
<div className="font-bold">{item.name}</div>
<div>{item.fluency}</div>
<div>{item.description}</div>
</div>
)}
</Section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

@@ -0,0 +1,321 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 120,
"aspectRatio": 1.2,
"borderRadius": 4,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 1,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": []
},
"profiles": {
"name": "Profiles",
"columns": 1,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 1,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": false,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 1,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "azurill",
"layout": [
[
["summary", "experience", "education", "references"],
[
"profiles",
"skills",
"certifications",
"projects",
"interests",
"languages",
"awards",
"volunteer",
"publications"
]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#ca8a04"
},
"typography": {
"font": {
"family": "Merriweather",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.75,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
@@ -0,0 +1,346 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 140,
"aspectRatio": 1,
"borderRadius": 4,
"effects": {
"hidden": true,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 2,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 2,
"visible": true,
"id": "languages",
"items": [
{
"id": "ey0c353j3apepzqmyl8zd37c",
"visible": true,
"name": "English",
"description": "Native Speaker",
"level": 0
},
{
"id": "a4dnf32wyj5phgln2rx97qk2",
"visible": true,
"name": "Spanish",
"description": "Intermediate",
"level": 0
}
]
},
"profiles": {
"name": "Profiles",
"columns": 3,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
},
{
"id": "k97vdxzmssmgel79km48kxgg",
"visible": true,
"network": "StackOverflow",
"username": "johndoe",
"icon": "stackoverflow",
"url": {
"label": "",
"href": "https://stackoverflow.com/u/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 2,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 3,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "bronzor",
"layout": [
[
["profiles", "summary", "experience", "education", "projects"],
[
"skills",
"certifications",
"languages",
"references",
"interests",
"awards",
"volunteer",
"publications"
]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#059669"
},
"typography": {
"font": {
"family": "IBM Plex Sans",
"subset": "latin",
"variants": ["regular", "500"],
"size": 13
},
"lineHeight": 1.5,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
@@ -0,0 +1,346 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 140,
"aspectRatio": 1,
"borderRadius": 4,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 1,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": [
{
"id": "ey0c353j3apepzqmyl8zd37c",
"visible": true,
"name": "English",
"description": "Native Speaker",
"level": 0
},
{
"id": "a4dnf32wyj5phgln2rx97qk2",
"visible": true,
"name": "Spanish",
"description": "Intermediate",
"level": 0
}
]
},
"profiles": {
"name": "Profiles",
"columns": 3,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
},
{
"id": "k97vdxzmssmgel79km48kxgg",
"visible": true,
"network": "StackOverflow",
"username": "johndoe",
"icon": "stackoverflow",
"url": {
"label": "",
"href": "https://stackoverflow.com/u/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 2,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 1,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "chikorita",
"layout": [
[
["profiles", "summary", "experience", "education", "projects"],
[
"skills",
"certifications",
"languages",
"references",
"interests",
"awards",
"volunteer",
"publications"
]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#059669"
},
"typography": {
"font": {
"family": "Merriweather",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.5,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
@@ -0,0 +1,347 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 140,
"aspectRatio": 1,
"borderRadius": 4,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 1,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": [
{
"id": "ey0c353j3apepzqmyl8zd37c",
"visible": true,
"name": "English",
"description": "Native Speaker",
"level": 0
},
{
"id": "a4dnf32wyj5phgln2rx97qk2",
"visible": true,
"name": "Spanish",
"description": "Intermediate",
"level": 0
}
]
},
"profiles": {
"name": "Profiles",
"columns": 1,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
},
{
"id": "k97vdxzmssmgel79km48kxgg",
"visible": true,
"network": "StackOverflow",
"username": "johndoe",
"icon": "stackoverflow",
"url": {
"label": "",
"href": "https://stackoverflow.com/u/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 2,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 1,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "ditto",
"layout": [
[
["summary", "experience", "education", "projects"],
[
"profiles",
"skills",
"certifications",
"languages",
"references",
"interests",
"awards",
"volunteer",
"publications"
]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#0891b2"
},
"typography": {
"font": {
"family": "Merriweather",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.75,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
@@ -0,0 +1,319 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 64,
"aspectRatio": 1,
"borderRadius": 0,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 2,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 2,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": []
},
"profiles": {
"name": "Profiles",
"columns": 1,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 2,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 3,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "kakuna",
"layout": [
[
[
"summary",
"experience",
"education",
"projects",
"certifications",
"skills",
"references"
],
["profiles", "interests", "languages", "awards", "volunteer", "publications"]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#57534e"
},
"typography": {
"font": {
"family": "Lora",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.5,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
@@ -0,0 +1,338 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 90,
"aspectRatio": 1,
"borderRadius": 4,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 1,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "Aug 2012 - May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "Jan 2019 - Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "Jun 2016 - Dec 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": [
{
"id": "ey0c353j3apepzqmyl8zd37c",
"visible": true,
"name": "English",
"description": "Native Speaker",
"level": 0
},
{
"id": "a4dnf32wyj5phgln2rx97qk2",
"visible": true,
"name": "Spanish",
"description": "Intermediate",
"level": 0
}
]
},
"profiles": {
"name": "Profiles",
"columns": 3,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
},
{
"id": "k97vdxzmssmgel79km48kxgg",
"visible": true,
"network": "StackOverflow",
"username": "johndoe",
"icon": "stackoverflow",
"url": {
"label": "",
"href": "https://stackoverflow.com/u/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 1,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 1,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "nosepass",
"layout": [
[
["profiles", "summary", "experience", "education"],
["interests", "awards", "volunteer", "publications"]
],
[["projects", "certifications", "skills", "languages", "references"], []]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 24,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#5d93bc"
},
"typography": {
"font": {
"family": "Work Sans",
"subset": "latin",
"variants": ["regular"],
"size": 13.8
},
"lineHeight": 1.5,
"hideIcons": true,
"underlineLinks": true
},
"notes": ""
}
}
+319
View File
@@ -0,0 +1,319 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 100,
"aspectRatio": 1,
"borderRadius": 0,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 2,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor of Science",
"area": "Computer Science",
"score": "Berkeley, CA",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": "https://www.universityofcalifornia.edu/"
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": []
},
"profiles": {
"name": "Profiles",
"columns": 1,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 1,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 3,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "onyx",
"layout": [
[
[
"summary",
"experience",
"education",
"projects",
"certifications",
"skills",
"references"
],
["profiles", "interests", "languages", "awards", "volunteer", "publications"]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 18,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#dc2626"
},
"typography": {
"font": {
"family": "PT Serif",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.5,
"hideIcons": false,
"underlineLinks": false
},
"notes": ""
}
}
@@ -0,0 +1,347 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 140,
"aspectRatio": 1,
"borderRadius": 4,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 1,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": [
{
"id": "ey0c353j3apepzqmyl8zd37c",
"visible": true,
"name": "English",
"description": "Native Speaker",
"level": 0
},
{
"id": "a4dnf32wyj5phgln2rx97qk2",
"visible": true,
"name": "Spanish",
"description": "Intermediate",
"level": 0
}
]
},
"profiles": {
"name": "Profiles",
"columns": 1,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
},
{
"id": "k97vdxzmssmgel79km48kxgg",
"visible": true,
"network": "StackOverflow",
"username": "johndoe",
"icon": "stackoverflow",
"url": {
"label": "",
"href": "https://stackoverflow.com/u/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 1,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": true,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 1,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "pikachu",
"layout": [
[
["summary", "experience", "education", "projects"],
[
"profiles",
"skills",
"certifications",
"languages",
"references",
"interests",
"awards",
"volunteer",
"publications"
]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#ca8a04"
},
"typography": {
"font": {
"family": "Titillium Web",
"subset": "latin",
"variants": ["regular"],
"size": 13.8
},
"lineHeight": 1.5,
"hideIcons": false,
"underlineLinks": false
},
"notes": ""
}
}
@@ -0,0 +1,320 @@
{
"basics": {
"name": "John Doe",
"headline": "Creative and Innovative Web Developer",
"email": "john.doe@gmail.com",
"phone": "(555) 123-4567",
"location": "Pleasantville, CA 94588",
"url": {
"label": "",
"href": "https://johndoe.me/"
},
"customFields": [],
"picture": {
"url": "https://i.imgur.com/HgwyOuJ.jpg",
"size": 64,
"aspectRatio": 1,
"borderRadius": 0,
"effects": {
"hidden": false,
"border": false,
"grayscale": false
}
}
},
"sections": {
"summary": {
"name": "Summary",
"columns": 1,
"visible": true,
"id": "summary",
"content": "<p>Innovative Web Developer with 5 years of experience in building impactful and user-friendly websites and applications. Specializes in <strong>front-end technologies</strong> and passionate about modern web standards and cutting-edge development techniques. Proven track record of leading successful projects from concept to deployment.</p>"
},
"awards": {
"name": "Awards",
"columns": 1,
"visible": true,
"id": "awards",
"items": []
},
"certifications": {
"name": "Certifications",
"columns": 2,
"visible": true,
"id": "certifications",
"items": [
{
"id": "spdhh9rrqi1gvj0yqnbqunlo",
"visible": true,
"name": "Full-Stack Web Development",
"issuer": "CodeAcademy",
"date": "2020",
"summary": "",
"url": {
"label": "",
"href": ""
}
},
{
"id": "n838rddyqv47zexn6cxauwqp",
"visible": true,
"name": "AWS Certified Developer",
"issuer": "Amazon Web Services",
"date": "2019",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"education": {
"name": "Education",
"columns": 1,
"visible": true,
"id": "education",
"items": [
{
"id": "yo3p200zo45c6cdqc6a2vtt3",
"visible": true,
"institution": "University of California",
"studyType": "Bachelor's in Computer Science",
"area": "Berkeley, CA",
"score": "",
"date": "August 2012 to May 2016",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"experience": {
"name": "Experience",
"columns": 1,
"visible": true,
"id": "experience",
"items": [
{
"id": "lhw25d7gf32wgdfpsktf6e0x",
"visible": true,
"company": "Creative Solutions Inc.",
"position": "Senior Web Developer",
"location": "San Francisco, CA",
"date": "January 2019 to Present",
"summary": "<ul><li><p>Spearheaded the redesign of the main product website, resulting in a 40% increase in user engagement.</p></li><li><p>Developed and implemented a new responsive framework, improving cross-device compatibility.</p></li><li><p>Mentored a team of four junior developers, fostering a culture of technical excellence.</p></li></ul>",
"url": {
"label": "",
"href": "https://creativesolutions.inc/"
}
},
{
"id": "r6543lil53ntrxmvel53gbtm",
"visible": true,
"company": "TechAdvancers",
"position": "Web Developer",
"location": "San Jose, CA",
"date": "June 2016 to December 2018",
"summary": "<ul><li><p>Collaborated in a team of 10 to develop high-quality web applications using React.js and Node.js.</p></li><li><p>Managed the integration of third-party services such as Stripe for payments and Twilio for SMS services.</p></li><li><p>Optimized application performance, achieving a 30% reduction in load times.</p></li></ul>",
"url": {
"label": "",
"href": "https://techadvancers.com/"
}
}
]
},
"volunteer": {
"name": "Volunteering",
"columns": 1,
"visible": true,
"id": "volunteer",
"items": []
},
"interests": {
"name": "Interests",
"columns": 1,
"visible": true,
"id": "interests",
"items": []
},
"languages": {
"name": "Languages",
"columns": 1,
"visible": true,
"id": "languages",
"items": []
},
"profiles": {
"name": "Profiles",
"columns": 4,
"visible": true,
"id": "profiles",
"items": [
{
"id": "cnbk5f0aeqvhx69ebk7hktwd",
"visible": true,
"network": "LinkedIn",
"username": "johndoe",
"icon": "linkedin",
"url": {
"label": "",
"href": "https://linkedin.com/in/johndoe"
}
},
{
"id": "ukl0uecvzkgm27mlye0wazlb",
"visible": true,
"network": "GitHub",
"username": "johndoe",
"icon": "github",
"url": {
"label": "",
"href": "https://github.com/johndoe"
}
}
]
},
"projects": {
"name": "Projects",
"columns": 2,
"visible": true,
"id": "projects",
"items": [
{
"id": "yw843emozcth8s1ubi1ubvlf",
"visible": true,
"name": "E-Commerce Platform",
"description": "Project Lead",
"date": "",
"summary": "<p>Led the development of a full-stack e-commerce platform, improving sales conversion by 25%.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
},
{
"id": "ncxgdjjky54gh59iz2t1xi1v",
"visible": true,
"name": "Interactive Dashboard",
"description": "Frontend Developer",
"date": "",
"summary": "<p>Created an interactive analytics dashboard for a SaaS application, enhancing data visualization for clients.</p>",
"keywords": [],
"url": {
"label": "",
"href": ""
}
}
]
},
"publications": {
"name": "Publications",
"columns": 1,
"visible": true,
"id": "publications",
"items": []
},
"references": {
"name": "References",
"columns": 1,
"visible": false,
"id": "references",
"items": [
{
"id": "f2sv5z0cce6ztjl87yuk8fak",
"visible": true,
"name": "Available upon request",
"description": "",
"summary": "",
"url": {
"label": "",
"href": ""
}
}
]
},
"skills": {
"name": "Skills",
"columns": 3,
"visible": true,
"id": "skills",
"items": [
{
"id": "hn0keriukh6c0ojktl9gsgjm",
"visible": true,
"name": "Web Technologies",
"description": "Advanced",
"level": 0,
"keywords": ["HTML5", "JavaScript", "PHP", "Python"]
},
{
"id": "r8c3y47vykausqrgmzwg5pur",
"visible": true,
"name": "Web Frameworks",
"description": "Intermediate",
"level": 0,
"keywords": ["React.js", "Angular", "Vue.js", "Laravel", "Django"]
},
{
"id": "b5l75aseexqv17quvqgh73fe",
"visible": true,
"name": "Tools",
"description": "Intermediate",
"level": 0,
"keywords": ["Webpack", "Git", "Jenkins", "Docker", "JIRA"]
}
]
},
"custom": {}
},
"metadata": {
"template": "rhyhorn",
"layout": [
[
[
"profiles",
"summary",
"experience",
"education",
"projects",
"certifications",
"skills",
"references"
],
["interests", "languages", "awards", "volunteer", "publications"]
]
],
"css": {
"value": ".section {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}",
"visible": false
},
"page": {
"margin": 14,
"format": "a4",
"options": {
"breakLine": true,
"pageNumbers": true
}
},
"theme": {
"background": "#ffffff",
"text": "#000000",
"primary": "#ca8a04"
},
"typography": {
"font": {
"family": "Merriweather",
"subset": "latin",
"variants": ["regular"],
"size": 13
},
"lineHeight": 1.75,
"hideIcons": false,
"underlineLinks": true
},
"notes": ""
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

+19 -18
View File
@@ -1,20 +1,21 @@
export const colors: string[] = [
"#78716c", // stone-500
"#ef4444", // red-500
"#f97316", // orange-500
"#f59e0b", // amber-500
"#eab308", // yellow-500
"#84cc16", // lime-500
"#22c55e", // green-500
"#10b981", // emerald-500
"#14b8a6", // teal-500
"#06b6d4", // cyan-500
"#0ea5e9", // sky-500
"#3b82f6", // blue-500
"#6366f1", // indigo-500
"#8b5cf6", // violet-500
"#a855f7", // purple-500
"#d946ef", // fuchsia-500
"#ec4899", // pink-500
"#f43f5e", // rose-500
"#475569", // slate-600
"#57534e", // stone-600
"#dc2626", // red-600
"#ea580c", // orange-600
"#d97706", // amber-600
"#ca8a04", // yellow-600
"#65a30d", // lime-600
"#16a34a", // green-600
"#059669", // emerald-600
"#0d9488", // teal-600
"#0891b2", // cyan-600
"#0284c7", // sky-600
"#2563eb", // blue-600
"#4f46e5", // indigo-600
"#7c3aed", // violet-600
"#9333ea", // purple-600
"#c026d3", // fuchsia-600
"#db2777", // pink-600
"#e11d48", // rose-600
];
+17 -15
View File
@@ -210,7 +210,7 @@ msgid "Backup Codes may contain only lowercase letters or numbers, and must be e
msgstr "Backup Codes may contain only lowercase letters or numbers, and must be exactly 10 characters."
#: apps/client/src/pages/builder/sidebars/left/index.tsx:57
msgctxt "The Basics section of a Resume consists of User's Picture, Full Name, Location etc."
msgctxt "The basics section of a resume consists of User's Picture, Full Name, Location etc."
msgid "Basics"
msgstr "Basics"
@@ -247,7 +247,7 @@ msgstr "Cancel"
msgid "Casual"
msgstr "Casual"
#: apps/client/src/pages/builder/_components/toolbar.tsx:90
#: apps/client/src/pages/builder/_components/toolbar.tsx:89
msgid "Center Artboard"
msgstr "Center Artboard"
@@ -310,7 +310,7 @@ msgstr "Continue"
msgid "Copy"
msgstr "Copy"
#: apps/client/src/pages/builder/_components/toolbar.tsx:124
#: apps/client/src/pages/builder/_components/toolbar.tsx:123
msgid "Copy Link to Resume"
msgstr "Copy Link to Resume"
@@ -521,7 +521,7 @@ msgstr "Even if you're not in a position to contribute financially, you can stil
msgid "Export"
msgstr "Export"
#: apps/client/src/pages/builder/_components/toolbar.tsx:130
#: apps/client/src/pages/builder/_components/toolbar.tsx:129
msgid "Export as PDF"
msgstr "Export as PDF"
@@ -652,6 +652,8 @@ msgstr "Here, you can update your account information such as your profile pictu
msgid "Here, you can update your profile to customize and personalize your experience."
msgstr "Here, you can update your profile to customize and personalize your experience."
#: apps/client/src/pages/builder/sidebars/left/dialogs/languages.tsx:77
#: apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx:82
#: apps/client/src/pages/builder/sidebars/left/sections/picture/options.tsx:185
msgid "Hidden"
msgstr "Hidden"
@@ -787,7 +789,7 @@ msgstr "JSON"
#: apps/client/src/pages/builder/sidebars/left/dialogs/custom-section.tsx:145
#: apps/client/src/pages/builder/sidebars/left/dialogs/interests.tsx:55
#: apps/client/src/pages/builder/sidebars/left/dialogs/projects.tsx:122
#: apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx:95
#: apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx:99
msgid "Keywords"
msgstr "Keywords"
@@ -952,7 +954,7 @@ msgstr "Notes"
msgid "One-Time Password"
msgstr "One-Time Password"
#: apps/client/src/libs/axios.ts:32
#: apps/client/src/libs/axios.ts:34
#: apps/client/src/pages/dashboard/resumes/_dialogs/import.tsx:190
msgid "Oops, the server returned an error."
msgstr "Oops, the server returned an error."
@@ -1028,7 +1030,7 @@ msgstr "Photograph by Patrick Tomasso"
msgid "Pick any font from Google Fonts"
msgstr "Pick any font from Google Fonts"
#: apps/client/src/pages/builder/sidebars/left/sections/picture/section.tsx:52
#: apps/client/src/pages/builder/sidebars/left/sections/picture/section.tsx:69
#: apps/client/src/pages/dashboard/settings/_sections/account.tsx:120
msgid "Picture"
msgstr "Picture"
@@ -1118,7 +1120,7 @@ msgstr "Reactive Resume is a passion project of over 3 years of hard work, and w
msgid "Reactive Resume thrives thanks to its vibrant community. This project owes its progress to numerous individuals who've dedicated their time and skills. Below, we celebrate the coders who've enhanced its features on GitHub and the linguists whose translations on Crowdin have made it accessible to a broader audience."
msgstr "Reactive Resume thrives thanks to its vibrant community. This project owes its progress to numerous individuals who've dedicated their time and skills. Below, we celebrate the coders who've enhanced its features on GitHub and the linguists whose translations on Crowdin have made it accessible to a broader audience."
#: apps/client/src/pages/builder/_components/toolbar.tsx:64
#: apps/client/src/pages/builder/_components/toolbar.tsx:63
msgid "Redo"
msgstr "Redo"
@@ -1150,7 +1152,7 @@ msgstr "Reset Layout"
msgid "Reset your password"
msgstr "Reset your password"
#: apps/client/src/pages/builder/_components/toolbar.tsx:84
#: apps/client/src/pages/builder/_components/toolbar.tsx:83
msgid "Reset Zoom"
msgstr "Reset Zoom"
@@ -1444,11 +1446,11 @@ msgstr "Title"
msgid "Title"
msgstr "Title"
#: apps/client/src/pages/builder/_components/toolbar.tsx:98
#: apps/client/src/pages/builder/_components/toolbar.tsx:97
msgid "Toggle Page Break Line"
msgstr "Toggle Page Break Line"
#: apps/client/src/pages/builder/_components/toolbar.tsx:110
#: apps/client/src/pages/builder/_components/toolbar.tsx:109
msgid "Toggle Page Numbers"
msgstr "Toggle Page Numbers"
@@ -1487,7 +1489,7 @@ msgstr "Typography"
msgid "Underline Links"
msgstr "Underline Links"
#: apps/client/src/pages/builder/_components/toolbar.tsx:58
#: apps/client/src/pages/builder/_components/toolbar.tsx:57
msgid "Undo"
msgstr "Undo"
@@ -1603,7 +1605,7 @@ msgstr "What's new in the latest version"
#: apps/client/src/pages/builder/sidebars/left/dialogs/custom-section.tsx:150
#: apps/client/src/pages/builder/sidebars/left/dialogs/interests.tsx:60
#: apps/client/src/pages/builder/sidebars/left/dialogs/projects.tsx:127
#: apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx:100
#: apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx:104
msgid "You can add multiple keywords by separating them with a comma or pressing enter."
msgstr "You can add multiple keywords by separating them with a comma or pressing enter."
@@ -1651,10 +1653,10 @@ msgstr "Your OpenAI API Key has not been set yet. Please go to your account sett
msgid "Your password has been updated successfully."
msgstr "Your password has been updated successfully."
#: apps/client/src/pages/builder/_components/toolbar.tsx:72
#: apps/client/src/pages/builder/_components/toolbar.tsx:71
msgid "Zoom In"
msgstr "Zoom In"
#: apps/client/src/pages/builder/_components/toolbar.tsx:78
#: apps/client/src/pages/builder/_components/toolbar.tsx:77
msgid "Zoom Out"
msgstr "Zoom Out"
@@ -5,7 +5,7 @@ import {
CircleNotch,
ClockClockwise,
CubeFocus,
DownloadSimple,
FilePdf,
Hash,
LineSegment,
LinkSimple,
@@ -51,7 +51,7 @@ export const BuilderToolbar = () => {
<motion.div
initial={{ opacity: 0.5 }}
whileHover={{ opacity: 1 }}
className="fixed inset-x-0 mx-auto hidden pb-4 pt-6 text-center md:block"
className="fixed inset-x-0 bottom-0 mx-auto pb-4 pt-6 text-center md:block"
>
<div className="inline-flex items-center justify-center rounded-full bg-background px-4 shadow-xl">
<Tooltip content={t`Undo`}>
@@ -134,7 +134,7 @@ export const BuilderToolbar = () => {
onClick={onPrint}
disabled={loading}
>
{loading ? <CircleNotch className="animate-spin" /> : <DownloadSimple />}
{loading ? <CircleNotch className="animate-spin" /> : <FilePdf />}
</Button>
</Tooltip>
</div>
@@ -10,7 +10,6 @@ import {
Input,
Slider,
} from "@reactive-resume/ui";
import { getCEFRLevel } from "@reactive-resume/utils";
import { useForm } from "react-hook-form";
import { z } from "zod";
@@ -44,11 +43,11 @@ export const LanguagesDialog = () => {
/>
<FormField
name="fluency"
name="description"
control={form.control}
render={({ field }) => (
<FormItem>
<FormLabel>{t`Fluency`}</FormLabel>
<FormLabel>{t`Description`}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@@ -58,22 +57,26 @@ export const LanguagesDialog = () => {
/>
<FormField
name="fluencyLevel"
name="level"
control={form.control}
render={({ field }) => (
<FormItem className="sm:col-span-2">
<FormLabel>{t`Fluency (CEFR)`}</FormLabel>
<FormLabel>{t`Level`}</FormLabel>
<FormControl className="py-2">
<div className="flex items-center gap-x-4">
<Slider
{...field}
min={1}
max={6}
min={0}
max={5}
value={[field.value]}
onValueChange={(value) => field.onChange(value[0])}
/>
<span className="text-base font-bold">{getCEFRLevel(field.value)}</span>
{field.value === 0 ? (
<span className="text-base font-bold">{t`Hidden`}</span>
) : (
<span className="text-base font-bold">{field.value}</span>
)}
</div>
</FormControl>
<FormMessage />
@@ -71,14 +71,18 @@ export const SkillsDialog = () => {
<div className="flex items-center gap-x-4">
<Slider
{...field}
min={1}
min={0}
max={5}
value={[field.value]}
orientation="horizontal"
onValueChange={(value) => field.onChange(value[0])}
/>
<span className="text-base font-bold">{field.value}</span>
{field.value === 0 ? (
<span className="text-base font-bold">{t`Hidden`}</span>
) : (
<span className="text-base font-bold">{field.value}</span>
)}
</div>
</FormControl>
<FormMessage />
@@ -16,7 +16,6 @@ import {
Volunteer,
} from "@reactive-resume/schema";
import { Button, ScrollArea, Separator } from "@reactive-resume/ui";
import { getCEFRLevel } from "@reactive-resume/utils";
import { Fragment, useRef } from "react";
import { Link } from "react-router-dom";
@@ -57,21 +56,21 @@ export const LeftSidebar = () => {
name={t({
message: "Basics",
context:
"The Basics section of a Resume consists of User's Picture, Full Name, Location etc.",
"The basics section of a resume consists of User's Picture, Full Name, Location etc.",
})}
/>
<SectionIcon id="summary" onClick={() => scrollIntoView("#summary")} />
<SectionIcon id="profiles" onClick={() => scrollIntoView("#profiles")} />
<SectionIcon id="experience" onClick={() => scrollIntoView("#experience")} />
<SectionIcon id="education" onClick={() => scrollIntoView("#education")} />
<SectionIcon id="skills" onClick={() => scrollIntoView("#skills")} />
<SectionIcon id="languages" onClick={() => scrollIntoView("#languages")} />
<SectionIcon id="awards" onClick={() => scrollIntoView("#awards")} />
<SectionIcon id="certifications" onClick={() => scrollIntoView("#certifications")} />
<SectionIcon id="interests" onClick={() => scrollIntoView("#interests")} />
<SectionIcon id="languages" onClick={() => scrollIntoView("#languages")} />
<SectionIcon id="volunteer" onClick={() => scrollIntoView("#volunteer")} />
<SectionIcon id="projects" onClick={() => scrollIntoView("#projects")} />
<SectionIcon id="publications" onClick={() => scrollIntoView("#publications")} />
<SectionIcon id="skills" onClick={() => scrollIntoView("#skills")} />
<SectionIcon id="volunteer" onClick={() => scrollIntoView("#volunteer")} />
<SectionIcon id="references" onClick={() => scrollIntoView("#references")} />
<SectionIcon
@@ -118,6 +117,21 @@ export const LeftSidebar = () => {
description={(item) => item.area}
/>
<Separator />
<SectionBase<Skill>
id="skills"
title={(item) => item.name}
description={(item) => {
if (item.description) return item.description;
if (item.keywords.length > 0) return `${item.keywords.length} keywords`;
}}
/>
<Separator />
<SectionBase<Language>
id="languages"
title={(item) => item.name}
description={(item) => item.description}
/>
<Separator />
<SectionBase<Award>
id="awards"
title={(item) => item.title}
@@ -138,18 +152,6 @@ export const LeftSidebar = () => {
}}
/>
<Separator />
<SectionBase<Language>
id="languages"
title={(item) => item.name}
description={(item) => item.fluency || getCEFRLevel(item.fluencyLevel)}
/>
<Separator />
<SectionBase<Volunteer>
id="volunteer"
title={(item) => item.organization}
description={(item) => item.position}
/>
<Separator />
<SectionBase<Project>
id="projects"
title={(item) => item.name}
@@ -162,13 +164,10 @@ export const LeftSidebar = () => {
description={(item) => item.publisher}
/>
<Separator />
<SectionBase<Skill>
id="skills"
title={(item) => item.name}
description={(item) => {
if (item.description) return item.description;
if (item.keywords.length > 0) return `${item.keywords.length} keywords`;
}}
<SectionBase<Volunteer>
id="volunteer"
title={(item) => item.organization}
description={(item) => item.position}
/>
<Separator />
<SectionBase<Reference>
@@ -1,8 +1,7 @@
import { t } from "@lingui/macro";
import { Aperture, UploadSimple } from "@phosphor-icons/react";
import { Aperture, Trash, UploadSimple } from "@phosphor-icons/react";
import {
Avatar,
AvatarFallback,
AvatarImage,
buttonVariants,
Input,
@@ -11,8 +10,8 @@ import {
PopoverContent,
PopoverTrigger,
} from "@reactive-resume/ui";
import { cn, getInitials } from "@reactive-resume/utils";
import { AnimatePresence, motion } from "framer-motion";
import { cn } from "@reactive-resume/utils";
import { motion } from "framer-motion";
import { useMemo, useRef } from "react";
import { z } from "zod";
@@ -23,10 +22,9 @@ import { PictureOptions } from "./options";
export const PictureSection = () => {
const inputRef = useRef<HTMLInputElement>(null);
const { uploadImage, loading } = useUploadImage();
const { uploadImage } = useUploadImage();
const setValue = useResumeStore((state) => state.setValue);
const name = useResumeStore((state) => state.resume.data.basics.name);
const picture = useResumeStore((state) => state.resume.data.basics.picture);
const isValidUrl = useMemo(() => z.string().url().safeParse(picture.url).success, [picture.url]);
@@ -41,16 +39,37 @@ export const PictureSection = () => {
}
};
const onAvatarClick = () => {
if (isValidUrl) {
setValue("basics.picture.url", "");
} else {
inputRef.current?.click();
}
};
return (
<div className="flex items-center gap-x-4">
<Avatar className="h-14 w-14">
{isValidUrl && <AvatarImage src={picture.url} />}
<AvatarFallback className="text-lg font-bold">{getInitials(name)}</AvatarFallback>
</Avatar>
<div className="group relative cursor-pointer" onClick={onAvatarClick}>
<Avatar className="h-14 w-14 bg-secondary">
<AvatarImage src={picture.url} />
</Avatar>
{isValidUrl ? (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-full bg-background/30 opacity-0 transition-opacity group-hover:opacity-100">
<Trash size={16} weight="bold" />
</div>
) : (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-full bg-background/30 opacity-0 transition-opacity group-hover:opacity-100">
<UploadSimple size={16} weight="bold" />
</div>
)}
</div>
<div className="flex w-full flex-col gap-y-1.5">
<Label htmlFor="basics.picture.url">{t`Picture`}</Label>
<div className="flex items-center gap-x-2">
<input hidden type="file" ref={inputRef} onChange={onSelectImage} />
<Input
id="basics.picture.url"
placeholder="https://..."
@@ -58,44 +77,23 @@ export const PictureSection = () => {
onChange={(event) => setValue("basics.picture.url", event.target.value)}
/>
<AnimatePresence>
{/* Show options button if picture exists */}
{isValidUrl && (
<Popover>
<PopoverTrigger asChild>
<motion.button
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className={cn(buttonVariants({ size: "icon", variant: "ghost" }))}
>
<Aperture />
</motion.button>
</PopoverTrigger>
<PopoverContent className="w-[360px]">
<PictureOptions />
</PopoverContent>
</Popover>
)}
{/* Show upload button if picture doesn't exist, else show remove button to delete picture */}
{!isValidUrl && (
<>
<input hidden type="file" ref={inputRef} onChange={onSelectImage} />
{isValidUrl && (
<Popover>
<PopoverTrigger asChild>
<motion.button
disabled={loading}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => inputRef.current?.click()}
className={cn(buttonVariants({ size: "icon", variant: "ghost" }))}
>
<UploadSimple />
<Aperture />
</motion.button>
</>
)}
</AnimatePresence>
</PopoverTrigger>
<PopoverContent className="w-[360px]">
<PictureOptions />
</PopoverContent>
</Popover>
)}
</div>
</div>
</div>
@@ -1,6 +1,7 @@
import { t } from "@lingui/macro";
import { Button, HoverCard, HoverCardContent, HoverCardTrigger } from "@reactive-resume/ui";
import { AspectRatio } from "@reactive-resume/ui";
import { cn, templatesList } from "@reactive-resume/utils";
import { motion } from "framer-motion";
import { useResumeStore } from "@/client/stores/resume";
@@ -19,31 +20,28 @@ export const TemplateSection = () => {
</div>
</header>
<main className="grid grid-cols-2 gap-4">
{templatesList.map(({ id, name }) => (
<HoverCard key={id} openDelay={0} closeDelay={0}>
<HoverCardTrigger asChild>
<Button
variant="outline"
onClick={() => setValue("metadata.template", id)}
className={cn(
"flex h-12 items-center justify-center overflow-hidden rounded border text-center text-sm capitalize ring-primary transition-colors hover:bg-secondary-accent focus:outline-none focus:ring-1 disabled:opacity-100",
id === currentTemplate && "ring-1",
)}
>
{name}
</Button>
</HoverCardTrigger>
<main className="grid grid-cols-2 gap-5 @lg/right:grid-cols-3 @2xl/right:grid-cols-4">
{templatesList.map((template, index) => (
<AspectRatio ratio={1 / 1.4142}>
<motion.div
initial={{ opacity: 0, x: -50 }}
animate={{ opacity: 1, x: 0, transition: { delay: index * 0.1 } }}
whileTap={{ scale: 0.98, transition: { duration: 0.1 } }}
onClick={() => setValue("metadata.template", template)}
className={cn(
"relative cursor-pointer rounded-sm ring-primary transition-all hover:ring-2",
currentTemplate === template && "ring-2",
)}
>
<img src={`/templates/jpg/${template}.jpg`} alt={template} className="rounded-sm" />
<HoverCardContent className="max-w-xs overflow-hidden border-none bg-white p-0">
<img
alt={name}
loading="lazy"
src="/templates/sample.jpg"
className="aspect-[1/1.4142]"
/>
</HoverCardContent>
</HoverCard>
<div className="absolute inset-x-0 bottom-0 h-32 w-full bg-gradient-to-b from-transparent to-background/80">
<p className="absolute inset-x-0 bottom-2 text-center font-bold capitalize text-primary">
{template}
</p>
</div>
</motion.div>
</AspectRatio>
))}
</main>
</section>
@@ -137,7 +137,7 @@ export const TypographySection = () => {
<Slider
min={12}
max={18}
step={1}
step={0.05}
value={[typography.font.size]}
onValueChange={(value) => {
setValue("metadata.typography.font.size", value[0]);
@@ -154,7 +154,7 @@ export const TypographySection = () => {
<Slider
min={0}
max={3}
step={0.25}
step={0.05}
value={[typography.lineHeight]}
onValueChange={(value) => {
setValue("metadata.typography.lineHeight", value[0]);
@@ -1,6 +1,6 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { t } from "@lingui/macro";
import { Check, DownloadSimple, Warning } from "@phosphor-icons/react";
import { Check, DownloadSimple } from "@phosphor-icons/react";
import {
JsonResume,
JsonResumeParser,
@@ -141,7 +141,6 @@ export const ImportDialog = () => {
toast({
variant: "error",
icon: <Warning size={16} weight="bold" />,
title: t`An error occurred while validating the file.`,
});
}
@@ -186,7 +185,6 @@ export const ImportDialog = () => {
} catch (error) {
toast({
variant: "error",
icon: <Warning size={16} weight="bold" />,
title: t`Oops, the server returned an error.`,
description: importError?.message,
});
+2 -2
View File
@@ -6,9 +6,9 @@ import { FAQSection } from "./sections/faq";
import { FeaturesSection } from "./sections/features";
import { HeroSection } from "./sections/hero";
import { LogoCloudSection } from "./sections/logo-cloud";
import { SampleResumesSection } from "./sections/sample-resumes";
import { StatisticsSection } from "./sections/statistics";
import { SupportSection } from "./sections/support";
import { TemplatesSection } from "./sections/templates";
import { TestimonialsSection } from "./sections/testimonials";
export const HomePage = () => (
@@ -23,7 +23,7 @@ export const HomePage = () => (
<LogoCloudSection />
<StatisticsSection />
<FeaturesSection />
<SampleResumesSection />
<TemplatesSection />
<TestimonialsSection />
<SupportSection />
<FAQSection />
@@ -1,35 +1,22 @@
import { t, Trans } from "@lingui/macro";
import { t } from "@lingui/macro";
import { templatesList } from "@reactive-resume/utils";
import { motion } from "framer-motion";
const resumes = [
"/sample-resumes/ditto",
"/sample-resumes/ditto",
"/sample-resumes/ditto",
"/sample-resumes/ditto",
];
export const SampleResumesSection = () => (
export const TemplatesSection = () => (
<section id="sample-resumes" className="relative py-24 sm:py-32">
<div className="container flex flex-col gap-12 lg:min-h-[600px] lg:flex-row lg:items-start">
<div className="space-y-4 lg:mt-16 lg:basis-96">
<h2 className="text-4xl font-bold">{t`Sample Resumes`}</h2>
<h2 className="text-4xl font-bold">{t`Templates`}</h2>
<Trans>
<p className="leading-relaxed">
Have a look at some of the resume created to showcase the templates available on
Reactive Resume.
</p>
<p className="leading-relaxed">
They could also serve as examples to help guide the creation of your next resume.
</p>
</Trans>
<p className="leading-relaxed">
{t`Explore the templates available in Reactive Resume and view the resumes crafted with them. They could also serve as examples to help guide the creation of your next resume.`}
</p>
</div>
<div className="w-full overflow-hidden lg:absolute lg:right-0 lg:max-w-[55%]">
<motion.div
animate={{
x: [0, -400],
x: [0, templatesList.length * 200 * -1],
transition: {
x: {
duration: 30,
@@ -40,20 +27,21 @@ export const SampleResumesSection = () => (
}}
className="flex items-center gap-x-6"
>
{resumes.map((resume, index) => (
{templatesList.map((template, index) => (
<motion.a
key={index}
target="_blank"
rel="noreferrer"
href={`${resume}.pdf`}
href={`templates/pdf/${template}.pdf`}
className="max-w-none flex-none"
viewport={{ once: true }}
initial={{ opacity: 0, x: -100 }}
whileInView={{ opacity: 1, x: 0, transition: { delay: (index + 1) * 0.5 } }}
whileInView={{ opacity: 1, x: 0 }}
>
<img
alt={resume}
src={`${resume}.jpg`}
alt={template}
loading="lazy"
src={`/templates/jpg/${template}.jpg`}
className=" aspect-[1/1.4142] h-[400px] rounded object-cover lg:h-[600px]"
/>
</motion.a>
+11
View File
@@ -1,7 +1,9 @@
import { t } from "@lingui/macro";
import { StatisticsDto, UrlDto } from "@reactive-resume/dto";
import { useMutation } from "@tanstack/react-query";
import { RESUME_KEY } from "@/client/constants/query-keys";
import { toast } from "@/client/hooks/use-toast";
import { axios } from "@/client/libs/axios";
import { queryClient } from "@/client/libs/query-client";
@@ -24,6 +26,15 @@ export const usePrintResume = () => {
return { ...cache, downloads: cache.downloads + 1 } satisfies StatisticsDto;
});
},
onError: (error) => {
const message = error?.message;
toast({
variant: "error",
title: t`Oops, the server returned an error.`,
description: message,
});
},
});
return { printResume: printResumeFn, loading, error };
+1 -1
View File
@@ -40,7 +40,7 @@ export const configSchema = z.object({
REDIS_URL: z.string().url().startsWith("redis://").optional(),
// Sentry
SENTRY_DSN: z.string().url().startsWith("https://").optional(),
VITE_SENTRY_DSN: z.string().url().startsWith("https://").optional(),
// Crowdin (Optional)
CROWDIN_PROJECT_ID: z.coerce.number().optional(),
+1 -3
View File
@@ -1,6 +1,5 @@
import { Injectable } from "@nestjs/common";
import { HealthIndicator, HealthIndicatorResult } from "@nestjs/terminus";
import { withTimeout } from "@reactive-resume/utils";
import { PrinterService } from "../printer/printer.service";
@@ -12,8 +11,7 @@ export class BrowserHealthIndicator extends HealthIndicator {
async isHealthy(): Promise<HealthIndicatorResult> {
try {
const version = await withTimeout(this.printerService.getVersion(), 5000);
// const version = await this.printerService.getVersion();
const version = await this.printerService.getVersion();
return this.getStatus("browser", true, { version });
} catch (error) {
+1 -1
View File
@@ -23,7 +23,7 @@ async function bootstrap() {
// Sentry
// Error Reporting and Performance Monitoring
const sentryDsn = configService.get("SENTRY_DSN");
const sentryDsn = configService.get("VITE_SENTRY_DSN");
if (sentryDsn) {
const express = app.getHttpAdapter().getInstance();
+126 -107
View File
@@ -4,7 +4,7 @@ import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import fontkit from "@pdf-lib/fontkit";
import { ResumeDto } from "@reactive-resume/dto";
import { getFontUrls, withTimeout } from "@reactive-resume/utils";
import { getFontUrls } from "@reactive-resume/utils";
import { ErrorMessage } from "@reactive-resume/utils";
import retry from "async-retry";
import { PDFDocument } from "pdf-lib";
@@ -14,8 +14,6 @@ import { Config } from "../config/schema";
import { StorageService } from "../storage/storage.service";
import { UtilsService } from "../utils/utils.service";
const PRINTER_TIMEOUT = 10000; // 10 seconds
@Injectable()
export class PrinterService {
private readonly logger = new Logger(PrinterService.name);
@@ -55,11 +53,11 @@ export class PrinterService {
async () => {
const start = performance.now();
const url = await retry(() => withTimeout(this.generateResume(resume), PRINTER_TIMEOUT), {
retries: 2,
const url = await retry(() => this.generateResume(resume), {
retries: 3,
randomize: true,
onRetry: (_, attempt) => {
this.logger.debug(`Print Resume: retry attempt #${attempt}`);
this.logger.log(`Retrying to print resume #${resume.id}, attempt #${attempt}`);
},
});
@@ -76,117 +74,138 @@ export class PrinterService {
async printPreview(resume: ResumeDto) {
return this.utils.getCachedOrSet(
`user:${resume.userId}:storage:previews:${resume.id}`,
async () => withTimeout(this.generatePreview(resume), PRINTER_TIMEOUT),
async () => {
const start = performance.now();
const url = await retry(() => this.generatePreview(resume), {
retries: 3,
randomize: true,
onRetry: (_, attempt) => {
this.logger.log(
`Retrying to generate preview of resume #${resume.id}, attempt #${attempt}`,
);
},
});
const duration = Number(performance.now() - start).toFixed(0);
this.logger.debug(`Chrome took ${duration}ms to generate preview`);
return url;
},
);
}
async generateResume(resume: ResumeDto) {
const browser = await this.getBrowser();
const page = await browser.newPage();
try {
const browser = await this.getBrowser();
const page = await browser.newPage();
let url = this.utils.getUrl();
const publicUrl = this.configService.getOrThrow<string>("PUBLIC_URL");
const storageUrl = this.configService.getOrThrow<string>("STORAGE_URL");
let url = this.utils.getUrl();
const publicUrl = this.configService.getOrThrow<string>("PUBLIC_URL");
const storageUrl = this.configService.getOrThrow<string>("STORAGE_URL");
if ([publicUrl, storageUrl].some((url) => url.includes("localhost"))) {
// Switch client URL from `localhost` to `host.docker.internal` in development
// This is required because the browser is running in a container and the client is running on the host machine.
url = url.replace("localhost", "host.docker.internal");
if ([publicUrl, storageUrl].some((url) => url.includes("localhost"))) {
// Switch client URL from `localhost` to `host.docker.internal` in development
// This is required because the browser is running in a container and the client is running on the host machine.
url = url.replace("localhost", "host.docker.internal");
await page.setRequestInterception(true);
await page.setRequestInterception(true);
// Intercept requests of `localhost` to `host.docker.internal` in development
page.on("request", (request) => {
if (request.url().startsWith(storageUrl)) {
const modifiedUrl = request.url().replace("localhost", `host.docker.internal`);
// Intercept requests of `localhost` to `host.docker.internal` in development
page.on("request", (request) => {
if (request.url().startsWith(storageUrl)) {
const modifiedUrl = request.url().replace("localhost", `host.docker.internal`);
request.continue({ url: modifiedUrl });
} else {
request.continue();
}
});
request.continue({ url: modifiedUrl });
} else {
request.continue();
}
});
}
// Set the data of the resume to be printed in the browser's session storage
const numPages = resume.data.metadata.layout.length;
await page.evaluateOnNewDocument((data) => {
window.localStorage.setItem("resume", JSON.stringify(data));
}, resume.data);
await page.goto(`${url}/artboard/preview`, { waitUntil: "networkidle0" });
const pagesBuffer: Buffer[] = [];
const processPage = async (index: number) => {
const pageElement = await page.$(`[data-page="${index}"]`);
const width = (await (await pageElement?.getProperty("scrollWidth"))?.jsonValue()) ?? 0;
const height = (await (await pageElement?.getProperty("scrollHeight"))?.jsonValue()) ?? 0;
const tempHtml = await page.evaluate((element: HTMLDivElement) => {
const clonedElement = element.cloneNode(true) as HTMLDivElement;
const tempHtml = document.body.innerHTML;
document.body.innerHTML = `${clonedElement.outerHTML}`;
return tempHtml;
}, pageElement);
pagesBuffer.push(await page.pdf({ width, height, printBackground: true }));
await page.evaluate((tempHtml: string) => {
document.body.innerHTML = tempHtml;
}, tempHtml);
};
// Loop through all the pages and print them, by first displaying them, printing the PDF and then hiding them back
for (let index = 1; index <= numPages; index++) {
await processPage(index);
}
// Using 'pdf-lib', merge all the pages from their buffers into a single PDF
const pdf = await PDFDocument.create();
pdf.registerFontkit(fontkit);
// Get information about fonts used in the resume from the metadata
const fontData = resume.data.metadata.typography.font;
const fontUrls = getFontUrls(fontData.family, fontData.variants);
// Load all the fonts from the URLs using HttpService
const responses = await Promise.all(
fontUrls.map((url) =>
this.httpService.axiosRef.get(url, {
responseType: "arraybuffer",
}),
),
);
const fontsBuffer = responses.map((response) => response.data as ArrayBuffer);
// Embed all the fonts in the PDF
await Promise.all(fontsBuffer.map((buffer) => pdf.embedFont(buffer)));
for (let index = 0; index < pagesBuffer.length; index++) {
const page = await PDFDocument.load(pagesBuffer[index]);
const [copiedPage] = await pdf.copyPages(page, [0]);
pdf.addPage(copiedPage);
}
// Save the PDF to storage and return the URL to download the resume
// Store the URL in cache for future requests, under the previously generated hash digest
const buffer = Buffer.from(await pdf.save());
// This step will also save the resume URL in cache
const resumeUrl = await this.storageService.uploadObject(
resume.userId,
"resumes",
buffer,
resume.id,
);
// Close all the pages and disconnect from the browser
await page.close();
browser.disconnect();
return resumeUrl;
} catch (error) {
console.trace(error);
}
// Set the data of the resume to be printed in the browser's session storage
const numPages = resume.data.metadata.layout.length;
await page.evaluateOnNewDocument((data) => {
window.localStorage.setItem("resume", JSON.stringify(data));
}, resume.data);
await page.goto(`${url}/artboard/preview`, { waitUntil: "networkidle0" });
const pagesBuffer: Buffer[] = [];
const processPage = async (index: number) => {
const pageElement = await page.$(`[data-page="${index}"]`);
const width = (await (await pageElement?.getProperty("scrollWidth"))?.jsonValue()) ?? 0;
const height = (await (await pageElement?.getProperty("scrollHeight"))?.jsonValue()) ?? 0;
const tempHtml = await page.evaluate((element: HTMLDivElement) => {
const clonedElement = element.cloneNode(true) as HTMLDivElement;
const tempHtml = document.body.innerHTML;
document.body.innerHTML = `${clonedElement.outerHTML}`;
return tempHtml;
}, pageElement);
pagesBuffer.push(await page.pdf({ width, height, printBackground: true }));
await page.evaluate((tempHtml: string) => {
document.body.innerHTML = tempHtml;
}, tempHtml);
};
// Loop through all the pages and print them, by first displaying them, printing the PDF and then hiding them back
for (let index = 1; index <= numPages; index++) {
await processPage(index);
}
// Using 'pdf-lib', merge all the pages from their buffers into a single PDF
const pdf = await PDFDocument.create();
pdf.registerFontkit(fontkit);
// Get information about fonts used in the resume from the metadata
const fontData = resume.data.metadata.typography.font;
const fontUrls = getFontUrls(fontData.family, fontData.variants);
// Load all the fonts from the URLs using HttpService
const responses = await Promise.all(
fontUrls.map((url) =>
this.httpService.axiosRef.get(url, {
responseType: "arraybuffer",
}),
),
);
const fontsBuffer = responses.map((response) => response.data as ArrayBuffer);
// Embed all the fonts in the PDF
await Promise.all(fontsBuffer.map((buffer) => pdf.embedFont(buffer)));
for (let index = 0; index < pagesBuffer.length; index++) {
const page = await PDFDocument.load(pagesBuffer[index]);
const copiedPage = await pdf.copyPages(page, [0]);
pdf.addPage(copiedPage[0]);
}
// Save the PDF to storage and return the URL to download the resume
// Store the URL in cache for future requests, under the previously generated hash digest
const buffer = Buffer.from(await pdf.save());
// This step will also save the resume URL in cache
const resumeUrl = await this.storageService.uploadObject(
resume.userId,
"resumes",
buffer,
resume.id,
);
// Close all the pages and disconnect from the browser
await page.close();
browser.disconnect();
return resumeUrl;
}
async generatePreview(resume: ResumeDto) {
+1 -2
View File
@@ -1,4 +1,4 @@
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
import { BadRequestException, Injectable } from "@nestjs/common";
import { Prisma } from "@prisma/client";
import { CreateResumeDto, ImportResumeDto, ResumeDto, UpdateResumeDto } from "@reactive-resume/dto";
import { defaultResumeData, ResumeData } from "@reactive-resume/schema";
@@ -18,7 +18,6 @@ import { UtilsService } from "../utils/utils.service";
@Injectable()
export class ResumeService {
private readonly redis: Redis;
private readonly logger = new Logger(ResumeService.name);
constructor(
private readonly prisma: PrismaService,