{"id":30744,"date":"2026-10-22T10:21:00","date_gmt":"2026-10-22T04:51:00","guid":{"rendered":"https:\/\/internshala.com\/blog\/?p=30744"},"modified":"2026-10-22T22:22:31","modified_gmt":"2026-10-22T16:52:31","slug":"employer-node-js-developer-job-description","status":"publish","type":"post","link":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/","title":{"rendered":"Node. js Developer Job Description: Free Sample &#038; Template"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"427\" src=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description-1-1-1024x427.png\" alt=\"Node.js Developer Job Description (1)\" class=\"wp-image-30747\" srcset=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description-1-1-1024x427.png 1024w, https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description-1-1-672x280.png 672w, https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description-1-1.png 1199w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-pale-cyan-blue-background-color has-background\"><tbody><tr><td><strong>Summary<\/strong>: Node.js powers scalable applications through Chrome\u2019s V8 JavaScript engine and its asynchronous, event-driven architecture. When hiring developers to build and maintain such applications, employers need to define the skills and responsibilities the role requires. A well-structured Node.js developer job description should cover core skills like JavaScript and API development, alongside role-specific requirements such as TypeScript, cloud platforms, and microservices.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Hiring the right Node.js developer starts with knowing what your business needs from the role. Whether you are building a new application, improving an existing product, or expanding your development team, a well-defined job description attracts applicants with relevant skills and experience. It also sets clear expectations about daily tasks, technical requirements, and performance goals. This guide covers a ready-to-use Node.js developer job description format, a sample job post, essential skills, hiring costs, and practical tips to help you make informed recruitment decisions.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_86 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title ez-toc-toggle\" style=\"cursor:pointer\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Who_Is_a_Nodejs_Developer\" >Who Is a Node.js Developer?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Nodejs_Developer_Job_Description_Template\" >Node.js Developer Job Description Template<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Nodejs_Developer_Job_Description_Sample\" >Node.js Developer Job Description Sample<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Cost_for_Hiring_a_Nodejs_Developer\" >Cost for Hiring a Node.js Developer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Tips_for_Writing_a_Strong_Job_Description_for_Hiring_a_Nodejs_Developer\" >Tips for Writing a Strong Job Description for Hiring a Node.js Developer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#Conclusion\" >Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#FAQs\" >FAQs<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Who_Is_a_Nodejs_Developer\"><\/span>Who Is a Node.js Developer?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Node.js is a JavaScript runtime environment that extends the language beyond web browsers for server-side programming. It supports back-end development by enabling you to build web servers, APIs, and other components that process data, connect to databases, and handle user requests.<\/p>\n\n\n\n<p>A Node.js developer builds, tests, and maintains these components to ensure applications function smoothly. They also collaborate with front-end developers, designers, and project managers to develop and maintain digital products.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Nodejs_Developer_Job_Description_Template\"><\/span>Node.js Developer Job Description Template<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A clear <a href=\"https:\/\/internshala.com\/blog\/what-is-job-description\/\" target=\"_blank\" rel=\"noreferrer noopener\">job description<\/a> enables employers to communicate role expectations and attract suitable candidates. Use the following Node.js developer job description template for full-time, part-time, or contract roles, and customize it to match your hiring requirements.<\/p>\n\n\n\n<!-- Job Description Template Builder: paste this whole file into a WordPress \"Custom HTML\" block.\n     The template is filled in from the post the builder is placed in; there are no built-in job templates.\n       Job title: the post's main heading (\"Python Developer Job Description: ...\" or \"Job Description for a Telecaller\").\n       Responsibilities, skills \/ qualifications, role overview and benefits: the post's sample job description (the section\n       under an H2 containing \"sample\", \"template\" or \"example\") first, then matching sections anywhere in the article.\n       Anything not found is left as a [placeholder]. Intern posts get internship details and intern benefits.\n       To choose exactly which blocks are used, add a CSS class in WordPress (block settings > Advanced > Additional CSS class):\n       jd-title, jd-summary, jd-responsibilities, jd-qualifications, jd-benefits.\n     data-role=\"blank\" ignores the post and opens with placeholders only (leave it as \"auto\" otherwise).\n     data-design sets the template style a post opens with: classic, modern (Bold header), simple or sidebar.\n     data-cta-url is where the \"Post this job\" link goes. The builder adds tracking tags to it automatically:\n     utm_source=is_blog, utm_medium=jd_builder, utm_campaign=(the post's URL slug), utm_content=(the job title read from the post). Tags you put in the URL yourself are kept.\n     data-gate=\"form\" asks for name, work email, mobile and company before a download and sends them to data-lead-url (a Google\n       Apps Script web app that adds a row to a Google Sheet). data-gate=\"signup\" asks visitors to create an Internshala\n       account instead. data-gate=\"off\" lets anyone download.\n       Employers already signed in to the site download straight away. To tell, the builder loads data-login-check\n       (default \/employer\/dashboard) in the background: signed-out visitors get a login form there. Others see the sign-up box;\n       sign-up opens in a small window, which closes and the download starts once the site confirms the sign-in.\n       Optional settings, added the same way as data-gate: data-google-url, data-login-url (sign-up and log-in addresses),\n       data-login-cookie (name of a cookie that only signed-in users have), data-gate-fallback=\"off\" (hides the \"I've signed in\"\n       button). Add ?jdgate=reset to a post's address to be asked again.\n     Analytics events sent to GA4 or Tag Manager when present: jd_builder_view, jd_builder_edit,\n     jd_builder_design_change, jd_builder_download, jd_builder_cta_click,\n     jd_builder_gate_open, jd_builder_signup_click, jd_builder_signup_complete, jd_builder_gate_close,\n     jd_builder_already_signed_in, jd_builder_lead_submit -->\n<div id=\"cwjd\" class=\"cwjd\" data-role=\"auto\" data-design=\"classic\" data-gate=\"form\" data-lead-url=\"https:\/\/script.google.com\/macros\/s\/AKfycbz-qprMw0zQmyDBBI7huZ9pGWNbDa8DAlea1nEmt7fvOmcPsY8vySLYyf1tyU4xWsIt3w\/exec\" data-cta-url=\"https:\/\/internshala.com\/hire-talent\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=DM+Sans:wght@400;500;700&#038;family=Fraunces:opsz,wght@9..144,500;9..144,700&#038;display=swap\">\n<style>\n#cwjd,#cwjd *{box-sizing:border-box}\n#cwjd{--ui-ink:#1d1d1b;--ui-muted:#5c5a54;--ui-line:#d9d5cb;--ui-bg:#ffffff;--ui-soft:#f6f4ef;--ui-accent:#0f5e5a;color:var(--ui-ink);font-size:16px;line-height:1.45;text-align:left;margin:32px 0;max-width:none}\n#cwjd .cwjd-app{display:grid;grid-template-columns:1fr;gap:28px;align-items:start}\n#cwjd.cwjd-wide .cwjd-app{grid-template-columns:minmax(290px,360px) minmax(0,1fr);gap:24px}\n#cwjd .cwjd-previewcol{min-width:0}\n#cwjd .cwjd-app{position:relative}\n#cwjd.cwjd-wide.cwjd-sticky:not(.cwjd-expanded) .cwjd-previewcol{position:sticky;top:var(--cwjd-top,16px)}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-actions{gap:8px;margin-bottom:10px}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-actions .cwjd-btn{min-height:40px;padding:8px 14px;font-size:14px;gap:6px}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-actions .cwjd-btn svg{width:16px;height:16px}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-status{min-height:0;margin-bottom:8px}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-status:empty{display:none}\n#cwjd .cwjd-stage{cursor:zoom-in}\n#cwjd.cwjd-expanded .cwjd-previewcol{position:fixed;top:0;left:0;right:0;bottom:0;z-index:2147483000;background:rgba(29,29,27,.88);overflow:auto;padding:20px 16px 40px 16px;transform:none !important}\n#cwjd.cwjd-expanded .cwjd-actions{justify-content:center}\n#cwjd.cwjd-expanded .cwjd-status{text-align:center;color:#ffffff}\n#cwjd.cwjd-expanded .cwjd-btn,#cwjd.cwjd-expanded .cwjd-btn-primary{background:#ffffff;color:#1d1d1b;border-color:#ffffff}\n#cwjd.cwjd-expanded .cwjd-btn:hover{background:#e9e6df}\n#cwjd.cwjd-expanded .cwjd-stage{cursor:default}\n#cwjd .cwjd-form{background:var(--ui-bg);border:1px solid var(--ui-line);border-radius:14px;padding:22px;display:flex;flex-direction:column;gap:22px}\n#cwjd .cwjd-formtitle{font-size:20px;font-weight:700;margin:0 0 4px 0;line-height:1.25}\n#cwjd .cwjd-hint{font-size:14px;color:var(--ui-muted);margin:0}\n#cwjd .cwjd-jump{display:inline-block;margin-top:10px;font-size:14px;font-weight:600;color:var(--ui-accent);text-decoration:underline}\n#cwjd.cwjd-wide .cwjd-jump{display:none}\n#cwjd .cwjd-group{display:flex;flex-direction:column;gap:12px;padding-top:18px;border-top:1px solid var(--ui-line)}\n#cwjd .cwjd-gtitle{font-size:13px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ui-muted);margin:0}\n#cwjd .cwjd-field{display:flex;flex-direction:column;gap:5px;margin:0;font-size:14px;font-weight:600;font-style:normal;color:var(--ui-ink)}\n#cwjd label,#cwjd .cwjd-field span,#cwjd .cwjd-field small{font-style:normal}\n#cwjd .cwjd-field small{font-weight:400;color:var(--ui-muted);font-size:13px}\n#cwjd .cwjd-field input[type=text],#cwjd .cwjd-field textarea,#cwjd .cwjd-field select{width:100%;max-width:none;margin:0;padding:10px 12px;border:1px solid #bdb8ab;border-radius:8px;background:#fff;color:var(--ui-ink);font:inherit;font-weight:400;font-size:15px;line-height:1.45;box-shadow:none;height:auto;min-height:44px}\n#cwjd .cwjd-field textarea{resize:vertical;min-height:96px}\n#cwjd .cwjd-field textarea.cwjd-tall{min-height:190px}\n#cwjd .cwjd-field input:focus,#cwjd .cwjd-field textarea:focus,#cwjd .cwjd-field select:focus{outline:2px solid var(--ui-accent);outline-offset:1px;border-color:var(--ui-accent)}\n#cwjd .cwjd-swatches{display:flex;flex-wrap:wrap;gap:8px;align-items:center}\n#cwjd .cwjd-swatch{width:36px;height:36px;min-height:0;padding:0;margin:0;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px var(--ui-line);cursor:pointer}\n#cwjd .cwjd-swatch[aria-pressed=true]{box-shadow:0 0 0 2px var(--ui-ink)}\n#cwjd .cwjd-colorwrap{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600}\n#cwjd .cwjd-colorwrap input[type=color]{width:44px;height:36px;padding:0;margin:0;border:1px solid #bdb8ab;border-radius:8px;background:#fff;cursor:pointer}\n#cwjd .cwjd-logorow{display:flex;flex-wrap:wrap;gap:8px;align-items:center;font-weight:400}\n#cwjd .cwjd-logorow input[type=file]{font:inherit;font-size:14px;font-weight:400;width:auto;max-width:100%;height:auto;margin:0;padding:6px 0;border:0;background:none;box-shadow:none}\n#cwjd .cwjd-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;margin:0;padding:10px 18px;border-radius:999px;border:1.5px solid var(--ui-ink);background:#fff;color:var(--ui-ink);font:inherit;font-size:15px;font-weight:700;line-height:1.2;text-transform:none;letter-spacing:0;cursor:pointer;box-shadow:none;text-decoration:none}\n#cwjd .cwjd-btn:hover{background:var(--ui-soft)}\n#cwjd .cwjd-btn-primary{background:var(--ui-ink);color:#fff}\n#cwjd .cwjd-btn-primary:hover{background:#3a3a36}\n#cwjd .cwjd-btn-small{min-height:36px;padding:6px 14px;font-size:14px}\n#cwjd .cwjd-btn:disabled{opacity:.55;cursor:wait}\n#cwjd .cwjd-btn svg{width:18px;height:18px;flex:none}\n#cwjd .cwjd-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;padding:0;margin:-1px}\n#cwjd .cwjd-fmt{display:inline-flex;margin:0;position:relative}\n#cwjd .cwjd-select{min-height:44px;height:auto;width:auto;max-width:100%;margin:0;padding:8px 34px 8px 16px;border:1.5px solid var(--ui-ink);border-radius:999px;background-color:#fff;color:var(--ui-ink);font:inherit;font-size:15px;font-weight:700;line-height:1.2;box-shadow:none;cursor:pointer}\n#cwjd .cwjd-select:focus{outline:2px solid var(--ui-accent);outline-offset:1px}\n#cwjd .cwjd-select:disabled{opacity:.55;cursor:wait}\n#cwjd.cwjd-wide:not(.cwjd-expanded) .cwjd-actions .cwjd-select{min-height:40px;padding:6px 30px 6px 14px;font-size:14px}\n#cwjd.cwjd-expanded .cwjd-select{border-color:#ffffff}\n#cwjd .cwjd-formfoot{display:flex;flex-wrap:wrap;gap:10px;padding-top:18px;border-top:1px solid var(--ui-line)}\n#cwjd .cwjd-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 14px 0}\n#cwjd .cwjd-status{font-size:14px;color:var(--ui-muted);min-height:20px;margin:0 0 10px 0}\n#cwjd .cwjd-status.cwjd-err{color:#a1260d;font-weight:600}\n#cwjd .cwjd-gate{position:fixed;top:0;left:0;right:0;bottom:0;z-index:2147483600;background:rgba(29,29,27,.62);display:flex;align-items:center;justify-content:center;padding:16px;overflow:auto;margin:0}\n#cwjd .cwjd-gate-box{position:relative;width:100%;max-width:420px;box-sizing:border-box;background:#ffffff;color:#1d1d1b;border-radius:16px;padding:32px 28px 24px 28px;box-shadow:0 20px 60px rgba(0,0,0,.3);display:flex;flex-direction:column;gap:12px;text-align:left;font-size:15px;line-height:1.45}\n#cwjd .cwjd-gate-x{position:absolute;top:8px;right:8px;width:44px;height:44px;min-height:0;margin:0;padding:0;border:0;border-radius:50%;background:none;color:#5c5a54;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:none}\n#cwjd .cwjd-gate-x:hover{background:#f1efe9}\n#cwjd .cwjd-gate-x svg{width:20px;height:20px}\n#cwjd .cwjd-gate-title{font-size:22px;font-weight:700;line-height:1.25;margin:0;padding-right:36px;color:#1d1d1b}\n#cwjd .cwjd-gate-sub{margin:0 0 6px 0;font-size:15px;line-height:1.45;color:#4a4944}\n#cwjd .cwjd-gate-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;min-height:48px;margin:0;padding:10px 16px;border:1.5px solid #0077c2;border-radius:10px;background:#ffffff;color:#006bb0;font:inherit;font-size:16px;font-weight:700;line-height:1.2;text-transform:none;letter-spacing:0;cursor:pointer;box-shadow:none}\n#cwjd .cwjd-gate-btn:hover{background:#eaf5fc;color:#006bb0}\n#cwjd .cwjd-gate-btn.cwjd-gate-main{background:#0077c2;color:#ffffff}\n#cwjd .cwjd-gate-btn.cwjd-gate-main:hover{background:#006bb0;color:#ffffff}\n#cwjd .cwjd-gate-btn svg{width:20px;height:20px;flex:none}\n#cwjd .cwjd-gate-btn:focus-visible,#cwjd .cwjd-gate-x:focus-visible,#cwjd .cwjd-gate-link:focus-visible{outline:2px solid #1d1d1b;outline-offset:2px}\n#cwjd .cwjd-gate-login,#cwjd .cwjd-gate-terms{margin:0;font-size:14px;line-height:1.45;color:#4a4944}\n#cwjd .cwjd-gate-status{margin:0;font-size:14px;line-height:1.45;font-weight:600;color:#1d1d1b}\n#cwjd .cwjd-gate-status:empty{display:none}\n#cwjd .cwjd-gate-link{display:inline;width:auto;min-height:0;margin:0;padding:0;border:0;border-radius:0;background:none;color:#006bb0;font:inherit;font-weight:700;text-decoration:underline;text-transform:none;letter-spacing:0;cursor:pointer;box-shadow:none}\n#cwjd .cwjd-gate-terms a,#cwjd .cwjd-gate-open{color:#006bb0;text-decoration:underline;font-weight:700}\n#cwjd .cwjd-gate-form{display:flex;flex-direction:column;gap:12px;margin:0}\n#cwjd .cwjd-gate-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}\n#cwjd .cwjd-gate-field{display:flex;flex-direction:column;gap:5px;margin:0;font-size:14px;font-weight:600;font-style:normal;color:#1d1d1b;line-height:1.3}\n#cwjd .cwjd-gate-field input{width:100%;max-width:none;height:auto;min-height:44px;box-sizing:border-box;margin:0;padding:10px 12px;border:1px solid #bdb8ab;border-radius:8px;background:#ffffff;color:#1d1d1b;font:inherit;font-size:15px;font-weight:400;line-height:1.3;box-shadow:none}\n#cwjd .cwjd-gate-field input:focus{outline:2px solid #0077c2;outline-offset:1px;border-color:#0077c2}\n#cwjd .cwjd-gate-field input[aria-invalid=true]{border-color:#a1260d}\n#cwjd .cwjd-gate-tel{display:flex;gap:8px}\n#cwjd .cwjd-gate-cc{flex:none;display:flex;align-items:center;min-height:44px;padding:0 12px;border:1px solid #bdb8ab;border-radius:8px;background:#f6f4ef;font-weight:400;font-size:15px;color:#1d1d1b}\n#cwjd .cwjd-gate-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}\n#cwjd .cwjd-gate-ferr{margin:0;font-size:14px;line-height:1.4;font-weight:600;color:#a1260d}\n#cwjd .cwjd-gate-ferr:empty{display:none}\n#cwjd .cwjd-gate-form .cwjd-gate-btn:disabled{opacity:.6;cursor:wait}\n#cwjd .cwjd-gate-done{display:flex;flex-direction:column;gap:10px;padding-top:12px;border-top:1px solid #d9d5cb}\n#cwjd .cwjd-gate-done .cwjd-btn{width:100%}\n#cwjd .cwjd-cta{display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:44px;margin:0 0 12px 0;padding:8px 14px;border:1px solid #b9dcf2;border-radius:10px;background:#eaf5fc;color:#1d1d1b;font-size:14px;line-height:1.35;font-weight:400;text-decoration:none;box-shadow:none}\n#cwjd .cwjd-cta strong{color:#006bb0;font-weight:700}\n#cwjd .cwjd-cta svg{width:18px;height:18px;flex:none;color:#006bb0}\n#cwjd .cwjd-cta:hover{background:#dcedf9;color:#1d1d1b;text-decoration:none}\n#cwjd .cwjd-cta:focus-visible{outline:2px solid #006bb0;outline-offset:2px}\n#cwjd .cwjd-cta.cwjd-cta-hot{background:#0077c2;border-color:#0077c2;color:#ffffff}\n#cwjd .cwjd-cta.cwjd-cta-hot strong,#cwjd .cwjd-cta.cwjd-cta-hot svg{color:#ffffff}\n#cwjd .cwjd-cta.cwjd-cta-hot:hover{background:#006bb0;color:#ffffff}\n#cwjd.cwjd-expanded .cwjd-cta{max-width:560px;margin-left:auto;margin-right:auto}\n#cwjd .cwjd-stage{position:relative;overflow:hidden;margin:0 auto;max-width:100%;border-radius:10px;box-shadow:0 1px 3px rgba(0,0,0,.12),0 8px 28px rgba(0,0,0,.08);background:#f6f4ef}\n#cwjd .cwjd-scale{position:absolute;top:0;left:0;width:1080px;transform-origin:0 0}\n#cwjd [hidden]{display:none !important}\n#cwjd:not([data-live]) .cwjd-app{display:none}\n#cwjd .cwjd-boot{margin:0;padding:16px 18px;border:1px dashed var(--ui-line);border-radius:12px;background:var(--ui-soft);color:var(--ui-muted);font-size:15px}\n#cwjd .cwjd-boot.cwjd-boot-err{border:1px solid #a1260d;color:#a1260d;background:#fff6f3;font-weight:600}\n\/* ---------- the job description sheet (what gets downloaded) ---------- *\/\n#cwjd .cwjd-scale{--cw-accent:#0f5e5a;--cw-on:#ffffff;--cw-head:#0f5e5a;--cw-display:'Fraunces',Georgia,'Times New Roman',serif;--cw-body:'DM Sans','Helvetica Neue',Helvetica,Arial,sans-serif}\n#cwjd .cwjd-scale[data-font=sans]{--cw-display:'DM Sans','Helvetica Neue',Helvetica,Arial,sans-serif}\n#cwjd .cwjd-sheet{width:1080px;min-height:1400px;box-sizing:border-box;background:#ffffff;color:#1d1d1b;font-family:var(--cw-body);font-size:17px;line-height:1.55;text-align:left;margin:0}\n#cwjd .cwjd-sheet *{margin:0;padding:0;border:0;background:none;text-transform:none;letter-spacing:normal;font-family:inherit;color:inherit;box-shadow:none}\n#cwjd .cwjd-sheet *::before,#cwjd .cwjd-sheet *::after{content:none}\n#cwjd .cwjd-sheet .cw-logo{display:block;max-height:56px;max-width:200px;width:auto;height:auto;object-fit:contain}\n#cwjd .cwjd-sheet .cw-p{white-space:pre-line;overflow-wrap:anywhere}\n#cwjd .cwjd-sheet .cw-list{display:flex;flex-direction:column;gap:10px;min-width:0}\n#cwjd .cwjd-sheet .cw-li{display:flex;gap:12px;align-items:flex-start;line-height:25px;overflow-wrap:anywhere}\n#cwjd .cwjd-sheet .cw-dotbox{flex:none;display:flex;align-items:center;height:25px}\n#cwjd .cwjd-sheet .cw-dot{display:block;width:7px;height:7px;border-radius:50%;background:var(--cw-accent)}\n#cwjd .cwjd-sheet .cw-ph{opacity:.45}\n\/* design 1: Classic *\/\n#cwjd .cw-classic{padding:72px 72px 0 72px;display:flex;flex-direction:column;gap:40px;background:#f6f4ef}\n#cwjd .cw-classic .cw-top{display:flex;flex-direction:column;gap:14px;padding-bottom:36px;border-bottom:2px solid #1d1d1b}\n#cwjd .cw-classic .cw-brandrow{display:flex;justify-content:space-between;align-items:center;gap:24px}\n#cwjd .cw-classic .cw-brand{display:flex;align-items:center;gap:16px;min-width:0}\n#cwjd .cw-classic .cw-company{font-size:18px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;line-height:1.3}\n#cwjd .cw-classic .cw-badge{flex:none;display:flex;align-items:center;height:42px;font-size:16px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;color:var(--cw-on);background:var(--cw-accent);padding:0 18px;border-radius:999px;line-height:42px}\n#cwjd .cw-classic .cw-title{margin-top:12px;font-family:var(--cw-display);font-weight:700;font-size:92px;line-height:1.02;letter-spacing:-.02em;overflow-wrap:anywhere}\n#cwjd .cwjd-scale[data-font=sans] .cw-classic .cw-title{letter-spacing:-.03em}\n#cwjd .cw-classic .cw-details{font-size:20px;color:#4a4944}\n#cwjd .cw-classic .cw-h{font-family:var(--cw-display);font-weight:500;font-size:30px;line-height:1.2;color:var(--cw-head)}\n#cwjd .cwjd-scale[data-font=sans] .cw-classic .cw-h{font-weight:700;font-size:28px}\n#cwjd .cw-classic .cw-sec{display:flex;flex-direction:column;gap:14px;min-width:0}\n#cwjd .cw-classic .cw-row{display:grid;grid-template-columns:1fr 1fr;gap:48px}\n#cwjd .cw-classic .cw-row.cw-single{grid-template-columns:1fr}\n#cwjd .cw-classic .cw-row.cw-qb{grid-template-columns:1.4fr 1fr}\n#cwjd .cw-classic .cw-row.cw-qb.cw-single{grid-template-columns:1fr}\n#cwjd .cw-classic .cw-card{background:#ffffff;border:1px solid #d9d5cb;border-radius:16px;padding:32px;align-self:start}\n#cwjd .cw-classic .cw-foot{margin:auto -72px 0 -72px;background:var(--cw-accent);color:var(--cw-on);padding:44px 72px;display:flex;justify-content:space-between;align-items:center;gap:32px}\n#cwjd .cw-classic .cw-foot-l{display:flex;flex-direction:column;gap:6px;min-width:0}\n#cwjd .cw-classic .cw-foot-h{font-family:var(--cw-display);font-weight:700;font-size:34px;line-height:1.2}\n#cwjd .cw-classic .cw-foot-t{font-size:18px}\n#cwjd .cw-classic .cw-contact{flex:none;max-width:520px;font-size:24px;font-weight:700;border:2px solid var(--cw-on);border-radius:999px;padding:14px 28px;overflow-wrap:anywhere;text-align:center;line-height:1.3}\n\/* design 2: Bold header *\/\n#cwjd .cw-modern{display:flex;flex-direction:column}\n#cwjd .cw-modern .m-head{background:var(--cw-accent);color:var(--cw-on);padding:60px 72px 56px 72px;display:flex;flex-direction:column;gap:16px}\n#cwjd .cw-modern .m-brandrow{display:flex;justify-content:space-between;align-items:center;gap:24px}\n#cwjd .cw-modern .m-brand{display:flex;align-items:center;gap:16px;min-width:0}\n#cwjd .cw-modern .m-brand .cw-logo{background:#ffffff;padding:8px 12px;border-radius:10px;box-sizing:content-box}\n#cwjd .cw-modern .m-company{font-size:18px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;line-height:1.3}\n#cwjd .cw-modern .m-badge{flex:none;display:flex;align-items:center;height:40px;padding:0 18px;border:2px solid var(--cw-on);border-radius:999px;font-size:15px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;line-height:36px}\n#cwjd .cw-modern .m-title{margin-top:22px;font-family:var(--cw-display);font-weight:700;font-size:84px;line-height:1.04;letter-spacing:-.02em;overflow-wrap:anywhere}\n#cwjd .cw-modern .m-details{font-size:20px;opacity:.9}\n#cwjd .cw-modern .m-body{flex:1;display:grid;grid-template-columns:1.55fr 1fr;gap:56px;padding:52px 72px 64px 72px;align-items:start}\n#cwjd .cw-modern .m-main,#cwjd .cw-modern .m-side{display:flex;flex-direction:column;gap:36px;min-width:0}\n#cwjd .cw-modern .m-sec{display:flex;flex-direction:column;gap:14px;min-width:0}\n#cwjd .cw-modern .m-h{font-size:15px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--cw-head);line-height:1.3;padding-bottom:10px;border-bottom:2px solid var(--cw-accent)}\n#cwjd .cw-modern .m-card{display:flex;flex-direction:column;gap:14px;background:#f3f2ee;border-radius:14px;padding:26px}\n#cwjd .cw-modern .m-card .m-h{border-bottom:0;padding-bottom:0}\n#cwjd .cw-modern .m-apply{display:flex;flex-direction:column;gap:8px;border:2px solid var(--cw-accent);border-radius:14px;padding:26px}\n#cwjd .cw-modern .m-apply-h{font-family:var(--cw-display);font-weight:700;font-size:26px;line-height:1.2}\n#cwjd .cw-modern .m-apply-t{font-size:16px}\n#cwjd .cw-modern .m-contact{font-size:19px;font-weight:700;color:var(--cw-head);overflow-wrap:anywhere}\n\/* design 3: Simple *\/\n#cwjd .cw-simple{padding:84px 88px 76px 88px;display:flex;flex-direction:column;gap:30px}\n#cwjd .cw-simple .n-top{display:flex;flex-direction:column;gap:14px;padding-bottom:10px}\n#cwjd .cw-simple .n-brand{display:flex;align-items:center;gap:14px}\n#cwjd .cw-simple .n-company{font-size:17px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--cw-head);line-height:1.3}\n#cwjd .cw-simple .n-badge{margin-left:auto;flex:none;font-size:14px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#5c5a54;white-space:nowrap}\n#cwjd .cw-simple .n-title{margin-top:20px;font-family:var(--cw-display);font-weight:700;font-size:72px;line-height:1.05;letter-spacing:-.02em;overflow-wrap:anywhere}\n#cwjd .cw-simple .n-details{font-size:20px;color:#4a4944}\n#cwjd .cw-simple .n-sec{display:grid;grid-template-columns:210px 1fr;gap:36px;padding-top:28px;border-top:1px solid #d3d1c9}\n#cwjd .cw-simple .n-h{font-size:15px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--cw-head);line-height:1.5;padding-top:2px}\n#cwjd .cw-simple .n-apply{margin-top:auto;padding-top:28px;border-top:2px solid var(--cw-accent);display:flex;flex-direction:column;gap:6px}\n#cwjd .cw-simple .n-apply-h{font-family:var(--cw-display);font-weight:700;font-size:26px;line-height:1.2}\n#cwjd .cw-simple .n-apply-row{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:18px}\n#cwjd .cw-simple .n-contact{font-weight:700;color:var(--cw-head);overflow-wrap:anywhere}\n\/* design 4: Sidebar *\/\n#cwjd .cw-sidebar{display:flex;flex-direction:row;align-items:stretch}\n#cwjd .cw-sidebar .s-side{flex:none;width:350px;box-sizing:border-box;background:var(--cw-accent);color:var(--cw-on);padding:64px 40px 56px 40px;display:flex;flex-direction:column;gap:34px}\n#cwjd .cw-sidebar .s-side .cw-dot{background:var(--cw-on)}\n#cwjd .cw-sidebar .s-brand{display:flex;flex-direction:column;align-items:flex-start;gap:16px}\n#cwjd .cw-sidebar .s-brand .cw-logo{background:#ffffff;padding:8px 12px;border-radius:10px;box-sizing:content-box}\n#cwjd .cw-sidebar .s-company{font-size:19px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;line-height:1.3;overflow-wrap:anywhere}\n#cwjd .cw-sidebar .s-badge{align-self:flex-start;display:flex;align-items:center;height:38px;padding:0 16px;border:2px solid var(--cw-on);border-radius:999px;font-size:14px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;line-height:34px}\n#cwjd .cw-sidebar .s-sec{display:flex;flex-direction:column;gap:12px;font-size:16px;line-height:1.55}\n#cwjd .cw-sidebar .s-h{font-size:14px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;opacity:.85}\n#cwjd .cw-sidebar .s-apply{margin-top:auto;display:flex;flex-direction:column;gap:8px;padding-top:28px;border-top:1px solid var(--cw-on)}\n#cwjd .cw-sidebar .s-apply-h{font-family:var(--cw-display);font-weight:700;font-size:24px;line-height:1.2}\n#cwjd .cw-sidebar .s-apply-t{font-size:15px}\n#cwjd .cw-sidebar .s-contact{font-size:17px;font-weight:700;overflow-wrap:anywhere}\n#cwjd .cw-sidebar .s-main{flex:1;min-width:0;padding:64px 64px 64px 56px;display:flex;flex-direction:column;gap:34px}\n#cwjd .cw-sidebar .s-headline{display:flex;flex-direction:column;gap:14px;padding-bottom:30px;border-bottom:2px solid #1d1d1b}\n#cwjd .cw-sidebar .s-title{font-family:var(--cw-display);font-weight:700;font-size:72px;line-height:1.05;letter-spacing:-.02em;overflow-wrap:anywhere}\n#cwjd .cw-sidebar .s-details{font-size:20px;color:#4a4944}\n#cwjd .cw-sidebar .s-msec{display:flex;flex-direction:column;gap:14px}\n#cwjd .cw-sidebar .s-mh{font-family:var(--cw-display);font-weight:500;font-size:28px;line-height:1.2;color:var(--cw-head)}\n#cwjd .cwjd-scale[data-font=sans] .cw-sidebar .s-mh{font-weight:700;font-size:26px}\n<\/style>\n<p class=\"cwjd-boot\">Loading the job description builder\u2026 If this message doesn&#8217;t go away, scripts are being blocked or removed on this page.<\/p>\n<script>\n(function () {\n  var s = document.currentScript, r = (s && s.closest) ? s.closest('.cwjd') : null;\n  if (!r) return;\n  var b = r.querySelector('.cwjd-boot'), err = '';\n  if (b) b.textContent = 'Loading the job description builder\u2026';\n  function onErr(e) {\n    var m = (e && e.message) || '';\n    if (!err && \/SyntaxError\/i.test(m) && (!e.filename || e.filename.split('#')[0] === location.href.split('#')[0])) err = m + (e.lineno ? ' (line ' + e.lineno + ')' : '');\n  }\n  window.addEventListener('error', onErr);\n  function check() {\n    window.removeEventListener('error', onErr);\n    if (!b || r.getAttribute('data-live') || \/cwjd-boot-err\/.test(b.className)) return;\n    b.className = 'cwjd-boot cwjd-boot-err';\n    b.textContent = err ? \"The job description builder's code was changed or cut off when it was saved, so it can't run. Browser error: \" + err\n      : \"The job description builder's main code didn't run on this page. It may have been removed, cut off while pasting, or delayed by a speed plugin.\";\n  }\n  if (document.readyState === 'complete') setTimeout(check, 2500);\n  else window.addEventListener('load', function () { setTimeout(check, 2500); });\n})();\n<\/script>\n<div class=\"cwjd-app\">\n<div class=\"cwjd-form\">\n<div class=\"cwjd-formhead\">\n<div class=\"cwjd-formtitle\">Customize your job description<\/div>\n<p class=\"cwjd-hint\">The job title, responsibilities and skills are filled in from this article. Edit any field and the preview updates as you type. Everything stays in your browser, nothing is uploaded.<\/p>\n<a class=\"cwjd-jump\" href=\"#cwjd-previewcol\">Jump to preview and download<\/a>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Template<\/div>\n<label class=\"cwjd-field\">Template style <small>Changes the look only. Your text stays the same.<\/small><select id=\"cwjd-design\"><option value=\"classic\">Classic<\/option><option value=\"modern\">Bold header<\/option><option value=\"simple\">Simple<\/option><option value=\"sidebar\">Sidebar<\/option><\/select><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Company &amp; branding<\/div>\n<label class=\"cwjd-field\">Company name<input type=\"text\" data-field=\"companyName\" autocomplete=\"organization\" placeholder=\"Your company name\"><\/label>\n<div class=\"cwjd-field\"><label for=\"cwjd-logo\">Logo <small>(optional, PNG, JPG, WebP or SVG)<\/small><\/label>\n<div class=\"cwjd-logorow\"><input type=\"file\" id=\"cwjd-logo\" accept=\"image\/png,image\/jpeg,image\/webp,image\/svg+xml\"><button type=\"button\" class=\"cwjd-btn cwjd-btn-small\" id=\"cwjd-logo-remove\" hidden>Remove logo<\/button><\/div><\/div>\n<label class=\"cwjd-field\">Tag text <small>Leave empty to hide it<\/small><input type=\"text\" data-field=\"badge\"><\/label>\n<div class=\"cwjd-field\"><span id=\"cwjd-color-label\">Brand color<\/span>\n<div class=\"cwjd-swatches\" role=\"group\" aria-labelledby=\"cwjd-color-label\">\n<button type=\"button\" class=\"cwjd-swatch\" data-color=\"#0f5e5a\" style=\"background:#0f5e5a\" aria-label=\"Teal\"><\/button>\n<button type=\"button\" class=\"cwjd-swatch\" data-color=\"#23408e\" style=\"background:#23408e\" aria-label=\"Blue\"><\/button>\n<button type=\"button\" class=\"cwjd-swatch\" data-color=\"#6d2b5e\" style=\"background:#6d2b5e\" aria-label=\"Plum\"><\/button>\n<button type=\"button\" class=\"cwjd-swatch\" data-color=\"#a23b12\" style=\"background:#a23b12\" aria-label=\"Rust\"><\/button>\n<button type=\"button\" class=\"cwjd-swatch\" data-color=\"#2f2f2f\" style=\"background:#2f2f2f\" aria-label=\"Charcoal\"><\/button>\n<label class=\"cwjd-colorwrap\">Custom <input type=\"color\" id=\"cwjd-color\" value=\"#0f5e5a\"><\/label>\n<\/div><\/div>\n<label class=\"cwjd-field\">Heading style<select data-field=\"font\"><option value=\"serif\">Classic serif<\/option><option value=\"sans\">Modern sans<\/option><\/select><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Job basics<\/div>\n<label class=\"cwjd-field\">Job title<input type=\"text\" data-field=\"jobTitle\"><\/label>\n<label class=\"cwjd-field\">Details line <small>e.g. job type, location, experience<\/small><input type=\"text\" data-field=\"details\"><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">About the company<\/div>\n<label class=\"cwjd-field\">Section heading<input type=\"text\" data-field=\"aboutHeading\"><\/label>\n<label class=\"cwjd-field\">Text <small>Leave empty to hide this section<\/small><textarea data-field=\"aboutText\"><\/textarea><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">About the role<\/div>\n<label class=\"cwjd-field\">Section heading<input type=\"text\" data-field=\"roleHeading\"><\/label>\n<label class=\"cwjd-field\">Text <small>Leave empty to hide this section<\/small><textarea data-field=\"roleText\"><\/textarea><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Responsibilities<\/div>\n<label class=\"cwjd-field\">Section heading<input type=\"text\" data-field=\"respHeading\"><\/label>\n<label class=\"cwjd-field\">One per line <small>Long lists split into two columns automatically<\/small><textarea class=\"cwjd-tall\" data-field=\"respList\"><\/textarea><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Qualifications<\/div>\n<label class=\"cwjd-field\">Section heading<input type=\"text\" data-field=\"qualHeading\"><\/label>\n<label class=\"cwjd-field\">One per line<textarea class=\"cwjd-tall\" data-field=\"qualList\"><\/textarea><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">Benefits<\/div>\n<label class=\"cwjd-field\">Section heading<input type=\"text\" data-field=\"benHeading\"><\/label>\n<label class=\"cwjd-field\">One per line <small>Leave empty to hide this section<\/small><textarea data-field=\"benList\"><\/textarea><\/label>\n<\/div>\n<div class=\"cwjd-group\">\n<div class=\"cwjd-gtitle\">How to apply<\/div>\n<label class=\"cwjd-field\">Heading<input type=\"text\" data-field=\"applyHeading\"><\/label>\n<label class=\"cwjd-field\">Short line<input type=\"text\" data-field=\"applyText\"><\/label>\n<label class=\"cwjd-field\">Email or link<input type=\"text\" data-field=\"applyContact\" placeholder=\"e.g. careers@yourcompany.com\"><\/label>\n<\/div>\n<div class=\"cwjd-formfoot\">\n<button type=\"button\" class=\"cwjd-btn cwjd-btn-small\" id=\"cwjd-reset\">Reset template<\/button>\n<button type=\"button\" class=\"cwjd-btn cwjd-btn-small\" id=\"cwjd-clear\">Clear all fields<\/button>\n<\/div>\n<\/div>\n<div class=\"cwjd-previewcol\" id=\"cwjd-previewcol\">\n<div class=\"cwjd-actions\">\n<label class=\"cwjd-fmt\"><span class=\"cwjd-sr\">Download format<\/span><select id=\"cwjd-format\" class=\"cwjd-select\"><option value=\"pdf\">PDF<\/option><option value=\"docx\">Word (.docx)<\/option><option value=\"png\">PNG image<\/option><\/select><\/label>\n<button type=\"button\" class=\"cwjd-btn cwjd-btn-primary\" id=\"cwjd-download\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 3v12\"\/><path d=\"m7 10 5 5 5-5\"\/><path d=\"M5 21h14\"\/><\/svg>Download<\/button>\n<button type=\"button\" class=\"cwjd-btn\" id=\"cwjd-zoom\" aria-expanded=\"false\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M15 3h6v6\"\/><path d=\"M9 21H3v-6\"\/><path d=\"M21 3l-7 7\"\/><path d=\"M3 21l7-7\"\/><\/svg><span id=\"cwjd-zoom-label\">Enlarge<\/span><\/button>\n<\/div>\n<a class=\"cwjd-cta\" id=\"cwjd-cta\" href=\"https:\/\/internshala.com\/hire-talent?utm_source=is_blog&amp;utm_medium=jd_builder\" target=\"_blank\" rel=\"noopener\"><span><span id=\"cwjd-cta-lead\">Hiring for this role?<\/span> <strong id=\"cwjd-cta-strong\">Post this job for free<\/strong><\/span><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M5 12h14\"\/><path d=\"m13 6 6 6-6 6\"\/><\/svg><\/a>\n<p class=\"cwjd-status\" id=\"cwjd-status\" role=\"status\" aria-live=\"polite\"><\/p>\n<div class=\"cwjd-stage\" id=\"cwjd-stage\">\n<div class=\"cwjd-scale\" id=\"cwjd-scale\" data-font=\"serif\">\n<div class=\"cwjd-sheet cw-classic\" data-design=\"classic\">\n<div class=\"cw-top\">\n<div class=\"cw-brandrow\">\n<div class=\"cw-brand\"><img class=\"cw-logo\" alt=\"\" hidden><div class=\"cw-company\" data-out=\"companyName\" data-ph=\"[Company name]\"><\/div><\/div>\n<div class=\"cw-badge\" data-out=\"badge\" data-hide-empty=\"badge\"><\/div>\n<\/div>\n<div class=\"cw-title\" data-out=\"jobTitle\" data-ph=\"[Job title]\"><\/div>\n<div class=\"cw-details\" data-out=\"details\" data-hide-empty=\"details\"><\/div>\n<\/div>\n<div class=\"cw-row\" data-pair=\"aboutText roleText\">\n<div class=\"cw-sec\" data-hide-empty=\"aboutText\"><div class=\"cw-h\" data-out=\"aboutHeading\"><\/div><div class=\"cw-p\" data-out=\"aboutText\"><\/div><\/div>\n<div class=\"cw-sec\" data-hide-empty=\"roleText\"><div class=\"cw-h\" data-out=\"roleHeading\"><\/div><div class=\"cw-p\" data-out=\"roleText\"><\/div><\/div>\n<\/div>\n<div class=\"cw-sec\" data-hide-empty=\"respList\"><div class=\"cw-h\" data-out=\"respHeading\"><\/div>\n<div class=\"cw-row\" data-two=\"respList\"><div class=\"cw-list\" data-list=\"respList\" data-half=\"a\"><\/div><div class=\"cw-list\" data-list=\"respList\" data-half=\"b\"><\/div><\/div>\n<\/div>\n<div class=\"cw-row cw-qb\" data-pair=\"qualList benList\">\n<div class=\"cw-sec\" data-hide-empty=\"qualList\"><div class=\"cw-h\" data-out=\"qualHeading\"><\/div><div class=\"cw-list\" data-list=\"qualList\"><\/div><\/div>\n<div class=\"cw-sec cw-card\" data-hide-empty=\"benList\"><div class=\"cw-h\" data-out=\"benHeading\"><\/div><div class=\"cw-list\" data-list=\"benList\"><\/div><\/div>\n<\/div>\n<div class=\"cw-foot\">\n<div class=\"cw-foot-l\"><div class=\"cw-foot-h\" data-out=\"applyHeading\"><\/div><div class=\"cw-foot-t\" data-out=\"applyText\"><\/div><\/div>\n<div class=\"cw-contact\" data-out=\"applyContact\" data-ph=\"[Your email or job link]\"><\/div>\n<\/div>\n<\/div>\n<div class=\"cwjd-sheet cw-modern\" data-design=\"modern\" hidden>\n<div class=\"m-head\">\n<div class=\"m-brandrow\">\n<div class=\"m-brand\"><img class=\"cw-logo\" alt=\"\" hidden><div class=\"m-company\" data-out=\"companyName\" data-ph=\"[Company name]\"><\/div><\/div>\n<div class=\"m-badge\" data-out=\"badge\" data-hide-empty=\"badge\"><\/div>\n<\/div>\n<div class=\"m-title\" data-out=\"jobTitle\" data-ph=\"[Job title]\"><\/div>\n<div class=\"m-details\" data-out=\"details\" data-hide-empty=\"details\"><\/div>\n<\/div>\n<div class=\"m-body\">\n<div class=\"m-main\">\n<div class=\"m-sec\" data-hide-empty=\"roleText\"><div class=\"m-h\" data-out=\"roleHeading\"><\/div><div class=\"cw-p\" data-out=\"roleText\"><\/div><\/div>\n<div class=\"m-sec\" data-hide-empty=\"respList\"><div class=\"m-h\" data-out=\"respHeading\"><\/div><div class=\"cw-list\" data-list=\"respList\"><\/div><\/div>\n<div class=\"m-sec\" data-hide-empty=\"qualList\"><div class=\"m-h\" data-out=\"qualHeading\"><\/div><div class=\"cw-list\" data-list=\"qualList\"><\/div><\/div>\n<\/div>\n<div class=\"m-side\">\n<div class=\"m-sec\" data-hide-empty=\"aboutText\"><div class=\"m-h\" data-out=\"aboutHeading\"><\/div><div class=\"cw-p\" data-out=\"aboutText\"><\/div><\/div>\n<div class=\"m-card\" data-hide-empty=\"benList\"><div class=\"m-h\" data-out=\"benHeading\"><\/div><div class=\"cw-list\" data-list=\"benList\"><\/div><\/div>\n<div class=\"m-apply\"><div class=\"m-apply-h\" data-out=\"applyHeading\"><\/div><div class=\"m-apply-t\" data-out=\"applyText\"><\/div><div class=\"m-contact\" data-out=\"applyContact\" data-ph=\"[Your email or job link]\"><\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cwjd-sheet cw-simple\" data-design=\"simple\" hidden>\n<div class=\"n-top\">\n<div class=\"n-brand\"><img class=\"cw-logo\" alt=\"\" hidden><div class=\"n-company\" data-out=\"companyName\" data-ph=\"[Company name]\"><\/div><div class=\"n-badge\" data-out=\"badge\" data-hide-empty=\"badge\"><\/div><\/div>\n<div class=\"n-title\" data-out=\"jobTitle\" data-ph=\"[Job title]\"><\/div>\n<div class=\"n-details\" data-out=\"details\" data-hide-empty=\"details\"><\/div>\n<\/div>\n<div class=\"n-sec\" data-hide-empty=\"aboutText\"><div class=\"n-h\" data-out=\"aboutHeading\"><\/div><div class=\"cw-p\" data-out=\"aboutText\"><\/div><\/div>\n<div class=\"n-sec\" data-hide-empty=\"roleText\"><div class=\"n-h\" data-out=\"roleHeading\"><\/div><div class=\"cw-p\" data-out=\"roleText\"><\/div><\/div>\n<div class=\"n-sec\" data-hide-empty=\"respList\"><div class=\"n-h\" data-out=\"respHeading\"><\/div><div class=\"cw-list\" data-list=\"respList\"><\/div><\/div>\n<div class=\"n-sec\" data-hide-empty=\"qualList\"><div class=\"n-h\" data-out=\"qualHeading\"><\/div><div class=\"cw-list\" data-list=\"qualList\"><\/div><\/div>\n<div class=\"n-sec\" data-hide-empty=\"benList\"><div class=\"n-h\" data-out=\"benHeading\"><\/div><div class=\"cw-list\" data-list=\"benList\"><\/div><\/div>\n<div class=\"n-apply\"><div class=\"n-apply-h\" data-out=\"applyHeading\"><\/div><div class=\"n-apply-row\"><div data-out=\"applyText\"><\/div><div class=\"n-contact\" data-out=\"applyContact\" data-ph=\"[Your email or job link]\"><\/div><\/div><\/div>\n<\/div>\n<div class=\"cwjd-sheet cw-sidebar\" data-design=\"sidebar\" hidden>\n<div class=\"s-side\">\n<div class=\"s-brand\"><img class=\"cw-logo\" alt=\"\" hidden><div class=\"s-company\" data-out=\"companyName\" data-ph=\"[Company name]\"><\/div><\/div>\n<div class=\"s-badge\" data-out=\"badge\" data-hide-empty=\"badge\"><\/div>\n<div class=\"s-sec\" data-hide-empty=\"aboutText\"><div class=\"s-h\" data-out=\"aboutHeading\"><\/div><div class=\"cw-p\" data-out=\"aboutText\"><\/div><\/div>\n<div class=\"s-sec\" data-hide-empty=\"benList\"><div class=\"s-h\" data-out=\"benHeading\"><\/div><div class=\"cw-list\" data-list=\"benList\"><\/div><\/div>\n<div class=\"s-apply\"><div class=\"s-apply-h\" data-out=\"applyHeading\"><\/div><div class=\"s-apply-t\" data-out=\"applyText\"><\/div><div class=\"s-contact\" data-out=\"applyContact\" data-ph=\"[Your email or job link]\"><\/div><\/div>\n<\/div>\n<div class=\"s-main\">\n<div class=\"s-headline\"><div class=\"s-title\" data-out=\"jobTitle\" data-ph=\"[Job title]\"><\/div><div class=\"s-details\" data-out=\"details\" data-hide-empty=\"details\"><\/div><\/div>\n<div class=\"s-msec\" data-hide-empty=\"roleText\"><div class=\"s-mh\" data-out=\"roleHeading\"><\/div><div class=\"cw-p\" data-out=\"roleText\"><\/div><\/div>\n<div class=\"s-msec\" data-hide-empty=\"respList\"><div class=\"s-mh\" data-out=\"respHeading\"><\/div><div class=\"cw-list\" data-list=\"respList\"><\/div><\/div>\n<div class=\"s-msec\" data-hide-empty=\"qualList\"><div class=\"s-mh\" data-out=\"qualHeading\"><\/div><div class=\"cw-list\" data-list=\"qualList\"><\/div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"cwjd-gate\" id=\"cwjd-gate\" hidden>\n<div class=\"cwjd-gate-box\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"cwjd-gate-title\">\n<button type=\"button\" class=\"cwjd-gate-x\" id=\"cwjd-gate-close\" aria-label=\"Close\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 6l12 12\"\/><path d=\"M18 6L6 18\"\/><\/svg><\/button>\n<div class=\"cwjd-gate-title\" id=\"cwjd-gate-title\">Sign up free to download your job description<\/div>\n<p class=\"cwjd-gate-sub\" id=\"cwjd-gate-sub\">Create your free Internshala employer account to download this JD, then post the job to reach candidates.<\/p>\n<div class=\"cwjd-gate-signup\" id=\"cwjd-gate-signup\">\n<button type=\"button\" class=\"cwjd-gate-btn cwjd-gate-main\" id=\"cwjd-gate-google\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"8\" r=\"4\"\/><path d=\"M4 21a8 8 0 0 1 16 0\"\/><\/svg>Sign up with Google<\/button>\n<button type=\"button\" class=\"cwjd-gate-btn\" id=\"cwjd-gate-email\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\"\/><path d=\"m3 7 9 6 9-6\"\/><\/svg>Sign up with Email<\/button>\n<\/div>\n<form class=\"cwjd-gate-form\" id=\"cwjd-gate-form\" novalidate hidden>\n<div class=\"cwjd-gate-row\">\n<label class=\"cwjd-gate-field\">First name<input type=\"text\" name=\"first_name\" autocomplete=\"given-name\" maxlength=\"60\" required><\/label>\n<label class=\"cwjd-gate-field\">Last name<input type=\"text\" name=\"last_name\" autocomplete=\"family-name\" maxlength=\"60\" required><\/label>\n<\/div>\n<label class=\"cwjd-gate-field\">Official email<input type=\"email\" name=\"email\" autocomplete=\"email\" placeholder=\"name@company.com\" maxlength=\"120\" required><\/label>\n<label class=\"cwjd-gate-field\">Mobile number<span class=\"cwjd-gate-tel\"><span class=\"cwjd-gate-cc\">+91<\/span><input type=\"tel\" name=\"mobile\" autocomplete=\"tel-national\" inputmode=\"numeric\" placeholder=\"10-digit mobile number\" maxlength=\"20\" required><\/span><\/label>\n<label class=\"cwjd-gate-field\">Company name<input type=\"text\" name=\"company\" autocomplete=\"organization\" maxlength=\"120\" required><\/label>\n<label class=\"cwjd-gate-hp\" aria-hidden=\"true\">Leave this empty<input type=\"text\" name=\"website\" tabindex=\"-1\" autocomplete=\"off\"><\/label>\n<p class=\"cwjd-gate-ferr\" id=\"cwjd-gate-ferr\" role=\"alert\"><\/p>\n<button type=\"submit\" class=\"cwjd-gate-btn cwjd-gate-main\" id=\"cwjd-gate-submit\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 3v12\"\/><path d=\"m7 10 5 5 5-5\"\/><path d=\"M5 21h14\"\/><\/svg>Download my JD<\/button>\n<\/form>\n<p class=\"cwjd-gate-login\"><span id=\"cwjd-gate-login-lead\">Already have an account?<\/span> <button type=\"button\" class=\"cwjd-gate-link\" id=\"cwjd-gate-login\">Log in<\/button><\/p>\n<p class=\"cwjd-gate-status\" id=\"cwjd-gate-status\" role=\"status\" aria-live=\"polite\"><\/p>\n<div class=\"cwjd-gate-done\" id=\"cwjd-gate-done\" hidden>\n<a class=\"cwjd-gate-open\" id=\"cwjd-gate-open\" href=\"https:\/\/internshala.com\/hire-talent\" target=\"_blank\" rel=\"noopener\" hidden>Open the sign-up page in a new tab<\/a>\n<button type=\"button\" class=\"cwjd-btn cwjd-btn-primary\" id=\"cwjd-gate-continue\">I&#8217;ve signed in, download my file<\/button>\n<\/div>\n<p class=\"cwjd-gate-terms\"><span id=\"cwjd-gate-terms-lead\">By signing up, you agree to our<\/span> <a href=\"https:\/\/internshala.com\/terms#employer\" target=\"_blank\" rel=\"noopener\">T&amp;C<\/a>.<\/p>\n<\/div>\n<\/div>\n<script>\n(function () {\n  \/* Find this script's own builder block, so the builder still works if a page has more than one copy. *\/\n  var me = document.currentScript, root = (me && me.closest) ? me.closest('.cwjd') : null;\n  if (!root || root.getAttribute('data-ready')) {\n    root = null;\n    var all = document.querySelectorAll('.cwjd');\n    for (var n = 0; all.length > n; n++) { if (!all[n].getAttribute('data-ready')) { root = all[n]; break; } }\n  }\n  if (!root) return;\n  root.setAttribute('data-ready', '1');\n  var boot = root.querySelector('.cwjd-boot');\n  function go() {\n    try {\n      start(root);\n      root.setAttribute('data-live', '1');\n      if (boot && boot.parentNode) boot.parentNode.removeChild(boot);\n    } catch (err) {\n      if (boot) { boot.textContent = \"Sorry, the job description builder couldn't start. Please refresh the page. (\" + (err && err.message ? err.message : err) + \")\"; boot.className = 'cwjd-boot cwjd-boot-err'; }\n      if (window.console && console.error) console.error('Job description builder:', err);\n    }\n  }\n  \/* Start once the whole post has loaded, so the builder can read sections that come after it in the article. *\/\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go); else go();\n  function start(root) {\n  var H2C = 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2canvas\/1.4.1\/html2canvas.min.js';\n  var JSPDF = 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js';\n  var DOCX_SRC = ['https:\/\/cdn.jsdelivr.net\/npm\/docx@8.5.0\/build\/index.umd.min.js', 'https:\/\/unpkg.com\/docx@8.5.0\/build\/index.umd.js'];\n  var DESIGNS = ['classic', 'modern', 'simple', 'sidebar'];\n  var PAPER = { classic: '#f6f4ef', modern: '#ffffff', simple: '#ffffff', sidebar: '#ffffff' };\n  \/* Note: this code deliberately uses no backslash or less-than characters. WordPress's text formatter treats a less-than sign as\n     the start of an HTML tag and rewrites the ampersands after it, which breaks the script. Write comparisons as b > a instead. *\/\n  var NL = String.fromCharCode(10);\n  \/* Company-level fields: the same for every role, and kept when someone switches roles. *\/\n  var COMMON = {\n    companyName: \"\",\n    badge: \"We're hiring\",\n    aboutHeading: \"About us\",\n    aboutText: \"[Company name] is a [industry] company that [what you do and who you serve]. [Add a line about your team, culture or mission.]\",\n    roleHeading: \"The role\",\n    respHeading: \"Key responsibilities\",\n    qualHeading: \"Qualifications & skills\",\n    benHeading: \"Benefits\",\n    benList: [\"Competitive salary\", \"Health insurance\", \"Paid time off\", \"Learning and growth opportunities\"].join(NL),\n    applyHeading: \"Think you're a good fit?\",\n    applyText: \"Send your resume and a cover letter to\",\n    applyContact: \"\",\n    accent: \"#0f5e5a\",\n    font: \"serif\"\n  };\n  \/* ---- Template from the blog post ----\n     The builder has no built-in job templates: everything role-specific is read from the post it is placed in.\n     Job title: the post's main heading, e.g. \"Python Developer Job Description: ...\" or \"Job Description for a Telecaller\".\n     Responsibilities, skills \/ qualifications, the role overview and benefits: the post's own sample job description\n     (the section under an H2 containing \"sample\", \"template\" or \"example\") first, then matching sections anywhere in the article.\n     To choose the exact blocks, add a CSS class in WordPress (block settings > Advanced > Additional CSS class):\n       jd-title, jd-summary, jd-responsibilities, jd-qualifications, jd-benefits.\n     Anything the post doesn't have is left as a [placeholder] for the employer to fill in. *\/\n  var ROLE_FIELDS = [\"jobTitle\", \"details\", \"roleText\", \"respList\", \"qualList\", \"benList\"];\n  var KEEP_ON_CLEAR = [\"aboutHeading\", \"roleHeading\", \"respHeading\", \"qualHeading\", \"benHeading\", \"applyHeading\", \"accent\", \"font\"];\n  var INTERN_BEN = [\"Stipend of [amount] per month\", \"Certificate of completion\", \"Letter of recommendation\", \"Hands-on learning and mentorship\"].join(NL);\n  function toSlug(s) { return String(s || \"\").toLowerCase().replace(\/&\/g, \" and \").replace(\/[^a-z0-9]+\/g, \"-\").replace(\/^-+|-+$\/g, \"\"); }\n  var TAB = String.fromCharCode(9);\n  function squash(t) { return String(t || \"\").split(NL).join(\" \").split(TAB).join(\" \").replace(\/ {2,}\/g, \" \").trim(); }\n  function outsideBuilder(el) { return !root.contains(el) && !el.closest(\"nav, aside, footer, .cwjd\"); }\n  function articleScope() {\n    var host = root.closest(\"article, .entry-content, .post-content, .single-content, main\");\n    return host || document.body;\n  }\n  \/* The job named by a heading shaped like \"X Job Description...\" or \"Job Description for a X...\", or \"\" for any other heading. *\/\n  function jobFromText(t) {\n    t = squash(t);\n    var low = t.toLowerCase(), at = low.indexOf(\"job description\");\n    if (at > 0) t = t.slice(0, at);\n    else if (at === 0 && \/^job description (for|of) \/i.test(t)) {\n      t = t.replace(\/^job description (for|of) \/i, \"\").split(\":\")[0].split(\" - \")[0].split(\" | \")[0].split(\"(\")[0];\n    } else return \"\";\n    t = t.replace(\/^(how to (write|create|draft|make) |what is |writing |sample |free |simple |best |great |good |effective |perfect |the |an? )+\/i, \"\");\n    t = t.replace(\/^[0-9]{4} \/, \"\").replace(\/[ :,|-]+$\/, \"\").replace(\/('s|\u2019s)$\/i, \"\").trim();\n    if (\/^(free |sample |simple |best )*(templates?|samples?|examples?|formats?|guides?)$\/i.test(t)) return \"\";\n    return t.length > 1 && 70 > t.length ? t : \"\";\n  }\n  function titleFromHeading() {\n    var tagged = document.querySelector(\".jd-title\");\n    if (tagged && !root.contains(tagged)) return squash(tagged.textContent);\n    var h1 = null, art = root.closest(\"article\"), all = [];\n    if (art) all = Array.prototype.slice.call(art.querySelectorAll(\"h1\"));\n    all = all.concat(Array.prototype.slice.call(document.querySelectorAll(\"h1.entry-title, .entry-title h1, h1\")));\n    for (var i = 0; all.length > i; i++) {\n      if (!outsideBuilder(all[i])) continue;\n      h1 = jobFromText(all[i].textContent);\n      if (h1) return h1;\n    }\n    return jobFromText(document.title.split(\" - \")[0].split(\" | \")[0]);\n  }\n  \/* Top-level bullet points of a list (sub-points are left out), skipping bullets that are only links, e.g. a contents list. *\/\n  function listItems(el) {\n    var out = [], list = el.tagName === \"UL\" || el.tagName === \"OL\" ? el : el.querySelector(\"ul, ol\");\n    if (list) {\n      Array.prototype.forEach.call(list.children, function (li) {\n        if (li.tagName !== \"LI\") return;\n        var copy = li.cloneNode(true), subs = copy.querySelectorAll(\"ul, ol\");\n        for (var k = 0; subs.length > k; k++) { if (subs[k].parentNode) subs[k].parentNode.removeChild(subs[k]); }\n        var txt = squash(copy.textContent), links = copy.querySelectorAll(\"a\"), linkText = \"\";\n        for (var j = 0; links.length > j; j++) linkText += links[j].textContent;\n        if (links.length && squash(linkText) === txt) return;\n        if (txt.length > 2) out.push(txt.length > 220 ? txt.slice(0, 217) + \"\u2026\" : txt);\n      });\n    } else {\n      String(el.innerText || el.textContent || \"\").split(NL).forEach(function (l) {\n        l = squash(l).replace(\/^(?:[\u2022\u00b7\u25aa\u25e6*-]|[0-9]+[.)])(?=[ ])\/, \"\").trim();\n        if (l.length > 2) out.push(l);\n      });\n    }\n    return out.slice(0, 12);\n  }\n  \/* The first usable bullet list (or table cell) that belongs to a heading matching the pattern. *\/\n  function findSection(scope, pattern, wantText, from, to) {\n    var heads = Array.prototype.slice.call(scope.querySelectorAll(\"h2, h3, h4, h5, h6, th, td, strong, b, p\"));\n    var bounds = Array.prototype.slice.call(scope.querySelectorAll(\"h2, h3, h4\"));\n    var lists = Array.prototype.slice.call(scope.querySelectorAll(\"ul, ol\"));\n    var paras = Array.prototype.slice.call(scope.querySelectorAll(\"p\"));\n    for (var i = 0; heads.length > i; i++) {\n      var h = heads[i];\n      if (!outsideBuilder(h)) continue;\n      if (from && from !== h && !(from.compareDocumentPosition(h) & 4)) continue;\n      if (to && !(h.compareDocumentPosition(to) & 4)) continue;\n      var label = squash(h.textContent);\n      if (!label || label.length > 70 || !pattern.test(label)) continue;\n      if (h.tagName === \"STRONG\" || h.tagName === \"B\" || h.tagName === \"P\") {\n        if (h.tagName !== \"P\" && squash(h.parentNode.textContent).length > label.length + 3) continue;\n        if (h.tagName === \"P\" && label.length > 40) continue;\n      }\n      var cell = h.closest(\"td, th\");\n      if (cell && cell.parentNode) {\n        var cells = cell.parentNode.children;\n        for (var c = 0; cells.length > c; c++) {\n          if (cells[c] === cell || cells[c].contains(h)) continue;\n          if (wantText) { var tx = squash(cells[c].textContent); if (tx.length > 20) return tx; }\n          else { var fromCell = listItems(cells[c]); if (fromCell.length >= 2) return fromCell; }\n        }\n      }\n      var next = null;\n      for (var b = 0; bounds.length > b; b++) {\n        if (bounds[b] !== h && !bounds[b].contains(h) && (h.compareDocumentPosition(bounds[b]) & 4)) { next = bounds[b]; break; }\n      }\n      var pool = wantText ? paras : lists;\n      for (var k = 0; pool.length > k; k++) {\n        var el = pool[k];\n        if (el === h || el.contains(h) || h.contains(el) || !outsideBuilder(el)) continue;\n        if (!(h.compareDocumentPosition(el) & 4)) continue;\n        if (next && !(el.compareDocumentPosition(next) & 4)) break;\n        if (wantText) { var pt = squash(el.textContent); if (pt.length > 40) return pt.length > 600 ? pt.slice(0, 597) + \"\u2026\" : pt; continue; }\n        if (el.parentNode && el.parentNode.closest && el.parentNode.closest(\"li\")) continue;\n        var items = listItems(el);\n        if (items.length >= 2) return items;\n      }\n      if (wantText) continue;\n      var tables = scope.querySelectorAll(\"table\");\n      for (var tb = 0; tables.length > tb; tb++) {\n        var tbl = tables[tb];\n        if (tbl.contains(h) || !outsideBuilder(tbl) || !(h.compareDocumentPosition(tbl) & 4)) continue;\n        if (next && !(tbl.compareDocumentPosition(next) & 4)) break;\n        var rows = toItems(textLines(tbl).filter(function (l) { return !(25 > l.length && \/:$\/.test(l)); }));\n        if (rows.length >= 3) return rows;\n        break;\n      }\n    }\n    return wantText ? \"\" : [];\n  }\n  \/* The visible lines of a block: a new line at each line break, paragraph, list item and table row. *\/\n  function textLines(el) {\n    var out = [], cur = \"\";\n    (function walk(n) {\n      if (n.nodeType === 3) { cur += n.nodeValue; return; }\n      if (n.nodeType !== 1 || n.tagName === \"SCRIPT\" || n.tagName === \"STYLE\") return;\n      if (n.tagName === \"BR\") { out.push(cur); cur = \"\"; return; }\n      var block = \/^(P|DIV|LI|TR|TD|TH|H[1-6]|UL|OL|TABLE|TBODY|FIGURE|SECTION|BLOCKQUOTE)$\/.test(n.tagName);\n      if (block) { out.push(cur); cur = \"\"; }\n      for (var c = n.firstChild; c; c = c.nextSibling) walk(c);\n      if (block) { out.push(cur); cur = \"\"; }\n    })(el);\n    out.push(cur);\n    return out.map(squash).filter(function (l) { return l.length > 0; });\n  }\n  \/* Cleans lines into bullet points: drops bullet characters and splits one long run-on line into sentences. *\/\n  function toItems(lines) {\n    var out = [];\n    lines.forEach(function (l) {\n      l = squash(l).replace(\/^(?:[\u2022\u00b7\u25aa\u25e6*\u2013-]|[0-9]+[.)])(?=[ ])\/, \"\").trim();\n      if (l.length > 2) out.push(l);\n    });\n    if (out.length === 1 && out[0].length > 150) {\n      out = out[0].replace(\/([a-z]{3})[.](?=[A-Z][a-z])\/g, \"$1.\" + NL).replace(\/([.;]) +(?=[A-Z0-9])\/g, \"$1\" + NL).split(NL).map(squash).filter(function (l) { return l.length > 2; });\n    }\n    return out.map(function (l) { return l.length > 220 ? l.slice(0, 217) + \"\u2026\" : l; }).slice(0, 12);\n  }\n  \/* Sample job descriptions written as bold labels (\"Key Responsibilities:\") followed by lines of text, often inside a\n     one-cell table, rather than as bullet lists. Returns the sections in order: [{ label, lines }]. *\/\n  function labelSections(blocks) {\n    var labels = [], secs = [], cur = null;\n    blocks.forEach(function (b) {\n      var bolds = b.querySelectorAll(\"strong, b, h3, h4, h5, h6\");\n      for (var i = 0; bolds.length > i; i++) { var lb = squash(bolds[i].textContent); if (lb.length > 1 && 60 >= lb.length) labels.push(lb); }\n    });\n    labels.sort(function (a, z) { return z.length - a.length; });\n    blocks.forEach(function (b) {\n      textLines(b).forEach(function (l) {\n        var low = l.toLowerCase(), hit = \"\";\n        for (var i = 0; labels.length > i; i++) {\n          var lb = labels[i];\n          if (low.indexOf(lb.toLowerCase()) === 0 && (l.length === lb.length || \/[:\u2013-]$\/.test(lb) || KNOWN_LABEL.test(lb))) { hit = lb; break; }\n        }\n        if (hit) {\n          cur = { label: hit, lines: [] }; secs.push(cur);\n          var rest = squash(l.slice(hit.length)).replace(\/^[:\u2013-]+\/, \"\").trim();\n          if (rest.length > 2) cur.lines.push(rest);\n        } else if (cur) {\n          if (\/^(send|email|apply|interested|to apply|share your)\/i.test(l)) cur = null; else cur.lines.push(l);\n        }\n      });\n    });\n    return secs;\n  }\n  var KNOWN_LABEL = \/responsibilit|duties|qualification|skills|requirements|eligibility|overview|summary|about the role|job description|benefits|perks\/i;\n  function fromLabels(secs, pattern, wantText) {\n    for (var i = 0; secs.length > i; i++) {\n      if (!pattern.test(secs[i].label)) continue;\n      if (wantText) { var tx = squash(secs[i].lines.join(\" \")); if (tx.length > 40) return tx.length > 600 ? tx.slice(0, 597) + \"\u2026\" : tx; }\n      else { var items = toItems(secs[i].lines); if (items.length >= 2) return items; }\n    }\n    return wantText ? \"\" : [];\n  }\n  function taggedItems(cls) {\n    var el = document.querySelector(\".\" + cls);\n    return el && !root.contains(el) ? listItems(el) : [];\n  }\n  var RESP_RE = \/responsibilit|duties|what you.ll do|key tasks|day-to-day\/i;\n  var QUAL_RE = \/qualification|skills|requirements|eligibility|who you are|what we.re looking for\/i;\n  var SUM_RE = \/job overview|job summary|role overview|about the role|position summary|role summary|job purpose\/i;\n  var BEN_RE = \/benefits|perks|what we offer|why join\/i;\n  \/* Reads the post. kind says how much was found: \"tagged\" (marked blocks), \"auto\" (lists found in the article),\n     \"title\" (only the job title) or \"none\" (nothing; the template is all placeholders). *\/\n  function readPost() {\n    var p = { title: titleFromHeading(), summary: \"\", resp: [], qual: [], ben: [], kind: \"none\" };\n    p.resp = taggedItems(\"jd-responsibilities\"); p.qual = taggedItems(\"jd-qualifications\"); p.ben = taggedItems(\"jd-benefits\");\n    var sumEl = document.querySelector(\".jd-summary\");\n    if (sumEl && !root.contains(sumEl)) p.summary = squash(sumEl.textContent);\n    if (p.resp.length || p.qual.length) p.kind = \"tagged\";\n    else {\n      var scope = articleScope(), sample = null, sampleEnd = null, h2s = Array.prototype.slice.call(scope.querySelectorAll(\"h2\"));\n      \/* The post's own sample job description: the section under an H2 with \"sample\" in it (or else \"template\" \/ \"example\"),\n         skipping the section the builder itself sits in. *\/\n      [\/sample\/i, \/template|example\/i].forEach(function (re) {\n        if (sample) return;\n        for (var i = 0; h2s.length > i; i++) {\n          var h = h2s[i], end = h2s[i + 1] || null;\n          if (!re.test(h.textContent) || !outsideBuilder(h)) continue;\n          var holdsBuilder = (h.compareDocumentPosition(root) & 4) && (!end || (root.compareDocumentPosition(end) & 4));\n          if (holdsBuilder) continue;\n          sample = h; sampleEnd = end; return;\n        }\n      });\n      \/* The sample is the best source; the rest of the article is the fallback.\n         The overview and benefits are only taken from the sample, since articles often have unrelated sections with those words. *\/\n      if (sample) {\n        p.resp = findSection(scope, RESP_RE, false, sample, sampleEnd);\n        p.qual = findSection(scope, QUAL_RE, false, sample, sampleEnd);\n        if (!p.summary) p.summary = findSection(scope, SUM_RE, true, sample, sampleEnd);\n        if (!p.ben.length) p.ben = findSection(scope, BEN_RE, false, sample, sampleEnd);\n        var blocks = [];\n        for (var n = sample.nextElementSibling; n && n !== sampleEnd; n = n.nextElementSibling) {\n          if (n !== root && !n.contains(root) && !root.contains(n)) blocks.push(n);\n        }\n        var secs = labelSections(blocks);\n        if (!p.resp.length) p.resp = fromLabels(secs, RESP_RE, false);\n        if (!p.qual.length) p.qual = fromLabels(secs, QUAL_RE, false);\n        if (!p.summary) p.summary = fromLabels(secs, SUM_RE, true) || fromLabels(secs, \/^job description:?$\/i, true);\n        if (!p.ben.length) p.ben = fromLabels(secs, BEN_RE, false);\n      }\n      if (!p.resp.length) p.resp = findSection(scope, RESP_RE, false);\n      if (!p.qual.length) p.qual = findSection(scope, QUAL_RE, false);\n      p.kind = p.resp.length >= 2 || p.qual.length >= 2 ? \"auto\" : (p.title ? \"title\" : \"none\");\n    }\n    return p;\n  }\n  var post = { title: \"\", summary: \"\", resp: [], qual: [], ben: [], kind: \"none\" };\n  if (String(root.getAttribute(\"data-role\") || \"auto\").trim() !== \"blank\") {\n    try { post = readPost(); } catch (e) { if (window.console && console.warn) console.warn(\"Job description builder: could not read the post.\", e); }\n  }\n  \/* \"an HR Intern\", \"an SEO Executive\", \"a UI\/UX Designer\", \"an Accountant\". *\/\n  function anA(name) {\n    if (\/^[A-Z]{2,}\/.test(name)) return \/^[AEFHILMNORSX]\/.test(name) ? \"an\" : \"a\";\n    return \/^[aeiou]\/i.test(name) ? \"an\" : \"a\";\n  }\n  function isIntern(t) { return \/(^| )interns?( |$)|internship\/i.test(t || \"\"); }\n  \/* The template fields built from what was read; gaps become placeholders. *\/\n  function postValues(p) {\n    var name = p.title, intern = isIntern(name);\n    return {\n      jobTitle: name || \"[Job title]\",\n      details: intern ? \"Internship \u00b7 [Location] \u00b7 [Duration]\" : \"Full-time \u00b7 [Location] \u00b7 [Experience]\",\n      roleText: p.summary || (\"We're looking for \" + (name ? anA(name) + \" \" + name : \"a [job title]\") + \" to [main purpose of the role]. [Add one or two lines about the team and what success looks like.]\"),\n      respList: (p.resp.length ? p.resp : [\"[Main responsibility]\", \"[Another key responsibility]\", \"[Another key responsibility]\"]).join(NL),\n      qualList: (p.qual.length ? p.qual : [\"[Degree or certification required]\", \"[Years of experience]\", \"[Key skill or tool]\"]).join(NL),\n      benList: p.ben.length >= 2 ? p.ben.join(NL) : (intern ? INTERN_BEN : COMMON.benList)\n    };\n  }\n  \/* Used in reports (utm_content, analytics and the sheet's fallback job role): the job read from the post, as a slug. *\/\n  var currentRole = toSlug(post.title) || \"custom\";\n  var state = {};\n  var logoData = '';\n  var $ = function (sel) { return root.querySelector(sel); };\n  var $$ = function (sel) { return Array.prototype.slice.call(root.querySelectorAll(sel)); };\n  var sheets = $$('.cwjd-sheet'), sheet = sheets[0], stage = $('#cwjd-stage'), scaler = $('#cwjd-scale');\n  var uid = 'j' + Math.random().toString(36).slice(2, 10);\n  sheets.forEach(function (sh, n) { sh.setAttribute('data-cwjd-uid', uid + n); });\n  var currentDesign = 'classic';\n  var statusEl = $('#cwjd-status');\n  var cta = $('#cwjd-cta'), downloaded = false;\n  function postSlug() {\n    var parts = window.location.pathname.split('\/').filter(Boolean);\n    return toSlug(parts[parts.length - 1] || '') || 'blog';\n  }\n  \/* Sends a usage event to Google Analytics 4 (gtag) or Google Tag Manager (dataLayer), whichever the site has. *\/\n  function track(name, extra) {\n    var p = { jd_role: currentRole, jd_source: post.kind, jd_design: currentDesign, jd_post: postSlug() }, k;\n    if (extra) { for (k in extra) p[k] = extra[k]; }\n    try {\n      if (typeof window.gtag === 'function') window.gtag('event', name, p);\n      else if (window.dataLayer && typeof window.dataLayer.push === 'function') { var d = { event: name }; for (k in p) d[k] = p[k]; window.dataLayer.push(d); }\n    } catch (e1) {}\n    try { root.dispatchEvent(new CustomEvent('cwjd:track', { bubbles: true, detail: { name: name, params: p } })); } catch (e2) {}\n  }\n  \/* The \"Post this job\" link: the address from data-cta-url plus tracking tags, so sign-ups can be traced to this tool and post. *\/\n  function tagUrl(base, medium) {\n    var hash = '', at = base.indexOf('#');\n    if (at > -1) { hash = base.slice(at); base = base.slice(0, at); }\n    var add = [];\n    if (base.indexOf('utm_source=') === -1) add.push('utm_source=is_blog');\n    if (base.indexOf('utm_medium=') === -1) add.push('utm_medium=' + medium);\n    if (base.indexOf('utm_campaign=') === -1) add.push('utm_campaign=' + encodeURIComponent(postSlug()));\n    if (base.indexOf('utm_content=') === -1) add.push('utm_content=' + encodeURIComponent(currentRole));\n    return base + (add.length ? (base.indexOf('?') > -1 ? '&' : '?') + add.join('&') : '') + hash;\n  }\n  function ctaUrl() { return tagUrl(String(root.getAttribute('data-cta-url') || '').trim() || 'https:\/\/internshala.com\/hire-talent', 'jd_builder'); }\n  function updateCta() { cta.href = ctaUrl(); }\n  \/* Keeps a copy of the finished job description in this browser, so the job-posting form on the same site can pre-fill from it. *\/\n  function saveDraft() {\n    try {\n      window.localStorage.setItem('is_jd_builder_draft', JSON.stringify({\n        v: 1, savedAt: new Date().toISOString(), source: window.location.href, role: currentRole, design: currentDesign,\n        company: state.companyName || '', title: state.jobTitle || '', details: state.details || '', about: state.aboutText || '', summary: state.roleText || '',\n        responsibilities: lines(state.respList), qualifications: lines(state.qualList), benefits: lines(state.benList), applyContact: state.applyContact || ''\n      }));\n    } catch (e) {}\n  }\n  cta.addEventListener('click', function () {\n    saveDraft();\n    track('jd_builder_cta_click', { jd_cta_state: downloaded ? 'after_download' : 'before_download' });\n  });\n  function copy(obj) { var o = {}; for (var k in obj) o[k] = obj[k]; return o; }\n  function lines(text) {\n    return String(text || '').split(NL).map(function (l) {\n      return l.trim().replace(\/^(?:[\u2022\u00b7\u25aa\u25e6]|[*-](?=[ ])|[0-9]+[.)](?=[ ]))\/, '').trim();\n    }).filter(Boolean);\n  }\n  function fillList(el, items) {\n    el.textContent = '';\n    items.forEach(function (item) {\n      var row = document.createElement('div'); row.className = 'cw-li';\n      var box = document.createElement('span'); box.className = 'cw-dotbox';\n      var dot = document.createElement('span'); dot.className = 'cw-dot'; box.appendChild(dot);\n      var txt = document.createElement('span'); txt.textContent = item;\n      row.appendChild(box); row.appendChild(txt); el.appendChild(row);\n    });\n  }\n  function hexToRgb(hex) {\n    var m = \/^#?([0-9a-f]{6})$\/i.exec(String(hex).trim());\n    if (!m) return null;\n    var n = parseInt(m[1], 16);\n    return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n  }\n  function lum(rgb) {\n    var c = rgb.map(function (v) { v \/= 255; return 0.03928 >= v ? v \/ 12.92 : Math.pow((v + 0.055) \/ 1.055, 2.4); });\n    return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];\n  }\n  function contrast(a, b) { var la = lum(a), lb = lum(b); return (Math.max(la, lb) + 0.05) \/ (Math.min(la, lb) + 0.05); }\n  function applyColor() {\n    var rgb = hexToRgb(state.accent) || hexToRgb('#0f5e5a');\n    var paper = [246, 244, 239];\n    scaler.style.setProperty('--cw-accent', state.accent);\n    scaler.style.setProperty('--cw-on', contrast(rgb, [255, 255, 255]) >= 4.5 ? '#ffffff' : '#1d1d1b');\n    scaler.style.setProperty('--cw-head', contrast(rgb, paper) >= 3 ? state.accent : '#1d1d1b');\n    root.style.setProperty('--ui-accent', contrast(rgb, [255, 255, 255]) >= 3 ? state.accent : '#1d1d1b');\n    $$('.cwjd-swatch').forEach(function (b) { b.setAttribute('aria-pressed', b.getAttribute('data-color').toLowerCase() === String(state.accent).toLowerCase() ? 'true' : 'false'); });\n    var picker = $('#cwjd-color'); if (picker.value.toLowerCase() !== String(state.accent).toLowerCase()) picker.value = state.accent;\n  }\n  function has(key) { return String(state[key] || '').trim() !== ''; }\n  function filled(key) { return \/List$\/.test(key) ? lines(state[key]).length > 0 : has(key); }\n  function render() {\n    $$('[data-out]').forEach(function (el) {\n      var key = el.getAttribute('data-out');\n      var val = String(state[key] || '').trim();\n      var ph = el.getAttribute('data-ph');\n      el.textContent = val || ph || '';\n      el.classList.toggle('cw-ph', !val && !!ph);\n    });\n    $$('[data-hide-empty]').forEach(function (el) { el.hidden = !filled(el.getAttribute('data-hide-empty')); });\n    $$('[data-list]').forEach(function (el) {\n      var items = lines(state[el.getAttribute('data-list')]), half = el.getAttribute('data-half');\n      if (!half) { fillList(el, items); return; }\n      var two = items.length > 5, cut = two ? Math.ceil(items.length \/ 2) : items.length;\n      if (half === 'a') fillList(el, items.slice(0, cut));\n      else { fillList(el, items.slice(cut)); el.hidden = !two; }\n    });\n    $$('[data-two]').forEach(function (el) { el.classList.toggle('cw-single', !(lines(state[el.getAttribute('data-two')]).length > 5)); });\n    $$('[data-pair]').forEach(function (el) {\n      var ks = el.getAttribute('data-pair').split(' '), a = filled(ks[0]), b = filled(ks[1]);\n      el.classList.toggle('cw-single', !(a && b));\n      el.hidden = !a && !b;\n    });\n    scaler.setAttribute('data-font', state.font === 'sans' ? 'sans' : 'serif');\n    $$('.cw-logo').forEach(function (img) {\n      if (logoData) { img.src = logoData; img.alt = (state.companyName || 'Company') + ' logo'; img.hidden = false; }\n      else { img.removeAttribute('src'); img.hidden = true; }\n    });\n    $('#cwjd-logo-remove').hidden = !logoData;\n    applyColor();\n    fit();\n  }\n  function fillForm() {\n    $$('[data-field]').forEach(function (el) { el.value = state[el.getAttribute('data-field')] || ''; });\n  }\n  function loadAny(list, test) {\n    var n = 0;\n    function next() { if (n >= list.length) return Promise.reject(new Error('lib')); return load(list[n++], test).catch(next); }\n    return next();\n  }\n  function load(src, test) {\n    if (test()) return Promise.resolve();\n    return new Promise(function (resolve, reject) {\n      var s = document.createElement('script');\n      s.src = src; s.async = true;\n      s.onload = function () { test() ? resolve() : reject(new Error('lib')); };\n      s.onerror = function () { s.parentNode && s.parentNode.removeChild(s); reject(new Error('net')); };\n      document.head.appendChild(s);\n    });\n  }\n  var app = root.querySelector('.cwjd-app'), col = $('#cwjd-previewcol'), form = root.querySelector('.cwjd-form');\n  var expanded = false, head = 0, mode = '', pinKey = '';\n  \/* Height of the bars that stay at the top of the window (admin bar, sticky site menu), measured as they sit once\n     stuck, so the preview can stay in view just below them. Measured on load, on resize and after scrolling stops,\n     never during scrolling, so scrolling stays smooth. *\/\n  function measureHead() {\n    if (!document.elementsFromPoint) return 0;\n    var off = 0, vw = window.innerWidth || 1200;\n    var x = Math.max(2, Math.round(root.getBoundingClientRect().left + 4));\n    for (var y = 2; 360 > y; y += 14) {\n      var stack = document.elementsFromPoint(x, y), el = null;\n      for (var i = 0; stack.length > i; i++) { if (!root.contains(stack[i])) { el = stack[i]; break; } }\n      while (el && el !== document.body && el !== document.documentElement) {\n        var cs = window.getComputedStyle(el);\n        if (cs.position === 'fixed' || cs.position === 'sticky') {\n          var r = el.getBoundingClientRect();\n          if (r.width > vw * 0.5 && 260 > r.height && r.height > 0) {\n            if (cs.position === 'fixed' && 200 > r.top && r.top > -5) off = Math.max(off, r.bottom);\n            if (cs.position === 'sticky') { var t = parseFloat(cs.top); if (!isNaN(t) && 200 > t) off = Math.max(off, t + r.height); }\n          }\n          break;\n        }\n        el = el.parentElement;\n      }\n    }\n    return Math.round(off);\n  }\n  \/* The browser's own sticky positioning is the smoothest, but a theme wrapper with overflow set blocks it. *\/\n  function stickyWorks() {\n    var el = root.parentElement;\n    while (el && el !== document.body && el !== document.documentElement) {\n      var cs = window.getComputedStyle(el), o = cs.overflowX + ' ' + cs.overflowY;\n      if (o.indexOf('hidden') > -1 || o.indexOf('auto') > -1 || o.indexOf('scroll') > -1) return false;\n      el = el.parentElement;\n    }\n    return true;\n  }\n  function applyHead() { root.style.setProperty('--cwjd-top', (head + 12) + 'px'); }\n  function fit() {\n    if (pinKey) clearPin();\n    var cs = window.getComputedStyle(col);\n    var width = (col.clientWidth - parseFloat(cs.paddingLeft || 0) - parseFloat(cs.paddingRight || 0)) || 1080;\n    var s = Math.min(1, width \/ 1080);\n    var h = sheet.offsetHeight;\n    if (!expanded && root.classList.contains('cwjd-wide')) {\n      var chrome = col.offsetHeight - stage.offsetHeight;\n      var room = (window.innerHeight || 900) - (head + 12) - chrome - 16;\n      s = Math.min(s, Math.max(0.22, room \/ h));\n    }\n    scaler.style.transform = 'scale(' + s + ')';\n    stage.style.width = Math.floor(1080 * s) + 'px';\n    stage.style.height = Math.ceil(h * s) + 'px';\n    pin();\n  }\n  \/* Backup for themes that block sticky: the preview switches between three states (in place, fixed to the window,\n     parked at the bottom of the builder). In the fixed state the browser itself holds it still, so scrolling stays smooth. *\/\n  function clearPin() { col.style.position = ''; col.style.top = ''; col.style.left = ''; col.style.width = ''; col.style.zIndex = ''; pinKey = ''; }\n  function pin() {\n    if (expanded || mode !== 'fixed' || !root.classList.contains('cwjd-wide')) { if (pinKey) clearPin(); return; }\n    var a = app.getBoundingClientRect(), f = form.getBoundingClientRect();\n    var line = head + 12, h = col.offsetHeight;\n    var gap = parseFloat(window.getComputedStyle(app).columnGap) || 24;\n    var left = Math.round(f.right + gap), width = Math.round(a.right - left);\n    var state = a.top >= line ? 'top' : (a.bottom - h >= line ? 'fixed' : 'bottom');\n    var key = state === 'top' ? '' : state + '|' + left + '|' + width + '|' + line + '|' + (state === 'bottom' ? Math.round(a.height - h) + '|' + Math.round(left - a.left) : '');\n    if (key === pinKey) return;\n    if (!key) { clearPin(); return; }\n    col.style.width = width + 'px';\n    col.style.zIndex = '5';\n    if (state === 'fixed') { col.style.position = 'fixed'; col.style.top = line + 'px'; col.style.left = left + 'px'; }\n    else { col.style.position = 'absolute'; col.style.top = Math.round(a.height - h) + 'px'; col.style.left = Math.round(left - a.left) + 'px'; }\n    pinKey = key;\n  }\n  var settleTimer = null;\n  function onScroll() {\n    if (mode === 'fixed') pin();\n    if (settleTimer) clearTimeout(settleTimer);\n    settleTimer = setTimeout(function () {\n      var h2 = measureHead();\n      if (Math.abs(h2 - head) > 4) { head = h2; applyHead(); fit(); }\n    }, 300);\n  }\n  var lastWidth = -1;\n  function layout() {\n    var w = root.clientWidth;\n    if (w !== lastWidth) {\n      lastWidth = w;\n      root.classList.toggle('cwjd-wide', w >= 680);\n      mode = stickyWorks() ? 'sticky' : 'fixed';\n      root.classList.toggle('cwjd-sticky', mode === 'sticky');\n      head = measureHead();\n      applyHead();\n    }\n    fit();\n  }\n  var zoomBtn = $('#cwjd-zoom'), zoomLabel = $('#cwjd-zoom-label'), savedOverflow = '';\n  function onKey(e) { if (e.key === 'Escape' || e.key === 'Esc') setExpanded(false); }\n  function setExpanded(on) {\n    if (on === expanded) return;\n    expanded = on;\n    root.classList.toggle('cwjd-expanded', on);\n    zoomBtn.setAttribute('aria-expanded', on ? 'true' : 'false');\n    zoomLabel.textContent = on ? 'Close preview' : 'Enlarge';\n    if (on) {\n      savedOverflow = document.documentElement.style.overflow;\n      document.documentElement.style.overflow = 'hidden';\n      document.addEventListener('keydown', onKey);\n      col.scrollTop = 0;\n    } else {\n      document.documentElement.style.overflow = savedOverflow;\n      document.removeEventListener('keydown', onKey);\n    }\n    fit();\n    zoomBtn.focus();\n  }\n  zoomBtn.addEventListener('click', function () { setExpanded(!expanded); });\n  stage.addEventListener('click', function () { if (!expanded) setExpanded(true); });\n  \/* The job title without [placeholders], e.g. \"\" while it still reads \"[Job title]\". *\/\n  function realTitle() {\n    var parts = String(state.jobTitle || '').split('['), out = parts[0];\n    for (var i = 1; parts.length > i; i++) { var at = parts[i].indexOf(']'); out += at > -1 ? parts[i].slice(at + 1) : parts[i]; }\n    return squash(out);\n  }\n  function slug() {\n    var s = (realTitle() + ' job description').trim();\n    return s.toLowerCase().replace(\/[^a-z0-9]+\/g, '-').replace(\/^-+|-+$\/g, '') || 'job-description';\n  }\n  function setStatus(msg, isErr) { statusEl.textContent = msg; statusEl.classList.toggle('cwjd-err', !!isErr); }\n  function capture() {\n    var fontsReady = (document.fonts && document.fonts.ready) ? document.fonts.ready : Promise.resolve();\n    var guard = null;\n    function unguard() { if (guard && guard.parentNode) guard.parentNode.removeChild(guard); guard = null; }\n    return load(H2C, function () { return !!window.html2canvas; }).then(function () { return fontsReady; }).then(function () {\n      \/* Themes often style every image tag (borders, display:block). html2canvas measures text with a hidden probe image,\n         so neutralize those styles on the probe while the file is being made, then remove this style again. *\/\n      guard = document.createElement('style');\n      guard.textContent = 'body>div[style*=\"visibility: hidden\"]>img,body>div[style*=\"visibility: hidden\"]>span{border:0 !important;display:inline !important;width:1px;height:1px;max-width:none !important;min-width:0 !important;box-shadow:none !important;float:none !important;position:static !important}body>div[style*=\"visibility: hidden\"]>span{width:auto;height:auto;line-height:inherit}';\n      document.head.appendChild(guard);\n      return window.html2canvas(sheet, {\n        scale: 2, backgroundColor: PAPER[currentDesign] || '#ffffff', useCORS: true, logging: false, windowWidth: 1400,\n        onclone: function (doc) {\n          var cs = doc.querySelector('[data-cwjd-uid=\"' + sheet.getAttribute('data-cwjd-uid') + '\"]');\n          var rt = cs && cs.closest ? cs.closest('.cwjd') : null;\n          if (!rt) return;\n          rt.classList.remove('cwjd-expanded');\n          var pc = rt.querySelector('.cwjd-previewcol');\n          if (pc) { pc.style.transform = 'none'; pc.style.position = 'static'; pc.style.width = 'auto'; }\n          var sc = rt.querySelector('.cwjd-scale'), st = rt.querySelector('.cwjd-stage');\n          if (sc) { sc.style.transform = 'none'; sc.style.position = 'static'; sc.style.left = '0'; }\n          if (st) { st.style.height = 'auto'; st.style.width = '1080px'; st.style.maxWidth = 'none'; st.style.overflow = 'visible'; }\n        }\n      });\n    }).then(function (c) { unguard(); return c; }, function (e) { unguard(); throw e; });\n  }\n  function saveBlob(blob, name) {\n    var url = URL.createObjectURL(blob);\n    var a = document.createElement('a');\n    a.href = url; a.download = name; a.style.display = 'none';\n    document.body.appendChild(a); a.click();\n    setTimeout(function () { URL.revokeObjectURL(url); a.parentNode && a.parentNode.removeChild(a); }, 1500);\n  }\n  var busy = false, edited = false;\n  var fmtSel = $('#cwjd-format'), dlBtn = $('#cwjd-download');\n  function run(fmt, work) {\n    if (busy) return;\n    busy = true;\n    dlBtn.disabled = true; fmtSel.disabled = true;\n    setStatus('Preparing your file\u2026');\n    work().then(function () {\n      setStatus('Done. Check your downloads folder.');\n      track('jd_builder_download', { jd_format: fmt });\n      if (!downloaded) {\n        downloaded = true;\n        cta.classList.add('cwjd-cta-hot');\n        $('#cwjd-cta-lead').textContent = 'Your JD is ready.';\n        $('#cwjd-cta-strong').textContent = 'Post this job on Internshala for free';\n        fit();\n      }\n    }).catch(function (err) {\n      if (window.console && console.error) console.error('Job description builder:', err);\n      setStatus(\"Sorry, the download couldn't be prepared. Please check your connection and try again.\", true);\n    }).then(function () {\n      busy = false;\n      dlBtn.disabled = false; fmtSel.disabled = false;\n    });\n  }\n  function makePng() {\n    return capture().then(function (canvas) {\n      return new Promise(function (resolve, reject) {\n        if (canvas.toBlob) canvas.toBlob(function (blob) { blob ? (saveBlob(blob, slug() + '.png'), resolve()) : reject(new Error('blob')); }, 'image\/png');\n        else { var a = document.createElement('a'); a.href = canvas.toDataURL('image\/png'); a.download = slug() + '.png'; a.click(); resolve(); }\n      });\n    });\n  }\n  function makePdf() {\n    return load(JSPDF, function () { return !!(window.jspdf && window.jspdf.jsPDF); }).then(capture).then(function (canvas) {\n      var w = 595.28, h = w * canvas.height \/ canvas.width;\n      var pdf = new window.jspdf.jsPDF({ orientation: 'portrait', unit: 'pt', format: [w, h], compress: true });\n      pdf.addImage(canvas.toDataURL('image\/jpeg', 0.95), 'JPEG', 0, 0, w, h);\n      pdf.save(slug() + '.pdf');\n    });\n  }\n  \/* Word needs PNG or JPG pictures, so any logo (including SVG and WebP) is redrawn as a PNG first. *\/\n  function logoPng() {\n    if (!logoData) return Promise.resolve(null);\n    return new Promise(function (resolve) {\n      var im = new Image();\n      im.onload = function () {\n        try {\n          var w = im.naturalWidth || 240, h = im.naturalHeight || 80, k = Math.min(1, 640 \/ w, 320 \/ h);\n          var c = document.createElement('canvas');\n          c.width = Math.max(1, Math.round(w * k)); c.height = Math.max(1, Math.round(h * k));\n          c.getContext('2d').drawImage(im, 0, 0, c.width, c.height);\n          c.toBlob(function (b) {\n            if (!b) { resolve(null); return; }\n            b.arrayBuffer().then(function (buf) { resolve({ data: new Uint8Array(buf), w: c.width, h: c.height }); }, function () { resolve(null); });\n          }, 'image\/png');\n        } catch (e) { resolve(null); }\n      };\n      im.onerror = function () { resolve(null); };\n      im.src = logoData;\n    });\n  }\n  \/* Builds an editable Word document from the same content: headings in the brand color, real bullet lists. *\/\n  function makeDocx() {\n    return loadAny(DOCX_SRC, function () { return !!(window.docx && window.docx.Document && window.docx.Packer); }).then(logoPng).then(function (logo) {\n      var D = window.docx;\n      var rgb = hexToRgb(state.accent) || [15, 94, 90];\n      var accent = String(state.accent || '').replace('#', '').toUpperCase();\n      if (accent.length !== 6) accent = '0F5E5A';\n      var headCol = contrast(rgb, [255, 255, 255]) >= 3 ? accent : '1D1D1B';\n      var display = state.font === 'sans' ? 'Calibri' : 'Georgia';\n      var kids = [];\n      function val(key, fallback) { return String(state[key] || '').trim() || fallback || ''; }\n      function tx(text, o) {\n        o = o || {};\n        return new D.TextRun({ text: text, bold: !!o.bold, size: o.size || 22, color: o.color || '1D1D1B', font: o.font || 'Calibri', allCaps: !!o.caps, characterSpacing: o.track || 0 });\n      }\n      function para(runs, o) {\n        o = o || {};\n        var p = { children: runs, spacing: { before: o.before || 0, after: o.after == null ? 120 : o.after } };\n        if (!o.plain) { p.spacing.line = 288; p.spacing.lineRule = D.LineRuleType.AUTO; }\n        if (o.bullet) p.bullet = { level: 0 };\n        if (o.border) p.border = o.border;\n        if (o.keepNext) p.keepNext = true;\n        return new D.Paragraph(p);\n      }\n      function heading(key) { var t = val(key); if (t) kids.push(para([tx(t, { bold: true, size: 28, color: headCol, font: display })], { before: 280, after: 100, keepNext: true, plain: true })); }\n      function block(key) { val(key).split(NL).forEach(function (l) { if (l.trim()) kids.push(para([tx(l.trim())])); }); }\n      function bullets(key) { lines(state[key]).forEach(function (l) { kids.push(para([tx(l)], { bullet: true, after: 40 })); }); }\n      if (logo) {\n        var k = Math.min(1, 170 \/ logo.w, 52 \/ logo.h);\n        kids.push(para([new D.ImageRun({ data: logo.data, transformation: { width: Math.max(1, Math.round(logo.w * k)), height: Math.max(1, Math.round(logo.h * k)) } })], { after: 160, plain: true }));\n      }\n      var top = [tx(val('companyName', '[Company name]'), { bold: true, size: 20, color: headCol, caps: true, track: 40 })];\n      if (val('badge')) top.push(tx('   |   ' + val('badge'), { size: 20, color: '5C5A54', caps: true, track: 40 }));\n      kids.push(para(top, { after: 200 }));\n      kids.push(para([tx(val('jobTitle', '[Job title]'), { bold: true, size: 60, font: display })], { after: 100, plain: true }));\n      kids.push(para(val('details') ? [tx(val('details'), { size: 24, color: '4A4944' })] : [], { after: 200, border: { bottom: { color: accent, space: 12, style: D.BorderStyle.SINGLE, size: 12 } } }));\n      if (val('aboutText')) { heading('aboutHeading'); block('aboutText'); }\n      if (val('roleText')) { heading('roleHeading'); block('roleText'); }\n      if (lines(state.respList).length) { heading('respHeading'); bullets('respList'); }\n      if (lines(state.qualList).length) { heading('qualHeading'); bullets('qualList'); }\n      if (lines(state.benList).length) { heading('benHeading'); bullets('benList'); }\n      heading('applyHeading');\n      var apply = [];\n      if (val('applyText')) apply.push(tx(val('applyText') + ' '));\n      apply.push(tx(val('applyContact', '[Your email or job link]'), { bold: true, color: headCol }));\n      kids.push(para(apply));\n      var doc = new D.Document({\n        creator: val('companyName', 'Job description builder'),\n        title: val('jobTitle', 'Job') + ' job description',\n        styles: { default: { document: { run: { font: 'Calibri', size: 22 } } } },\n        sections: [{ properties: { page: { margin: { top: 900, right: 1150, bottom: 900, left: 1150 } } }, children: kids }]\n      });\n      return D.Packer.toBlob(doc).then(function (blob) { saveBlob(blob, slug() + '.docx'); });\n    });\n  }\n  \/* ---- Sign-up step before download ----\n     Clicking Download first asks the site whether the visitor is already signed in as an employer (it opens\n     data-login-check, default \/employer\/dashboard, in the background: signed-out visitors get the login form there).\n     Signed-in employers download straight away. Everyone else sees a box with the site's own sign-up options, which open\n     in a small window; the download starts as soon as the site confirms the sign-in, and the window is closed.\n     A browser that has completed this once is remembered, so returning employers download straight away. *\/\n  var gate = $('#cwjd-gate'), gateStatusEl = $('#cwjd-gate-status'), gateDone = $('#cwjd-gate-done'), gateLink = $('#cwjd-gate-open');\n  var gateWin = null, gateTimer = null, gateFmt = 'pdf', gateMethod = '', gateShown = false, gateOverflow = '';\n  var gateHref = '', lastProbe = 0, probing = null, confirmClicks = 0;\n  var GATE_KEY = 'is_jd_builder_gate', GATE_DAYS = 30;\n  function attr(name, fallback) { return String(root.getAttribute(name) || '').trim() || fallback; }\n  function gateParam() { var q = \/[?&]jdgate=([^&#]+)\/.exec(window.location.search); return q ? q[1] : ''; }\n  \/* 'signup' (create an Internshala account), 'form' (fill in details that go to a Google Sheet) or 'off'. *\/\n  function gateMode() {\n    var v = gateParam();\n    if (v !== 'on' && v !== 'signup' && v !== 'form') v = attr('data-gate', 'off');\n    if (v === 'on') v = 'signup';\n    return v === 'signup' || v === 'form' ? v : 'off';\n  }\n  function gateOn() { return gateMode() !== 'off'; }\n  function cookieSaysIn() {\n    var n = attr('data-login-cookie', '');\n    return !!n && ('; ' + document.cookie + ';').indexOf('; ' + n + '=') > -1;\n  }\n  function gatePassed() {\n    try {\n      var t = parseInt(window.localStorage.getItem(GATE_KEY) || '0', 10), age = Date.now() - t;\n      if (t > 0 && age >= 0 && GATE_DAYS * 86400000 > age) return true;\n    } catch (e) {}\n    return cookieSaysIn();\n  }\n  function gateRemember() { try { window.localStorage.setItem(GATE_KEY, String(Date.now())); } catch (e) {} }\n  \/* Asks the site whether this browser is signed in as an employer. Resolves true (signed in), false (not signed in)\n     or null (could not tell, e.g. offline). Signed-out visitors get a login form (a password box or a Google login link). *\/\n  function checkSignedIn() {\n    if (probing) return probing;\n    if (cookieSaysIn()) return Promise.resolve(true);\n    if (!window.fetch) return Promise.resolve(null);\n    lastProbe = Date.now();\n    probing = window.fetch(attr('data-login-check', '\/employer\/dashboard'), { credentials: 'same-origin', cache: 'no-store' }).then(function (res) {\n      if (!res.ok) return null;\n      var path = '';\n      try { path = new URL(res.url, window.location.href).pathname; } catch (e) {}\n      return res.text().then(function (html) {\n        var loginForm = html.indexOf('type=\"password\"') > -1 || html.indexOf(\"type='password'\") > -1 || html.indexOf('type=password') > -1 || html.indexOf('login\/get_google') > -1;\n        return !loginForm && path.indexOf('\/employer') === 0;\n      });\n    }).then(function (v) { probing = null; return v; }, function () { probing = null; return null; });\n    return probing;\n  }\n  function gateStatus(msg) { gateStatusEl.textContent = msg || ''; }\n  function gateFallback(msg, withLink) {\n    if (msg) gateStatus(msg);\n    gateLink.hidden = !withLink;\n    if (attr('data-gate-fallback', 'on') !== 'off' || withLink) gateDone.hidden = false;\n    $('#cwjd-gate-continue').hidden = attr('data-gate-fallback', 'on') === 'off';\n  }\n  function gateStopWatch() { if (gateTimer) { clearInterval(gateTimer); gateTimer = null; } }\n  \/* Re-checks the sign-in now (soon=true) or at most every 8 seconds; finishes the download when it is confirmed. *\/\n  function gateVerify(soon) {\n    if (!gateShown) return Promise.resolve(false);\n    if (!soon && 8000 > Date.now() - lastProbe) return Promise.resolve(false);\n    return checkSignedIn().then(function (v) {\n      if (v === true && gateShown) gateSuccess('verified');\n      return v;\n    });\n  }\n  \/* Watches the sign-up window. Each time it moves to a new page on this site (for example after the Google step or after\n     the form is sent), the sign-in is checked. Pages on other sites, such as Google's, cannot be read and are skipped. *\/\n  function gateTick() {\n    if (!gateShown) return;\n    if (cookieSaysIn()) { gateSuccess('cookie'); return; }\n    if (!gateWin) { gateVerify(false); return; }\n    var closed = true;\n    try { closed = !!gateWin.closed; } catch (e) { closed = true; }\n    if (closed) {\n      gateWin = null; gateStopWatch();\n      gateStatus('Checking your sign-in\u2026');\n      gateVerify(true).then(function (v) { if (gateShown && v !== true) gateFallback('The sign-up window was closed before sign-in finished.', false); });\n      return;\n    }\n    var href = '';\n    try { var loc = gateWin.location; if (loc && loc.origin === window.location.origin) href = String(loc.href); } catch (e2) {}\n    if (href && href !== gateHref) { gateHref = href; setTimeout(function () { gateVerify(true); }, 400); return; }\n    gateVerify(false);\n  }\n  function gateKeys(e) {\n    if (e.key === 'Escape' || e.key === 'Esc') { closeGate(true); return; }\n    if (e.key !== 'Tab') return;\n    var items = Array.prototype.slice.call(gate.querySelectorAll('button, a[href], input:not([tabindex])')).filter(function (el) { return el.offsetParent !== null; });\n    if (!items.length) return;\n    var first = items[0], last = items[items.length - 1];\n    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n  }\n  function onGateFocus() {\n    if (!gateShown || !gateMethod) return;\n    gateVerify(true).then(function (v) { if (gateShown && v !== true && !gateWin) gateFallback('', !gateLink.hidden); });\n  }\n  function onGateMessage(e) {\n    if (!gateShown || e.origin !== window.location.origin) return;\n    if (e.data && e.data.cwjd === 'signed-in') gateSuccess('message');\n  }\n  function openGate(fmt) {\n    gateFmt = fmt; gateMethod = ''; gateShown = true; gateHref = ''; confirmClicks = 0;\n    gateStatus(''); gateDone.hidden = true; gateLink.hidden = true;\n    gate.hidden = false;\n    gateOverflow = document.documentElement.style.overflow;\n    document.documentElement.style.overflow = 'hidden';\n    document.addEventListener('keydown', gateKeys);\n    window.addEventListener('focus', onGateFocus);\n    window.addEventListener('message', onGateMessage);\n    var formMode = gateMode() === 'form';\n    $('#cwjd-gate-signup').hidden = formMode;\n    gateForm.hidden = !formMode;\n    gateFormErr('');\n    $('#cwjd-gate-title').textContent = formMode ? 'Get your job description' : 'Sign up free to download your job description';\n    $('#cwjd-gate-sub').textContent = formMode ? 'Fill in a few details and your download starts right away.' : 'Create your free Internshala employer account to download this JD, then post the job to reach candidates.';\n    $('#cwjd-gate-login-lead').textContent = formMode ? 'Already registered on Internshala?' : 'Already have an account?';\n    $('#cwjd-gate-terms-lead').textContent = formMode ? 'By submitting, you agree to be contacted by Internshala about hiring and to our' : 'By signing up, you agree to our';\n    if (formMode) {\n      if (!gateForm.elements.company.value.trim()) gateForm.elements.company.value = String(state.companyName || '').trim();\n      gateForm.elements.first_name.focus();\n    } else { $('#cwjd-gate-google').focus(); }\n    track('jd_builder_gate_open', { jd_format: fmt, jd_gate: formMode ? 'form' : 'signup' });\n  }\n  function closeGate(byUser) {\n    if (!gateShown) return;\n    gateShown = false;\n    gateStopWatch();\n    gate.hidden = true;\n    document.documentElement.style.overflow = gateOverflow;\n    document.removeEventListener('keydown', gateKeys);\n    window.removeEventListener('focus', onGateFocus);\n    window.removeEventListener('message', onGateMessage);\n    if (byUser) { track('jd_builder_gate_close', { jd_signup_started: gateMethod || 'no' }); dlBtn.focus(); }\n  }\n  function gateSuccess(how) {\n    if (!gateShown) return;\n    var w = gateWin; gateWin = null;\n    gateRemember();\n    try { if (w && !w.closed) w.close(); } catch (e) {}\n    closeGate(false);\n    track('jd_builder_signup_complete', { jd_method: gateMethod || 'unknown', jd_detect: how, jd_format: gateFmt });\n    startDownload(gateFmt);\n  }\n  function gateUrl(method) {\n    var base = method === 'google' ? attr('data-google-url', 'https:\/\/internshala.com\/login\/get_google\/employer\/employer%2Fdashboard')\n      : (method === 'login' ? attr('data-login-url', 'https:\/\/internshala.com\/login\/employer') : attr('data-cta-url', 'https:\/\/internshala.com\/hire-talent'));\n    return tagUrl(base, 'jd_builder_download');\n  }\n  function gateGo(method) {\n    var url = gateUrl(method);\n    gateMethod = method; gateHref = '';\n    saveDraft();\n    track('jd_builder_signup_click', { jd_method: method });\n    var wpx = 520, hpx = 720, sw = (window.screen && window.screen.width) || 1280, sh = (window.screen && window.screen.height) || 800;\n    var feat = 'width=' + wpx + ',height=' + hpx + ',left=' + Math.max(0, Math.round((sw - wpx) \/ 2)) + ',top=' + Math.max(0, Math.round((sh - hpx) \/ 2));\n    gateStopWatch();\n    try { gateWin = window.open(url, 'is_jd_signup', feat); } catch (e) { gateWin = null; }\n    if (!gateWin) {\n      gateLink.href = url;\n      gateFallback('Your browser blocked the sign-up window. Open it in a new tab, sign in, then come back here.', true);\n      gateTimer = setInterval(gateTick, 1000);\n      return;\n    }\n    try { gateWin.focus(); } catch (e3) {}\n    gateDone.hidden = true;\n    gateStatus('Finish signing in in the window that just opened. Your download will start here automatically.');\n    gateTimer = setInterval(gateTick, 600);\n  }\n  $('#cwjd-gate-google').addEventListener('click', function () { gateGo('google'); });\n  $('#cwjd-gate-email').addEventListener('click', function () { gateGo('email'); });\n  $('#cwjd-gate-login').addEventListener('click', function () { gateGo('login'); });\n  $('#cwjd-gate-close').addEventListener('click', function () { closeGate(true); });\n  \/* \"I've signed in\": checks with the site first. If the site can't be reached, or the visitor clicks a second time,\n     the download goes ahead, so nobody is ever left stuck. *\/\n  $('#cwjd-gate-continue').addEventListener('click', function () {\n    var btn = this;\n    confirmClicks++;\n    btn.disabled = true;\n    gateStatus('Checking your sign-in\u2026');\n    checkSignedIn().then(function (v) {\n      btn.disabled = false;\n      if (v === true) gateSuccess('verified');\n      else if (v === null || confirmClicks >= 2) gateSuccess('unverified');\n      else gateStatus(\"We can't see a sign-in yet. Finish signing in, then click the button again.\");\n    });\n  });\n  gateLink.addEventListener('click', function () { gateMethod = gateMethod || 'email'; });\n  gate.addEventListener('mousedown', function (e) { if (e.target === gate) closeGate(true); });\n  if (gateParam() === 'reset') { try { window.localStorage.removeItem(GATE_KEY); } catch (e) {} }\n  \/* ---- Details form (data-gate=\"form\") ----\n     Sends the details to the address in data-lead-url (a Google Apps Script web app that adds a row to a Google Sheet),\n     then starts the download. The download never waits more than 4 seconds for the sheet, and still happens if it fails. *\/\n  var gateForm = $('#cwjd-gate-form'), gateFormErrEl = $('#cwjd-gate-ferr');\n  function gateFormErr(msg, field) {\n    gateFormErrEl.textContent = msg || '';\n    Array.prototype.forEach.call(gateForm.querySelectorAll('input'), function (el) { el.removeAttribute('aria-invalid'); });\n    if (field) { field.setAttribute('aria-invalid', 'true'); field.focus(); }\n  }\n  function leadValues() {\n    var f = gateForm.elements;\n    return {\n      first_name: f.first_name.value.trim(), last_name: f.last_name.value.trim(), email: f.email.value.trim(),\n      mobile: f.mobile.value.replace(\/[^0-9]\/g, ''), company: f.company.value.trim(), website: f.website.value\n    };\n  }\n  function leadProblem(v) {\n    var f = gateForm.elements;\n    if (!v.first_name) return ['Please enter your first name.', f.first_name];\n    if (!v.last_name) return ['Please enter your last name.', f.last_name];\n    if (!\/^[^ @]+@[^ @]+[.][^ @]+$\/.test(v.email)) return ['Please enter a valid email address.', f.email];\n    if (v.mobile.length === 12 && v.mobile.indexOf('91') === 0) v.mobile = v.mobile.slice(2);\n    if (v.mobile.length === 11 && v.mobile.charAt(0) === '0') v.mobile = v.mobile.slice(1);\n    if (v.mobile.length !== 10) return ['Please enter a 10-digit mobile number.', f.mobile];\n    if (!v.company) return ['Please enter your company name.', f.company];\n    return null;\n  }\n  function sendLead(v) {\n    var url = attr('data-lead-url', '');\n    if (!url || !window.fetch || !window.URLSearchParams) {\n      if (!url && window.console && console.warn) console.warn('Job description builder: data-lead-url is not set, so form details are not being saved.');\n      return Promise.resolve('no');\n    }\n    var body = new URLSearchParams();\n    body.append('first_name', v.first_name); body.append('last_name', v.last_name); body.append('email', v.email);\n    body.append('mobile', '+91 ' + v.mobile); body.append('company', v.company); body.append('website', v.website);\n    body.append('job_role', realTitle() || post.title || '(not filled in)'); body.append('template', currentDesign); body.append('format', gateFmt);\n    body.append('blog_post', postSlug()); body.append('page_url', window.location.origin + window.location.pathname);\n    var sent = window.fetch(url, { method: 'POST', mode: 'no-cors', body: body, keepalive: true }).then(function () { return 'yes'; }, function () { return 'no'; });\n    var slow = new Promise(function (resolve) { setTimeout(function () { resolve('slow'); }, 4000); });\n    return Promise.race([sent, slow]);\n  }\n  gateForm.addEventListener('submit', function (e) {\n    e.preventDefault();\n    var v = leadValues(), problem = leadProblem(v);\n    if (problem) { gateFormErr(problem[0], problem[1]); return; }\n    gateFormErr('');\n    var btn = $('#cwjd-gate-submit');\n    btn.disabled = true;\n    gateStatus('Preparing your download\u2026');\n    if (v.website) { gateMethod = 'form'; gateSuccess('form'); btn.disabled = false; return; }\n    sendLead(v).then(function (result) {\n      btn.disabled = false;\n      gateStatus('');\n      track('jd_builder_lead_submit', { jd_lead_saved: result });\n      gateMethod = 'form';\n      gateSuccess('form');\n    });\n  });\n  function startDownload(f) { run(f, f === 'pdf' ? makePdf : (f === 'docx' ? makeDocx : makePng)); }\n  dlBtn.addEventListener('click', function () {\n    var f = fmtSel.value;\n    if (!gateOn() || gatePassed()) { startDownload(f); return; }\n    if (busy) return;\n    dlBtn.disabled = true;\n    setStatus('Checking your sign-in\u2026');\n    checkSignedIn().then(function (v) {\n      dlBtn.disabled = false;\n      setStatus('');\n      if (v === true) { gateRemember(); track('jd_builder_already_signed_in', { jd_format: f }); startDownload(f); }\n      else openGate(f);\n    });\n  });\n  $$('[data-field]').forEach(function (el) {\n    el.addEventListener('input', function () {\n      state[el.getAttribute('data-field')] = el.value; render();\n      if (!edited) { edited = true; track('jd_builder_edit', { jd_field: el.getAttribute('data-field') }); }\n    });\n    el.addEventListener('change', function () { state[el.getAttribute('data-field')] = el.value; render(); });\n  });\n  $$('.cwjd-swatch').forEach(function (b) {\n    b.addEventListener('click', function () { state.accent = b.getAttribute('data-color'); render(); });\n  });\n  $('#cwjd-color').addEventListener('input', function () { state.accent = this.value; render(); });\n  $('#cwjd-logo').addEventListener('change', function () {\n    var file = this.files && this.files[0];\n    if (!file) return;\n    if (['image\/png', 'image\/jpeg', 'image\/webp', 'image\/svg+xml'].indexOf(file.type) === -1) { setStatus('Please choose a PNG, JPG, WebP or SVG image.', true); this.value = ''; return; }\n    if (file.size > 3 * 1024 * 1024) { setStatus('That logo is over 3 MB. Please use a smaller file.', true); this.value = ''; return; }\n    var reader = new FileReader();\n    reader.onload = function () { logoData = String(reader.result); setStatus(''); render(); };\n    reader.readAsDataURL(file);\n  });\n  $('#cwjd-logo-remove').addEventListener('click', function () { logoData = ''; $('#cwjd-logo').value = ''; render(); });\n  var designSel = $('#cwjd-design');\n  function pickDesign() {\n    var q = \/[?&]jddesign=([^&#]+)\/.exec(window.location.search);\n    if (q && DESIGNS.indexOf(decodeURIComponent(q[1])) > -1) return decodeURIComponent(q[1]);\n    var attr = String(root.getAttribute('data-design') || '').trim();\n    return DESIGNS.indexOf(attr) > -1 ? attr : 'classic';\n  }\n  function setDesign(id) {\n    currentDesign = DESIGNS.indexOf(id) > -1 ? id : 'classic';\n    sheets.forEach(function (sh) {\n      var on = sh.getAttribute('data-design') === currentDesign;\n      sh.hidden = !on;\n      if (on) sheet = sh;\n    });\n    designSel.value = currentDesign;\n    fit();\n  }\n  designSel.addEventListener('change', function () {\n    var from = currentDesign;\n    setDesign(designSel.value);\n    track('jd_builder_design_change', { jd_from_design: from });\n  });\n  \/* Fills the role fields from the post (also used by Reset). Company details are not touched. *\/\n  function applyPost() {\n    var vals = postValues(post);\n    ROLE_FIELDS.forEach(function (k) { state[k] = vals[k]; });\n  }\n  $('#cwjd-reset').addEventListener('click', function () {\n    if (!window.confirm('Reset every field back to the template from this article? Your changes will be lost.')) return;\n    state = copy(COMMON); logoData = ''; $('#cwjd-logo').value = ''; applyPost();\n    fillForm(); setStatus(''); render(); updateCta();\n  });\n  $('#cwjd-clear').addEventListener('click', function () {\n    var next = {}, all = copy(COMMON);\n    ROLE_FIELDS.forEach(function (k) { all[k] = ''; });\n    for (var k in all) next[k] = KEEP_ON_CLEAR.indexOf(k) > -1 ? state[k] : '';\n    state = next; fillForm(); setStatus(''); render();\n  });\n  if (window.name === 'is_jd_signup' && window.opener) { try { window.opener.postMessage({ cwjd: 'signed-in' }, window.location.origin); } catch (e) {} }\n  state = copy(COMMON);\n  applyPost();\n  fillForm();\n  updateCta();\n  render();\n  setDesign(pickDesign());\n  layout();\n  \/* Counts a view once, the first time the builder actually scrolls into sight. *\/\n  if (window.IntersectionObserver) {\n    var seen = new IntersectionObserver(function (entries) {\n      for (var i = 0; entries.length > i; i++) {\n        if (entries[i].isIntersecting) { seen.disconnect(); track('jd_builder_view'); break; }\n      }\n    }, { threshold: 0.5 });\n    seen.observe(root.querySelector('.cwjd-formhead') || root);\n  } else { track('jd_builder_view'); }\n  if (window.ResizeObserver) {\n    new ResizeObserver(layout).observe(root);\n    var sheetWatch = new ResizeObserver(function () { fit(); });\n    sheets.forEach(function (sh) { sheetWatch.observe(sh); });\n  }\n  window.addEventListener('resize', layout);\n  window.addEventListener('scroll', onScroll, { passive: true });\n  if (document.fonts && document.fonts.ready) document.fonts.ready.then(fit);\n  }\n})();\n<\/script>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Nodejs_Developer_Job_Description_Sample\"><\/span>Node.js Developer Job Description Sample<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A sample job post gives you a ready-made starting point. The following example is for a company looking for a developer to build and maintain the back-end parts of its web applications:&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Node.js Developer Job Description <\/strong><br><br><strong>Job Title:<\/strong> Node.js Developer<br><strong>Company Name: <\/strong>TechWorks Solutions<br><strong>Location:<\/strong> Bengaluru, Karnataka (Hybrid)<br><strong>Employment Type: <\/strong>Full-time<br><strong>Experience Required: <\/strong>2 to 4 years<br><strong>Salary Range:<\/strong> \u20b98.8 LPA &#8211; \u20b910.5 LPA, depending on experience and skills<br><br><strong>About the Company<\/strong><br><br>TechWorks Solutions is a technology company that develops web applications and digital solutions for businesses across various industries. Our team builds reliable, user-friendly, scalable products that address real-world business challenges.<br><br><strong>Role Summary<\/strong><br><br>We are looking for a talented Node.js developer to build, test, and maintain server-side applications. The applicant should possess technical knowledge of JavaScript, back-end development, and API integration. You will collaborate with front-end developers, designers, and other team members to develop high-performance and secure applications that meet business requirements.<br><br><strong>Key Job Responsibilities<\/strong><br><br>Develop and maintain server-side applications using Node.js<br>Write clean, reusable, and maintainable code<br>Identify and resolve bugs, performance issues, and technical problems<br>Build, test, and document RESTful APIs for web and mobile applications<br>Integrate databases and third-party services into existing applications<br>Implement appropriate security measures and data validation practices<br>Work with front-end developers and other stakeholders to deliver application features<br>Participate in code reviews and contribute to improving development processes<br>Monitor application performance and maintain technical documentation<br><br><strong>Required Skills<\/strong><br><br>Proficiency in Node.js and JavaScript<br>Knowledge of Express.js and other back-end frameworks<br>Understanding of RESTful API development and integration<br>Knowledge of MongoDB, PostgreSQL, or MySQL<br>Familiarity with Git and version control workflows<br>Understanding of asynchronous programming, error handling, and debugging<br>Knowledge of basic web security practices<br><br><strong>Preferred Skills<\/strong><br><br>Experience with TypeScript<br>Familiarity with AWS or Microsoft Azure<br>Knowledge of CI\/CD pipelines and Docker<br>Understanding of microservices architecture<br>Experience with automated testing frameworks<br><br><strong>Education and Qualifications<\/strong><br><br>A bachelor&#8217;s degree in CS, IT, or a related field is preferred.<br>Relevant practical experience or demonstrable project work will also be considered.<br>Candidates should have a portfolio or examples of projects that demonstrate their back-end development skills.<br><br><strong>Benefits and Perks<\/strong><br><br>Competitive salary and performance-based incentives<br>Flexible working arrangements<br>Paid leave and health insurance, subject to company policy<br>Opportunities to work on challenging technical projects<br>Access to learning resources and professional development programs<br>A collaborative work environment with opportunities for career growth<br><br><strong>Application Process: <\/strong>You<strong> <\/strong>can apply by submitting your resume through our careers page or by emailing it to the recruitment team at the company&#8217;s official hiring email address. Please include links to relevant projects or your GitHub profile, if available.<br><br><strong>Application Deadline:<\/strong> 30\/10\/2026Shortlisted candidates will be contacted for a technical assessment and subsequent interview rounds.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Cost_for_Hiring_a_Nodejs_Developer\"><\/span>Cost for Hiring a Node.js Developer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Hiring costs for a Node.js developer depend on experience, technical skills, and employment type. Understanding the Node.js developer roles and responsibilities helps employers set realistic salary expectations and account for recruitment and onboarding expenses.&nbsp;<\/p>\n\n\n\n<p>Here are the main factors that influence hiring costs:<\/p>\n\n\n\n<ul>\n<li><strong>Experience Level<\/strong>: Developers with extensive experience in back-end architecture, application optimization, and system design may expect higher salaries than entry-level candidates.<\/li>\n\n\n\n<li><strong>Technical Skills<\/strong>: Specialized knowledge of TypeScript, cloud platforms, microservices, and database optimization can affect compensation, depending on the role.<\/li>\n\n\n\n<li><strong>Employment Type<\/strong>: Hiring a full-time employee involves ongoing salary and employment-related expenses, while contract or freelance arrangements may be billed hourly, monthly, or per project.<\/li>\n\n\n\n<li><strong>Location and Work Arrangement<\/strong>: Compensation expectations can vary by city, local talent availability, and whether the position is remote, hybrid, or office-based.<\/li>\n\n\n\n<li><strong>Project Complexity<\/strong>: Applications involving real-time processing, high traffic, complex integrations, or strict security requirements may require developers with more advanced expertise.<\/li>\n\n\n\n<li><strong>Recruitment and Onboarding<\/strong>: Job advertising, technical assessments, interviews, background checks, and onboarding add to the overall hiring cost.<\/li>\n<\/ul>\n\n\n\n<p>The table below shows the expected salary to offer Node.js developers based on job market trends.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Experience Level<\/strong><\/td><td><strong>Average Salary Range<\/strong><\/td><\/tr><tr><td><strong>Entry-Level [0 &#8211; 2 Years]<\/strong><\/td><td>\u20b93.7 LPA &#8211; \u20b94.8 LPA<\/td><\/tr><tr><td><strong>Intermediate-Level [3 &#8211; 5 Years]<\/strong><\/td><td>\u20b95.9 LPA &#8211; \u20b98.8 LPA<\/td><\/tr><tr><td><strong>Experienced Developers [5+ Years]<\/strong><\/td><td>\u20b99 LPA &#8211; \u20b913.2 LPA<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Tips_for_Writing_a_Strong_Job_Description_for_Hiring_a_Nodejs_Developer\"><\/span>Tips for Writing a Strong Job Description for Hiring a Node.js Developer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A strong job post helps candidates understand the role and decide whether to apply. It should be clear, honest, and easy to scan. Use these tips to improve your job description.<\/p>\n\n\n\n<ul>\n<li><strong>Use the Right Job Title<\/strong>: Choose a title that matches the actual role. For example, use \u2018Junior Node.js Developer&#8217; when hiring someone with limited professional experience.<\/li>\n\n\n\n<li><strong>Keep the Language Simple<\/strong>: Avoid long sentences and unnecessary technical terms. Explain specialized tools only when extra context is needed.<\/li>\n\n\n\n<li><strong>Make the Duties Specific<\/strong>: Instead of writing \u2018handle technical tasks, say \u2018build APIs, connect databases, and fix errors in existing applications.\u2018 Specific duties help candidates understand the job.<\/li>\n\n\n\n<li><strong>Separate Essential and Optional Skills: <\/strong>Clearly identify the skills candidates must have and those they can learn after joining. This can help attract applicants with the right level of experience.<\/li>\n\n\n\n<li><strong>Explain How to Apply<\/strong>: Tell candidates which documents they need to submit, where to apply, and when applications close.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large desktop-image\"><a href=\"https:\/\/internshala.com\/post-job\/?utm_source=is_blog&amp;utm_medium=employer-node-js-developer-job-description&amp;utm_campaign=employer-web-banner\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"203\" src=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/07\/Post-your-job-nowweb-1024x203.jpg\" alt=\"Post your job now(web)\" class=\"wp-image-24198\" srcset=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/07\/Post-your-job-nowweb-1024x203.jpg 1024w, https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/07\/Post-your-job-nowweb-672x133.jpg 672w, https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/07\/Post-your-job-nowweb-1536x305.jpg 1536w, https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/07\/Post-your-job-nowweb-2048x406.jpg 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full mobile-image\"><a href=\"https:\/\/internshala.com\/post-job\/?utm_source=is_blog&amp;utm_medium=employer-node-js-developer-job-description&amp;utm_campaign=employer-mobile-banner\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"356\" height=\"256\" src=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2024\/08\/Post-your-job-nowmobile.jpg\" alt=\"Post your job now (mobile)\" class=\"wp-image-24469\"\/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A well-drafted Node.js developer job description can help align your hiring decisions with your organization\u2019s technical priorities. Consider the challenges your team needs to solve, the expertise required, and how the role will contribute to product development. By focusing on long-term business objectives rather than short-term requirements alone, employers can make more informed recruitment decisions and build development teams equipped to support future growth.<\/p>\n\n\n\n<p>Looking to strengthen your hiring strategy? Explore <a href=\"https:\/\/internshala.com\/blog\/employer-best-website-to-hire-developers\/\" target=\"_blank\" rel=\"noreferrer noopener\">how to hire developers<\/a> to discover useful tips for finding the right technical talent for your team.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FAQs\"><\/span>FAQs<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<div class=\"schema-faq wp-block-yoast-faq-block\"><div class=\"schema-faq-section\" id=\"faq-question-1792687568933\"><strong class=\"schema-faq-question\">Q<strong>1. What should employers look for when hiring a Node.js developer?<\/strong><\/strong> <p class=\"schema-faq-answer\">Employers should assess a candidate\u2019s JavaScript and Node.js proficiency, API development experience, database knowledge, debugging skills, and understanding of application security.\u00a0<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1792687584878\"><strong class=\"schema-faq-question\">Q<strong>2. What should a Node.js developer job description include?<\/strong><\/strong> <p class=\"schema-faq-answer\">It should include the job title, company details, role overview, duties, required skills, experience, salary, benefits, work location, and application instructions. Employers should also mention any preferred skills.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1792687600537\"><strong class=\"schema-faq-question\">Q<strong>3. What skills are required for a Node.js developer?<\/strong><\/strong> <p class=\"schema-faq-answer\">The main skills include JavaScript, Node.js, API development, database knowledge, testing, debugging, and Git. Depending on the role, employers may also look for Express.js, TypeScript, cloud tools, and security knowledge.<\/p> <\/div> <div class=\"schema-faq-section\" id=\"faq-question-1792687614941\"><strong class=\"schema-faq-question\">Q<strong>4. How can employers evaluate Node.js developer candidates?<\/strong><\/strong> <p class=\"schema-faq-answer\">Employers can evaluate candidates through technical interviews, coding assignments, code reviews, and discussions about previous projects. Assessments should reflect the work involved in the position, troubleshooting errors, integrating databases, or improving application performance.<\/p> <\/div> <\/div>\n<aside class=\"mashsb-container mashsb-main \"><div class=\"mashsb-box\"><div class=\"mashsb-count mash-medium\" style=\"float:left\"><div class=\"counts mashsbcount\">0<\/div><span class=\"mashsb-sharetext\">SHARES<\/span><\/div><div class=\"mashsb-buttons\"><a class=\"mashicon-facebook mash-medium mashsb-noshadow\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https%3A%2F%2Finternshala.com%2Fblog%2Femployer-node-js-developer-job-description%2F\" target=\"_top\" rel=\"nofollow\"><span class=\"icon\"><\/span><span class=\"text\">Share&nbsp;on&nbsp;Facebook<\/span><\/a><a class=\"mashicon-subscribe mash-medium mashsb-noshadow\" href=\"#\" target=\"_top\" rel=\"nofollow\"><span class=\"icon\"><\/span><span class=\"text\">Get&nbsp;Your&nbsp;Dream&nbsp;Internship<\/span><\/a><div class=\"onoffswitch2 mash-medium mashsb-noshadow\" style=\"display:none\"><\/div><\/div>\n            <\/div>\n                <div style=\"clear:both\"><\/div><\/aside>\n            <!-- Share buttons by mashshare.net - Version: 4.0.42-->","protected":false},"excerpt":{"rendered":"<p>Summary: Node.js powers scalable applications through Chrome\u2019s V8 JavaScript engine and its asynchronous, event-driven architecture. When hiring developers to build and maintain such applications, employers need to define the skills<\/p>\n","protected":false},"author":6502,"featured_media":30745,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4319],"tags":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Node. js Developer Job Description: Free Sample &amp; Template<\/title>\n<meta name=\"description\" content=\"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Node. js Developer Job Description: Free Sample &amp; Template\" \/>\n<meta property=\"og:description\" content=\"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\" \/>\n<meta property=\"og:site_name\" content=\"Internshala blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-22T04:51:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-22T16:52:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description.png\" \/>\n\t<meta property=\"og:image:width\" content=\"900\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Shobha Saini\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Shobha Saini\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\"},\"author\":{\"name\":\"Shobha Saini\",\"@id\":\"https:\/\/internshala.com\/blog\/#\/schema\/person\/c220799e53244b6b0da150e24591978f\"},\"headline\":\"Node. js Developer Job Description: Free Sample &#038; Template\",\"datePublished\":\"2026-10-22T04:51:00+00:00\",\"dateModified\":\"2026-10-22T16:52:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\"},\"wordCount\":1636,\"publisher\":{\"@id\":\"https:\/\/internshala.com\/blog\/#organization\"},\"articleSection\":[\"HR Resources\"],\"inLanguage\":\"en-US\"},{\"@type\":[\"WebPage\",\"FAQPage\"],\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\",\"url\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\",\"name\":\"Node. js Developer Job Description: Free Sample & Template\",\"isPartOf\":{\"@id\":\"https:\/\/internshala.com\/blog\/#website\"},\"datePublished\":\"2026-10-22T04:51:00+00:00\",\"dateModified\":\"2026-10-22T16:52:31+00:00\",\"description\":\"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.\",\"breadcrumb\":{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#breadcrumb\"},\"mainEntity\":[{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933\"},{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878\"},{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537\"},{\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941\"}],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/internshala.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Employer Resources\",\"item\":\"https:\/\/internshala.com\/blog\/employer-resources\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"HR Resources\",\"item\":\"https:\/\/internshala.com\/blog\/employer-resources\/hr-resources\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Node JS Developer Job Description\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/internshala.com\/blog\/#website\",\"url\":\"https:\/\/internshala.com\/blog\/\",\"name\":\"Internshala blog\",\"description\":\"Your favourite senior outside college\",\"publisher\":{\"@id\":\"https:\/\/internshala.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/internshala.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/internshala.com\/blog\/#organization\",\"name\":\"Internshala blog\",\"url\":\"https:\/\/internshala.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/internshala.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/08\/LOGO-1.png\",\"contentUrl\":\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/08\/LOGO-1.png\",\"width\":112,\"height\":31,\"caption\":\"Internshala blog\"},\"image\":{\"@id\":\"https:\/\/internshala.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/internshala.com\/blog\/#\/schema\/person\/c220799e53244b6b0da150e24591978f\",\"name\":\"Shobha Saini\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/internshala.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/12\/Shobha-96x96.jpg\",\"contentUrl\":\"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/12\/Shobha-96x96.jpg\",\"caption\":\"Shobha Saini\"},\"description\":\"Shobha Saini is the Head of Human Resources at Internshala with over eight years of experience in employee relations and talent acquisition. She has led strategic HR initiatives and built effective people practices across the organization. She specializes in strategic planning, policy-making, and performance management. A multi-talented professional, she has played a key role in shaping HR strategies at Internshala.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/shobha-saini-she-her-7a95131a\/\"],\"url\":\"https:\/\/internshala.com\/blog\/author\/shobha-saini\/\"},{\"@type\":\"Question\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933\",\"position\":1,\"url\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933\",\"name\":\"Q1. What should employers look for when hiring a Node.js developer?\",\"answerCount\":1,\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Employers should assess a candidate\u2019s JavaScript and Node.js proficiency, API development experience, database knowledge, debugging skills, and understanding of application security.\u00a0\",\"inLanguage\":\"en-US\"},\"inLanguage\":\"en-US\"},{\"@type\":\"Question\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878\",\"position\":2,\"url\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878\",\"name\":\"Q2. What should a Node.js developer job description include?\",\"answerCount\":1,\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"It should include the job title, company details, role overview, duties, required skills, experience, salary, benefits, work location, and application instructions. Employers should also mention any preferred skills.\",\"inLanguage\":\"en-US\"},\"inLanguage\":\"en-US\"},{\"@type\":\"Question\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537\",\"position\":3,\"url\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537\",\"name\":\"Q3. What skills are required for a Node.js developer?\",\"answerCount\":1,\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"The main skills include JavaScript, Node.js, API development, database knowledge, testing, debugging, and Git. Depending on the role, employers may also look for Express.js, TypeScript, cloud tools, and security knowledge.\",\"inLanguage\":\"en-US\"},\"inLanguage\":\"en-US\"},{\"@type\":\"Question\",\"@id\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941\",\"position\":4,\"url\":\"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941\",\"name\":\"Q4. How can employers evaluate Node.js developer candidates?\",\"answerCount\":1,\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Employers can evaluate candidates through technical interviews, coding assignments, code reviews, and discussions about previous projects. Assessments should reflect the work involved in the position, troubleshooting errors, integrating databases, or improving application performance.\",\"inLanguage\":\"en-US\"},\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Node. js Developer Job Description: Free Sample & Template","description":"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.","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:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/","og_locale":"en_US","og_type":"article","og_title":"Node. js Developer Job Description: Free Sample & Template","og_description":"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.","og_url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/","og_site_name":"Internshala blog","article_published_time":"2026-10-22T04:51:00+00:00","article_modified_time":"2026-10-22T16:52:31+00:00","og_image":[{"width":900,"height":600,"url":"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2026\/10\/Node.js-Developer-Job-Description.png","type":"image\/png"}],"author":"Shobha Saini","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Shobha Saini","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#article","isPartOf":{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/"},"author":{"name":"Shobha Saini","@id":"https:\/\/internshala.com\/blog\/#\/schema\/person\/c220799e53244b6b0da150e24591978f"},"headline":"Node. js Developer Job Description: Free Sample &#038; Template","datePublished":"2026-10-22T04:51:00+00:00","dateModified":"2026-10-22T16:52:31+00:00","mainEntityOfPage":{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/"},"wordCount":1636,"publisher":{"@id":"https:\/\/internshala.com\/blog\/#organization"},"articleSection":["HR Resources"],"inLanguage":"en-US"},{"@type":["WebPage","FAQPage"],"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/","url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/","name":"Node. js Developer Job Description: Free Sample & Template","isPartOf":{"@id":"https:\/\/internshala.com\/blog\/#website"},"datePublished":"2026-10-22T04:51:00+00:00","dateModified":"2026-10-22T16:52:31+00:00","description":"Learn how to write a Node. js developer job description with a sample template, key responsibilities and practical tips to attract qualified candidates.","breadcrumb":{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#breadcrumb"},"mainEntity":[{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933"},{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878"},{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537"},{"@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941"}],"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/internshala.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Employer Resources","item":"https:\/\/internshala.com\/blog\/employer-resources\/"},{"@type":"ListItem","position":3,"name":"HR Resources","item":"https:\/\/internshala.com\/blog\/employer-resources\/hr-resources\/"},{"@type":"ListItem","position":4,"name":"Node JS Developer Job Description"}]},{"@type":"WebSite","@id":"https:\/\/internshala.com\/blog\/#website","url":"https:\/\/internshala.com\/blog\/","name":"Internshala blog","description":"Your favourite senior outside college","publisher":{"@id":"https:\/\/internshala.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/internshala.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/internshala.com\/blog\/#organization","name":"Internshala blog","url":"https:\/\/internshala.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/internshala.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/08\/LOGO-1.png","contentUrl":"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/08\/LOGO-1.png","width":112,"height":31,"caption":"Internshala blog"},"image":{"@id":"https:\/\/internshala.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/internshala.com\/blog\/#\/schema\/person\/c220799e53244b6b0da150e24591978f","name":"Shobha Saini","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/internshala.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/12\/Shobha-96x96.jpg","contentUrl":"https:\/\/internshala.com\/blog\/wp-content\/uploads\/2023\/12\/Shobha-96x96.jpg","caption":"Shobha Saini"},"description":"Shobha Saini is the Head of Human Resources at Internshala with over eight years of experience in employee relations and talent acquisition. She has led strategic HR initiatives and built effective people practices across the organization. She specializes in strategic planning, policy-making, and performance management. A multi-talented professional, she has played a key role in shaping HR strategies at Internshala.","sameAs":["https:\/\/www.linkedin.com\/in\/shobha-saini-she-her-7a95131a\/"],"url":"https:\/\/internshala.com\/blog\/author\/shobha-saini\/"},{"@type":"Question","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933","position":1,"url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687568933","name":"Q1. What should employers look for when hiring a Node.js developer?","answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"Employers should assess a candidate\u2019s JavaScript and Node.js proficiency, API development experience, database knowledge, debugging skills, and understanding of application security.\u00a0","inLanguage":"en-US"},"inLanguage":"en-US"},{"@type":"Question","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878","position":2,"url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687584878","name":"Q2. What should a Node.js developer job description include?","answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"It should include the job title, company details, role overview, duties, required skills, experience, salary, benefits, work location, and application instructions. Employers should also mention any preferred skills.","inLanguage":"en-US"},"inLanguage":"en-US"},{"@type":"Question","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537","position":3,"url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687600537","name":"Q3. What skills are required for a Node.js developer?","answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"The main skills include JavaScript, Node.js, API development, database knowledge, testing, debugging, and Git. Depending on the role, employers may also look for Express.js, TypeScript, cloud tools, and security knowledge.","inLanguage":"en-US"},"inLanguage":"en-US"},{"@type":"Question","@id":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941","position":4,"url":"https:\/\/internshala.com\/blog\/employer-node-js-developer-job-description\/#faq-question-1792687614941","name":"Q4. How can employers evaluate Node.js developer candidates?","answerCount":1,"acceptedAnswer":{"@type":"Answer","text":"Employers can evaluate candidates through technical interviews, coding assignments, code reviews, and discussions about previous projects. Assessments should reflect the work involved in the position, troubleshooting errors, integrating databases, or improving application performance.","inLanguage":"en-US"},"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/posts\/30744"}],"collection":[{"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/users\/6502"}],"replies":[{"embeddable":true,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/comments?post=30744"}],"version-history":[{"count":0,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/posts\/30744\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/media\/30745"}],"wp:attachment":[{"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/media?parent=30744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/categories?post=30744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internshala.com\/blog\/wp-json\/wp\/v2\/tags?post=30744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}