How to Automate Job Application with ChatGPT in 3 Steps
Tags: chatgpt, javascript, typescript, tutorial
Published: 2023-07-29 11:30:29

It was my usual day. I was swiping new interesting vacancies to see what is required for my and higher positions. Then I've started using ChatGPT to generate a cover letter for me, so my applications will be more personalized and my chances to have feedback will be higher, but I had to copy-paste more than 3 times, so I decided to automate this process.

Project's tech stack: React, TypeScript, JavaScript, CSS, HTML

![final result preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/591g3f3toeudifo3jrus.png)

## Step 1: Obtain OpenAI API Key
The first thing you need is to obtain the OpenAI API key, so you'll be able to do requests to ChatGPT model. To do so, you need:
- Generate OpenAI API key here https://platform.openai.com/account/api-keys
![API Key generation screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvk22sk7ofjozo81crvh.png)
- _Optional_ Set up a paid account here: https://platform.openai.com/account/billing/overview. **It might be required if your trial is expired**

![Paid account set up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpwcmck27b78a5nwmwmm.png)

And don't forget to save API key in safe place as it will be required in next steps and during usage.

## Step 2: Use WebExtension template 
I've developed a small WebExtension which contains the most needed code to automate job application. The source code could be found here: https://github.com/mainarthur/open-djinni-ai.git. I used https://djinni.co as a target job board platform. If you're using djinni.co you can just go ahead and use template extension as an app.

![Example of UI on djinni.co](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kcqtzz34mwrs8f2r8qo.png)

I'll show you how to adapt this template with other job board. I'll use https://jobs.dou.ua/ as a target in this tutorial.

![jobs.dou.ua UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ojtm3va2v6thnd11m3i.png)

 {% collapsible Template structure %}
### Template's structure

![Templates structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2mw5izmis28zwpt8wej5.png)

In contentScript folder you can find `contentScript.ts` file which will be injected into target webpage where you can add DOM manipulations and other logic

![contentScript integration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vfvnspdenqqznq6bj7nm.png)

In popup folder you can find files which will be used to render the extension's popup

![popup UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uws3rhdv7prablslzhr0.png)

In static folder you can update extension's logo and manifest.json. Using manifest.json, you specify basic metadata about your extension such as the name and version, and can also specify aspects of your extension's functionality (such as background scripts, content scripts, and browser actions). [#1](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) [#2](https://developer.chrome.com/docs/extensions/mv3/manifest/)

![extension in list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4gc5nfovjcagrgcm6g8.png)


{% endcollapsible %}

## Step 3: Template modification and usage

Dependencies: [git](https://git-scm.com/), [node.js](https://nodejs.org/), [yarn](https://yarnpkg.com/)

So let's start with cloning the template repo:
```bash
git clone https://github.com/mainarthur/open-djinni-ai.git open-dou-ai
cd open-dou-ai
```
_You can change_ `open-dou-ai` _to whatever name of folder you want or don't include it at all_ [#](https://git-scm.com/docs/git-clone)

{% collapsible Update remote URL %}
You can change remote URL in case you want to push your changes to own git account and here is an easy command for it:
```bash
git remote set-url origin git@github.com:yourUserName/YourRepoName.git
```
{% endcollapsible %}

Then we should install all dependencies:
```bash
yarn install
```
and let's start analyzing the web page

Let's take a look on vacancy URL

![vacancy URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxxirusikciixe08jmsi.png)

It will help you find a pattern for URL, because you will need it for manifest file:
`src/static/manifest.json`
```json
"content_scripts": [
    {
      "matches": [
        "https://jobs.dou.ua/companies/*/vacancies/*"
      ],
      "js": [
        "contentScript.js"
      ]
    }
  ],
```
Now our contentScript will be executed only on dou.ua vacancy page

Next, we will need an apply button. Locate it on the website, then you should find ID or class CSS selector for the element. The easiest way to do so is to use DevTools

![DevTools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/usvohsemn5xm47m8jbsn.png)

and now we can update the content script with our new selector
```typescript
const allApplyButtons = document.querySelectorAll(
  "a#reply-btn-id"
);
```

When we click "apply" the text area for cover letter shows up, then we repeat the same procedure as we did with apply button

![cover letter DevTools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcr5t4t4jxy0r66z8hyx.png)

Then we update contentScript again with this selector:
```typescript
  setTimeout(async () => {
    const textarea = document.querySelector(
      "textarea#reply_descr"
    ) as HTMLTextAreaElement;
```

Extension also requires vacancy text for ChatGPT prompt generation. So you need to find selector for vacancy text:

![Vacancy text selector](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l61dno74v67r6ry3swf5.png)

```typescript
    const data = {
      model: "gpt-3.5-turbo",
      messages: [
        {
          role: "user",
          content:
            "Hello, my skills are " +
            (await get(SKILLS_LIST_KEY)) +
            ", my experience:" +
            (await get(EXPERIENCE_KEY)) +
            " generate me a personalized apply message for a vacancy: " +
            (
              document.querySelector(
                "div.vacancy-section"
              ) as HTMLDivElement
            ).innerText,
        },
      ],
    };
```


And let's also don't forget to update the name of our new extension in `popup.tsx`

```typescript
  return (
    <React.Fragment>
      <Nav>
        <Heading>OpenAI dou.ua Apply</Heading>
      </Nav>
      <Main>
```

and in `manifest.json` file:
```json
{
  "manifest_version": 3,
  "name": "Dou AI",
  "description": "Chrome extension for applying dou.ua jobs using OpenAI's ChatGPT",
  "version": "1.0.0",
  "action": {
```

And now we're ready to build and run the extension. To build your code, you can run this command:
```bash
yarn build
```
and load the build in your browser
- Go to [chrome://extensions/](chrome://extensions/)
- Turn on developer mode
![dev mode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j0x46artvw8kiuobev5c.png)
- Load unpacked extension and here you have it

![your extension screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5kwbpeuvrco6dte7i29b.png)

Now we can move back to the vacancy page and refresh it. Open the popup and fill all data:

![filled data](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iewd6l2lndpkeqp9v85e.png)

We're ready to use it with any vacancy, because now we have 'Apply with ChatGPT' button. 

![Apply with ChatGPT](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/409niuybob5gjg8y3tvs.png)

Let's click on it and wait for result


![final result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsnaf0ra3lo4xuoefcfa.png)

And we're finally done. The result code you can find here:  https://github.com/mainarthur/open-dou-ai. This project still has a lot of room for improvement: we can add animations, adapt it for multiple platforms at once, and include the ability to dynamically select CSS selectors.