Skip to content

Commit

Permalink
NextJS Fullstack Webapp (#149)
Browse files Browse the repository at this point in the history
* feat: add full stack web app 

Adds in a nextjs and fastapi webapp (experimental)

* feat: render save service keys on web app ui (#135)

* feat: render save service keys on web app ui

Implemented new feature to allow users to view the required configurable service keys (and urls) to set, on the web app UI.

The configurable required service keys data is dynamically derived from the backend master YAML config file (located in `/scripts/similarity/config.yml`), and its actual pre-saved secret key values derived from a localised programatically created git-ignored YAML secrets config file (located in `/scripts/similarity/config.local.yml`).

Whenever a key is no longer required by the app, then it is safe to remove key from the master config file, and in turn this key and any pre-saved secret value will no longer render on the web UI.

If a secret has yet to be set for any of the required keys, then the value will fallback to the default placeholder value defined in the master YAML config.

* chore: update next.js version and dependencies

* chore: error handling for missing keys config file

Add error handling on the backend api for when `similarity/config.yaml` does not exist, to which it responds with a 404 not found response.

As a result, also added error handling on the frontend ui code to handle the above 404 backend api response edge case to not render the Service Keys ui section.

* chore: ui refactor resume.tsx to hero.tsx

Logically abstracted out and renamed `Hero` component to its own folder, and corrected / renamed component filename.

* chore: sync requirements.txt from upstream

Pulled a bugfix for `requirements.txt` file from upstream fork origin repo main branch, which broke the webapp backend server run.

Root cause was that the qdrant-client dependency was set with a specific version; `qdrant-client>=1.1.1`, but the upstream reversion fix; `qdrant-client` without explicitly specifying a version resolved the webapp backend server run issue.

* chore: add debug troubleshooting steps to webapp readme (#141)

This change is to add new sections labelled `Debugging` and `Troubleshooting` to the `webapp/README.md` file.

The debugging section guides users on how to run the FastAPI backend server in VS Codes' debug mode, along with running the frontend server in isolation.

The troubleshooting section currently highlights one potential common issue that users may encounter when only running the frontend server in isolation (e.g. `npm run next-dev`).

---------

Co-authored-by: Sayvai <[email protected]>
  • Loading branch information
srbhr and Sayvai authored Sep 16, 2023
1 parent 17e9808 commit 2b9cb6a
Show file tree
Hide file tree
Showing 47 changed files with 7,616 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,6 @@ dmypy.json
.vscode/*

scripts/similarity/config.yml

# Secrets
*.local.yml
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ Follow these steps to set up the environment and run the application.

2. Open `localhost:80` on your browser

<br/>

### Running the Web Application

The full stack Next.js (React and FastAPI) web application allows users to interact with the Resume Matcher tool interactively via a web browser.

To run the full stack web application (frontend client and backend api servers), follow the instructions over on the [webapp README](/webapp/README.md) file.

<br/>

### Cohere and Qdrant

1. Visit [Cohere website registration](https://dashboard.cohere.ai/welcome/register) and create an account.
Expand Down
5 changes: 4 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ decorator==5.1.1
en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.6.0/en_core_web_md-3.6.0-py3-none-any.whl#sha256=1618fc62e7aedc2b778caa3ea6e9c8280beac3b83fe7b93316cbb9e8f3abe7c5
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.6.0/en_core_web_sm-3.6.0-py3-none-any.whl#sha256=83276fc78a70045627144786b52e1f2728ad5e29e5e43916ec37ea9c26a11212
Faker==19.1.0
fastapi==0.101.1
favicon==0.7.0
floret==0.10.3
fonttools==4.41.0
Expand Down Expand Up @@ -61,6 +62,7 @@ pyparsing==3.0.9
pypdf==3.12.2
pyphen==0.14.0
python-dateutil==2.8.2
python-multipart==0.0.6
pytz==2023.3
pytz-deprecation-shim==0.1.0.post0
PyYAML==6.0
Expand Down Expand Up @@ -102,6 +104,7 @@ typer==0.9.0
typing_extensions==4.7.1
tzdata==2023.3
tzlocal==4.3.1
uvicorn==0.23.2
urllib3>=1.26.14
validators==0.20.0
wasabi==1.1.2
Expand All @@ -110,4 +113,4 @@ zipp==3.16.2
reportlab==4.0.4
easygui==0.98.3
cohere~=4.19.2
qdrant-client>=1.2
qdrant-client>=1.2
11 changes: 11 additions & 0 deletions webapp/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "next/core-web-vitals",
"rules": {
"no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_"
}
]
}
}
35 changes: 35 additions & 0 deletions webapp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
160 changes: 160 additions & 0 deletions webapp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Resume Matcher - A Full Stack Web Application

The Resume Matcher takes your resume and job descriptions as input, parses them using Python, and mimics the functionalities of an ATS, providing you with insights and suggestions to make your resume ATS-friendly.

## Demo

View a brief GIF demo of the web apps' design functionality below:

![Resume-Matcher-Web-App-UI-Quick-Demo-2](https://github.com/Sayvai/react-project-dashboard-mvp-match/assets/7581546/5bf9c4c8-a5d1-47ee-8e27-eacda0dbcac9)

## Getting Started

### Prerequisites

- install [Node.js](https://nodejs.org/en/download/). The version used for this project is v18.17.0

- install [Python](https://www.python.org/downloads/). The version used for this project is v3.11.5

### Setup

- clone the repository
- navigate to the project directory (e.g. `cd Resume-Matcher`)
- Follow the [README](../README.md) instructions set out in the root of the repository to setup the Python environment and run the Python scripts.
- navigate to the `webapp` directory (e.g. `cd webapp`)
- run `npm install` to install the frontend client app dependencies
- run `npm run dev` to start the web app (i.e. this script will start the frontend client and backend FastAPI servers concurrently within one terminal process inside `webapp` directory`)
- once both servers are ready, open [http://localhost:3000](http://localhost:3000) on your browser to view and interact with the app.

### Extra Setup Hints

- 💡 You may also decide to run the frontend and backend servers in separate terminal processes independently of one another. To run the frontend server in isolation, run `npm run next-dev`. To run the backend FastAPI server in isolation, run `npm run fastapi-dev`.

## Debugging

### VS Code Debugger - FastAPI Backend

When working with the backend web application files, you may like to debug the backend server during runtime and have the ability to set breakpoints to pause execution on certain line(s), inspect variable values, and other runtime data using the VS Code debugger. To do so, follow the steps below:

#### Setup VS Code Launch Configuration

- Open the VS Code debugger tab (i.e. the bug icon on the left sidebar)

- Click on the gear icon to open the launch.json file

- Add the following configuration to the launch.json file, and save:

```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug FastAPI Backend",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": ["webapp.backend.api.index:app", "--reload"],
"jinja": true,
"justMyCode": true
}
]
}
```

#### Start the Backend Server in Debug Mode

- ⚠️ IMPORTANT: Before proceeding along this set of steps, ensure the frontend server is NOT running. It will need to be running in isolation of the backend server, after the backend server has succesfully completed its starup process.

- Open the VS Code debugger tab (i.e. the bug icon on the left sidebar)

- Select the "Debug FastAPI Backend" configuration from the dropdown

- Click on the play button to start the backend server in debug mode

- A new terminal window will open and the backend server will start running in debug mode

- You may optionally set breakpoints in the backend python files to pause execution on certain line(s), inspect variable values, and other runtime data, as you interact with the app or make requests to the backend server.

- Esnure the frontend server is running in isolation of the backend server, after the backend server has succesfully completed its starup process. By running the following command in a separate terminal window:

```bash
npm run next-dev
```

- Once the backend server (and frontend server) is ready, open [http://localhost:3000](http://localhost:3000) on your browser to view and interact with the app.

### Visual demonstration of running the FastAPI backend server in VS Code Debugger

![Resume-Matcher-vs-code-debug-backend-fastapi-demo](https://github.com/srbhr/Resume-Matcher/assets/7581546/04b3b8e2-98c4-40ff-964f-8075c55091c9)

## Troubleshooting Common Issues

### Error: connect ECONNREFUSED 127.0.0.1:8000

<details>
<summary>You may encounter the following <code>Error: connect ECONNREFUSED 127.0.0.1:8000</code> error in the terminal (and browser ui throws an exception) when running the frontend server in isolation of the backend server via npm run next-dev (👉 👀 click to reveal error snippet):</summary>

```bash
[0] Failed to proxy http://127.0.0.1:8000/api/service-keys Error: connect ECONNREFUSED 127.0.0.1:8000
[0] at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) {
[0] errno: -61,
[0] code: 'ECONNREFUSED',
[0] syscall: 'connect',
[0] address: '127.0.0.1',
[0] port: 8000
[0] }
[0] Error: connect ECONNREFUSED 127.0.0.1:8000
[0] at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16) {
[0] errno: -61,
[0] code: 'ECONNREFUSED',
[0] syscall: 'connect',
[0] address: '127.0.0.1',
[0] port: 8000
[0] }
[0] SyntaxError: Unexpected token I in JSON at position 0
[0] at JSON.parse (<anonymous>)
[0] at parseJSONFromBytes (node:internal/deps/undici/undici:6662:19)
[0] at successSteps (node:internal/deps/undici/undici:6636:27)
[0] at node:internal/deps/undici/undici:1236:60
[0] at node:internal/process/task_queues:140:7
[0] at AsyncResource.runInAsyncScope (node:async_hooks:203:9)
[0] at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
[0] at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
[0] - error node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.edge.development.js (340:14) @ getErrorMessage
```
</details>
<br/>
💡 This is most likely because the backend server has not yet started in isolation. To resolve this, ensure the backend server is running in isolation of the frontend server, by running the following command in a separate terminal window, and wait for the backend server to complete its startup process, then refresh the browser window to view the app:
```bash
npm run fastapi-dev
```
💡 Or, you may alternatively run the backend server using the VS Code debugger, as described in the [VS Code Debugger - FastAPI Backend](#vs-code-debugger---fastapi-backend) section above.
## Future Improvements
Below are some of the improvements that can be made to the web app for future consideration:
- 👉 Replace mock response data with real data from the backend. View file; [scripts/resume_processor.py](/webapp/backend/scripts/resume_processor.py), where the `build_response()` function can be modified to hook up to other python scripts to process and return the real data from the backend. The initial python response model classes are defined in the [schemas/resume_processor.py](/webapp/backend/schemas/resume_processor.py) file, and so that should help to get started with thinking about how to structure the data to be returned from the backend.
- Add unit tests (frontend and backend)
- Add end-to-end functional tests (frontend)
- Improve the UI/UX of loading and error states as requests are made to the backend
## Technologies Used
This is a full stack web application, hosting the frontend UI interactive web client interface, and the backend server API.
The application is built using the following main technologies:
- [Next.js](https://nextjs.org/) - a React.js meta-framework for building client and server-side rendered React applications
- [FastAPI](https://fastapi.tiangolo.com/) - a Python framework for building web APIs
- [TailwindCSS](https://tailwindcss.com/) - a CSS framework for building responsive web applications
- [Zustand](https://github.com/pmndrs/zustand) - a frontend client state management library
- [react-pdf](https://projects.wojtekmaj.pl/react-pdf/) - a React component library for rendering PDF documents on the frontend ui
37 changes: 37 additions & 0 deletions webapp/app/(routes)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "@/app/globals.css";
import Header from "@/components/header/header";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Resume Matcher",
description:
"An AI Based Free & Open Source ATS, Resume Matcher to tailor your resume to a job description. Find the best keywords, and gain deep insights into your resume.",
keywords: ["Resume", "Matcher", "ATS", "Score"],
authors: [
{ name: "Samurize", url: "https://github.com/srbhr" },
{ name: "Sayvai", url: "https://github.com/Sayvai" },
],
icons: {
icon: "/favicon-32x32.png",
},
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<div className="flex flex-col w-full 2xl:w-2/3 m-auto bg-[#2A203B]">
<Header />
{children}
</div>
</body>
</html>
);
}
24 changes: 24 additions & 0 deletions webapp/app/(routes)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import JobDescriptions from "@/components/job-descriptions/job-descriptions";
import VectorScore from "@/components/vector-scores/vector-scores";
import CommonWords from "@/components/common-words/common-words";
import Suggestions from "@/components/suggestions/suggestions";
import ThirdPartyServicesKeys from "@/components/third-party-services/third-party-services";
import FileUpload from "@/components/resume/file-upload/file-upload";
import ResumeGlance from "@/components/resume/resume-glance/resume-glance";
import Hero from "@/components/hero/hero";

export default function Home() {
return (
<main>
<Hero>
<ThirdPartyServicesKeys />
<FileUpload buttonLabel="Upload Your Resume" />
</Hero>
<ResumeGlance />
<JobDescriptions />
<VectorScore />
<CommonWords />
<Suggestions />
</main>
);
}
22 changes: 22 additions & 0 deletions webapp/app/_components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import clsx from "clsx";

type ButtonProps = React.HTMLProps<HTMLButtonElement> & {
type?: "button" | "submit" | "reset";
children: React.ReactNode;
};

const Button = ({ children, type = "button", ...props }: ButtonProps) => {
const { className: inheritedClassNames, ...buttonProps } = props;

return (
<button
type={type}
className={clsx("flex gap-2 w-fit rounded-md p-4", inheritedClassNames)}
{...buttonProps}
>
{children}
</button>
);
};

export default Button;
Loading

0 comments on commit 2b9cb6a

Please sign in to comment.