{"id":28066,"date":"2022-08-11T12:52:38","date_gmt":"2022-08-11T12:52:38","guid":{"rendered":"http:\/\/generate-resumes-with-cloudinary-and-nextjs"},"modified":"2022-08-11T12:52:38","modified_gmt":"2022-08-11T12:52:38","slug":"generate-resumes-with-cloudinary-and-nextjs","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/","title":{"rendered":"Generate Resumes with Cloudinary &amp; NextJS"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>What\u2019s more popular than landing your next tech job? Nothing. And even then, how are you sure you\u2019re doing the right thing? Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.<\/p>\n<p><a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a> offers an end-to-end solution for all our image and video needs, including the upload, storage, administration, transformation, and optimized delivery.<\/p>\n<p><a href=\"https:\/\/nextjs.org\/\">Next.js<\/a> is a React-based frontend development framework that supports server-side rendering and static site generation.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/cloudinary-nextjs-resume-generator-hxv2ge?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Generate Resumes with Cloudinary &amp; Next.js\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>Prerequisites<\/h2>\n<p>This post requires the following:<\/p>\n<ul>\n<li>Experience with JavaScript and react.js<\/li>\n<li>Installation of Node.js<\/li>\n<li>A Cloudinary account. <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">Signup<\/a> is free!<\/li>\n<\/ul>\n<h2>Getting started<\/h2>\n<p>We start by downloading this <a href=\"https:\/\/www.canva.com\/design\/DAFINjs0heo\/o4qJQjyoDhb_s9H22Yg4Jw\/edit?utm_content=DAFINjs0heo&amp;utm_campaign=designshare&amp;utm_medium=link2&amp;utm_source=sharebutton\">Canva resume template<\/a>, and uploading the PDF file  to Cloudinary.<\/p>\n<p><a href=\"https:\/\/cloudinary.com\/users\/login\">Log in<\/a> to Cloudinary and follow the steps below to upload the file.<\/p>\n<ol>\n<li>\n<p>Click on \u201cMedia Library\u201d from the dashboard.<\/p>\n<\/li>\n<li>\n<p>Click on the <strong>Upload<\/strong> button.<\/p>\n<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_6716FCD8F2E88FFE63A952C7E3F742670F61204CA1BB3DD04A842EBA5A7128DC_1659635114043_Screenshot+2022-08-04+at+18.41.53.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1306\" height=\"706\"\/><\/p>\n<ol start=\"3\">\n<li>In the dialog box, navigate to \u201cMy Files,\u201d drag and drop the PDF file or browse to its directory to upload them.<\/li>\n<\/ol>\n<p>After successful upload we should note the file \u201cPublic-Id.\u201d; we\u2019ll be using it later.<\/p>\n<h2>Setting up Next.js application<\/h2>\n<p>Run the following command in the terminal to create a new Next.js application:<\/p>\n<pre><code>npx create-next-app resume-generator\n<\/code><\/pre>\n<p>The above command creates a starter next.js application in the <strong>resume-generator<\/strong> folder.<\/p>\n<p>Next, we\u2019ll navigate into the project directory and start the application with the following commands:<\/p>\n<pre><code>cd resume-generator # to navigate into the project directory\nnpm run dev # to run the dev server\n<\/code><\/pre>\n<p>Next.js will start a live development server at <a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a>.<\/p>\n<h2>Building the Resume Generator<\/h2>\n<p>We\u2019ll start by installing the <a href=\"https:\/\/www.npmjs.com\/package\/@cloudinary\/url-gen\">@cloudinary\/url-gen<\/a> package with the following command:<\/p>\n<pre><code>npm install @cloudinary\/url-gen #to access cloudinary SDK in react environment\n<\/code><\/pre>\n<p>Next, in the root directory of our project, let\u2019s create a components <strong>folder<\/strong> and <code>Form.js<\/code> file with the following snippets:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/components\/Form.js<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Form<\/span>(<span class=\"hljs-params\">{ userDetails, setUserDetails, handleSubmit }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> {\n        firstname,\n        lastname,\n        email,\n        mobile,\n        website,\n        course,\n        role,\n        company,\n        position,\n        school,\n        country,\n        state,\n        interest_1,\n        interest_2,\n        interest_3,\n      } = userDetails;\n    \n      <span class=\"hljs-keyword\">const<\/span> handleChange = <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>) =&gt;<\/span> {\n        setUserDetails({ ...userDetails, &#91;e.target.name]: e.target.value });\n      };\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"hljs-comment\">\/\/form inputs &amp; Submit button here<\/span>\n      );\n    }\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Form;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here:<\/p>\n<ul>\n<li>We destructured <code>userDetails<\/code>, <code>setUserDetails<\/code>, and <code>handleSubmit<\/code> props that we\u2019ll pass to this component later in the index.js file.<\/li>\n<li>Destructured user information from the <code>userDetails<\/code> and created the <code>handleChange()<\/code> function using the <code>setUserDetails<\/code> prop; this function will update the user information with the form input values.<\/li>\n<\/ul>\n<p>In the <code>return()<\/code> function of the <code>Form.js<\/code> component, we:<\/p>\n<ul>\n<li>Created the form to collect the user information and created a <strong>Submit<\/strong> button to submit the information.<\/li>\n<li>Passed the <code>handleChange()<\/code> function and the <code>handleSubmit()<\/code> function to the form input and the <strong>Submit<\/strong> button, respectively<\/li>\n<\/ul>\n<p>The complete snippets of the <code>Form.js<\/code> component are in this <a href=\"https:\/\/gist.github.com\/Kizmelvin\/4842dbb252149ad876e46e55664dbf5a\">GitHub Gist<\/a>.<\/p>\n<p>Next, let\u2019s clean up the <code>index.js<\/code> file and update it with the following snippets:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/pages\/index.js<\/span>\n    <span class=\"hljs-keyword\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/head\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/styles\/Home.module.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Form <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Form\"<\/span>;\n    \n    <span class=\"hljs-keyword\">const<\/span> initialState = {\n      <span class=\"hljs-attr\">email<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n      <span class=\"hljs-attr\">phone<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n      <span class=\"hljs-attr\">role<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n      <span class=\"hljs-attr\">school<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n      <span class=\"hljs-comment\">\/\/ init more user details (website, course, etc)<\/span>\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> &#91;userDetails, setUserDetails] = useState(initialState);\n      <span class=\"hljs-keyword\">const<\/span> &#91;showPDF, setShowPDF] = useState(<span class=\"hljs-literal\">false<\/span>);\n    \n      <span class=\"hljs-keyword\">const<\/span> handleSubmit = <span class=\"hljs-keyword\">async<\/span> (e) =&gt; {\n        e.preventDefault();\n        setShowPDF(<span class=\"hljs-literal\">true<\/span>);\n      };\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"hljs-comment\">\/\/ return statement here<\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the above snippets, we:<\/p>\n<ul>\n<li>Imported <code>useState<\/code> from \u201creact\u201d and <code>Form<\/code> from the components folder.<\/li>\n<li>Created <code>initialState<\/code> object that houses the information expected from a user.<\/li>\n<li>Created <code>userDetails<\/code> and <code>showPDF<\/code> constants and used the <code>useState<\/code> hook to set their values to <code>initialState<\/code> and <code>false<\/code>, respectively.<\/li>\n<li>Created <code>handleSubmit()<\/code> function that will update the value of the <code>showPDF<\/code> to true.<\/li>\n<\/ul>\n<p>Next, let\u2019s set up the <code>return()<\/code> statement in our <code>index.js<\/code> file to render the form on the browser:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/head\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/styles\/Home.module.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Form <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Form\"<\/span>;\n    \n    <span class=\"hljs-keyword\">const<\/span> initialState = {\n      <span class=\"hljs-comment\">\/\/ Init user details here<\/span>\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> &#91;userDetails, setUserDetails] = useState(initialState);\n      <span class=\"hljs-keyword\">const<\/span> &#91;showPDF, setShowPDF] = useState(<span class=\"hljs-literal\">false<\/span>);\n    \n     <span class=\"hljs-comment\">\/\/ handleSubmit() function here<\/span>\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Resume Generator<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Generated by create next app\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Form<\/span>\n              <span class=\"hljs-attr\">userDetails<\/span>=<span class=\"hljs-string\">{userDetails}<\/span>\n              <span class=\"hljs-attr\">setUserDetails<\/span>=<span class=\"hljs-string\">{setUserDetails}<\/span>\n              <span class=\"hljs-attr\">handleSubmit<\/span>=<span class=\"hljs-string\">{handleSubmit}<\/span>\n            \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we gave the application a title, rendered the <code>Form<\/code> we imported from the components <strong>folder<\/strong>, and passed <code>userDetails<\/code>, <code>setUserDetails<\/code>, and <code>handleSubmit<\/code> as props to it.<\/p>\n<p>In the browser, we should have the application working like below:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_6716FCD8F2E88FFE63A952C7E3F742670F61204CA1BB3DD04A842EBA5A7128DC_1659836830040_resume-form.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1070\" height=\"720\"\/><\/p>\n<p>Now let\u2019s fetch the resume template we saved earlier and use Cloudinary transformations to overlay the user information on the template.<\/p>\n<p>To achieve that, create a <code>Template.js<\/code> file inside the components folder with the following snippets.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/ components\/template.js<\/span>\n    <span class=\"hljs-keyword\">import<\/span> { Cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { source } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/actions\/overlay\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { text } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/qualifiers\/source\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { TextStyle } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/qualifiers\/textStyle\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Position } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/qualifiers\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { compass } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/qualifiers\/gravity\"<\/span>;\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\">{ userDetails, setUserDetails, setShowPDF, initialState }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> {\n        firstname,\n        lastname,\n        email,\n        mobile,\n        website,\n      <span class=\"hljs-comment\">\/\/ init more user details (school, course, etc)<\/span>\n      } = userDetails;\n    \n      <span class=\"hljs-keyword\">const<\/span> cld = <span class=\"hljs-keyword\">new<\/span> Cloudinary({\n        <span class=\"hljs-attr\">cloud<\/span>: {\n          <span class=\"hljs-attr\">cloudName<\/span>: <span class=\"hljs-string\">\"CLOUD_NAME\"<\/span>,\n        },\n      });\n    \n      <span class=\"hljs-keyword\">const<\/span> template = cld\n        .image(<span class=\"hljs-string\">\"YOUR_IMAGE_URL\"<\/span>)\n        .addFlag(<span class=\"hljs-string\">\"rasterize\"<\/span>);\n    \n      <span class=\"hljs-keyword\">return<\/span> ();\n    }\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the above snippets, we:<\/p>\n<ul>\n<li>Imported <code>Cloudinary<\/code> and some action qualifiers from \u201c@cloudinary\/url-gen.\u201d<\/li>\n<li>Destructured user information from the <code>userDetails<\/code> prop we\u2019ll pass when rendering the <code>Template.js<\/code> component in the <code>index.js<\/code> file.<\/li>\n<li>Instantiated a new <code>Cloudinary<\/code> instance with our <code>cloudName<\/code>, saved the <code>Cloudinary<\/code> instance as <code>template<\/code> constant, and passed the file public_id we held earlier.<\/li>\n<\/ul>\n<p>Next, let\u2019s overlay the user information on the PDF file using <code>Cloudinary<\/code> transformation.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/ components\/template.js<\/span>\n    template.overlay(\n        source(\n          text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${firstname}<\/span> <span class=\"hljs-subst\">${lastname}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Nunito\"<\/span>, <span class=\"hljs-number\">60<\/span>)).textColor(\n            <span class=\"hljs-string\">\"black\"<\/span>\n          )\n        ).position(\n          <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"north\"<\/span>)).offsetY(<span class=\"hljs-number\">200<\/span>).offsetX(<span class=\"hljs-number\">-400<\/span>)\n        )\n      );\n      <span class=\"hljs-comment\">\/\/Education Overlay<\/span>\n      template\n        .overlay(\n          source(text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${school}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>))).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"west\"<\/span>)).offsetY(<span class=\"hljs-number\">50<\/span>).offsetX(<span class=\"hljs-number\">100<\/span>)\n          )\n        )\n        .overlay(\n          source(\n            text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${course}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>)).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"west\"<\/span>)).offsetY(<span class=\"hljs-number\">120<\/span>).offsetX(<span class=\"hljs-number\">100<\/span>)\n          )\n        );\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we overlaid the user\u2019s firstname, lastname, and education information onto the template directly from Cloudinary. Next, lets overlay the user\u2019s contact and profile informations:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">     <span class=\"hljs-comment\">\/\/ Contacts Overlay<\/span>\n      template\n        .overlay(\n          source(\n            text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${mobile}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>)).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"west\"<\/span>)).offsetY(<span class=\"hljs-number\">410<\/span>).offsetX(<span class=\"hljs-number\">100<\/span>)\n          )\n        )\n        .overlay(\n          source(\n            text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${email}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>)).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"west\"<\/span>)).offsetY(<span class=\"hljs-number\">510<\/span>).offsetX(<span class=\"hljs-number\">100<\/span>)\n          )\n        )\n        .overlay(\n          source(\n            text(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${website}<\/span>`<\/span>, <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>)).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"west\"<\/span>)).offsetY(<span class=\"hljs-number\">610<\/span>).offsetX(<span class=\"hljs-number\">100<\/span>)\n          )\n        );\n      <span class=\"hljs-comment\">\/\/ Profile Overlays<\/span>\n      template\n        .overlay(\n          source(\n            text(\n              <span class=\"hljs-string\">`I'm <span class=\"hljs-subst\">${firstname}<\/span>  <span class=\"hljs-subst\">${lastname}<\/span>,`<\/span>,\n              <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">40<\/span>)\n            ).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"north\"<\/span>)).offsetY(<span class=\"hljs-number\">300<\/span>).offsetX(<span class=\"hljs-number\">200<\/span>)\n          )\n        )\n        .overlay(\n          source(\n            text(\n              <span class=\"hljs-string\">`a <span class=\"hljs-subst\">${role}<\/span> from <span class=\"hljs-subst\">${state}<\/span>, <span class=\"hljs-subst\">${country}<\/span>.`<\/span>,\n              <span class=\"hljs-keyword\">new<\/span> TextStyle(<span class=\"hljs-string\">\"Times\"<\/span>, <span class=\"hljs-number\">30<\/span>)\n            ).textColor(<span class=\"hljs-string\">\"gray\"<\/span>)\n          ).position(\n            <span class=\"hljs-keyword\">new<\/span> Position().gravity(compass(<span class=\"hljs-string\">\"north\"<\/span>)).offsetY(<span class=\"hljs-number\">350<\/span>).offsetX(<span class=\"hljs-number\">200<\/span>)\n          )\n        );\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Repeat this process and overlay the user\u2019s work experience information and any other interests onto the resume template. With all the necessary information overlaid onto the template, our resume is complete. Next, let\u2019s transform it into a downloadable Image that users can access via a URL:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">const<\/span> pdfTemplate = template.toURL();\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">iframe<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{pdfTemplate}<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"778\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">iframe<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"mt-3\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n              <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> {\n                setUserDetails(initialState);\n                setShowPDF(false);\n              }}\n              className=\"btn btn-primary\"\n            &gt;\n              Generate New Resume\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we:<\/p>\n<ul>\n<li>Transformed the <code>template<\/code> to a URL with the <code>toURL()<\/code> Cloudinary function and displayed the <code>template<\/code> in <code>return()<\/code> function.<\/li>\n<li>Created a <strong>Generate New Resume<\/strong> button that clears the form so a user can generate a new resume.<\/li>\n<\/ul>\n<p>We can find the complete snippets of the <code>Template.js<\/code> in this <a href=\"https:\/\/gist.github.com\/Kizmelvin\/653bae6edf45d0da4a050d4049268924\">Github Gist<\/a>.<\/p>\n<p>Next, let\u2019s import and render the <code>Template.js<\/code> component inside the <code>index.js<\/code> page and pass the <code>userDetails<\/code> to it. Update the <code>index.js<\/code> like in the below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-comment\">\/\/ Other imports here<\/span>\n    <span class=\"hljs-keyword\">import<\/span> Template <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/components\/Template\"<\/span>;\n    <span class=\"hljs-comment\">\/\/ Init state here<\/span>\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> &#91;userDetails, setUserDetails] = useState(initialState);\n      <span class=\"hljs-keyword\">const<\/span> &#91;showPDF, setShowPDF] = useState(<span class=\"hljs-literal\">false<\/span>);\n     \n    <span class=\"hljs-comment\">\/\/ handleSubmit function here<\/span>\n    \n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n            \/\/ Head tag here\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n           \/\/ Form component here\n           {showPDF &amp;&amp; (\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Template<\/span>\n                  <span class=\"hljs-attr\">userDetails<\/span>=<span class=\"hljs-string\">{userDetails}<\/span>\n                  <span class=\"hljs-attr\">setShowPDF<\/span>=<span class=\"hljs-string\">{setShowPDF}<\/span>\n                  <span class=\"hljs-attr\">setUserDetails<\/span>=<span class=\"hljs-string\">{setUserDetails}<\/span>\n                  <span class=\"hljs-attr\">initialState<\/span>=<span class=\"hljs-string\">{initialState}<\/span>\n                \/&gt;<\/span>\n              )}\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the above snippet, we import the <code>Template.js<\/code> file from the components folder, used the <code>showPDF<\/code> boolean to render it conditionally, and then passed-in the required properties.<\/p>\n<p>In the browser, when a user fills the form and clicks on the <strong>Generate Resume<\/strong> button, the resume gets generated with the information the user provided.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_6716FCD8F2E88FFE63A952C7E3F742670F61204CA1BB3DD04A842EBA5A7128DC_1659948063508_generated.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1280\" height=\"654\"\/><\/p>\n<h2>Conclusion<\/h2>\n<p>This post explored rich Cloudinary transformation APIs and discussed building a resume generator app that collects user information and generates a PDF resume with Next.js.<\/p>\n<h2>Resources<\/h2>\n<p><a href=\"https:\/\/cloudinary.com\/documentation\/layers\">Cloudinary text overlays<\/a> might be a helpful resource.<\/p>\n<p><a href=\"https:\/\/github.com\/kenny-io\/cloudinary-resume-generator\">Github Repository<\/a><\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28067,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,212,371],"class_list":["post-28066","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-next-js","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Generate Resumes with Cloudinary &amp; NextJS<\/title>\n<meta name=\"description\" content=\"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Generate Resumes with Cloudinary &amp; NextJS\" \/>\n<meta property=\"og:description\" content=\"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-11T12:52:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"4032\" \/>\n\t<meta property=\"og:image:height\" content=\"3024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Generate Resumes with Cloudinary &amp; NextJS\",\"datePublished\":\"2022-08-11T12:52:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Next.js\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\",\"name\":\"Generate Resumes with Cloudinary &amp; NextJS\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA\",\"datePublished\":\"2022-08-11T12:52:38+00:00\",\"description\":\"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA\",\"width\":4032,\"height\":3024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generate Resumes with Cloudinary &amp; NextJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Generate Resumes with Cloudinary &amp; NextJS","description":"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/","og_locale":"en_US","og_type":"article","og_title":"Generate Resumes with Cloudinary &amp; NextJS","og_description":"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-08-11T12:52:38+00:00","og_image":[{"width":4032,"height":3024,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/"},"author":{"name":"","@id":""},"headline":"Generate Resumes with Cloudinary &amp; NextJS","datePublished":"2022-08-11T12:52:38+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","keywords":["Guest Post","Next.js","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/","name":"Generate Resumes with Cloudinary &amp; NextJS","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","datePublished":"2022-08-11T12:52:38+00:00","description":"Crafting excellent resumes for your different job interests can be a daunting task without some extra help or automation. And even then, how are you sure you\u2019re doing the right thing. In this post, we\u2019ll walk through the process of generating a stellar resume on-demand (PDF) with Cloudinary by supplying only the necessary details via a Next.js form.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","width":4032,"height":3024},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/generate-resumes-with-cloudinary-and-nextjs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Generate Resumes with Cloudinary &amp; NextJS"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681922315\/Web_Assets\/blog\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91\/61244b2bd0f81bf659dfbf37fb56da6271a08db1-4032x3024-1_2806774e91.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28066","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28066"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28066\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28067"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28066"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28066"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28066"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}