diff --git a/.github/codeql/README.md b/.github/codeql/README.md new file mode 100644 index 0000000..85de7af --- /dev/null +++ b/.github/codeql/README.md @@ -0,0 +1,115 @@ +# CodeQL Setup for the-method + +This folder contains the CodeQL configuration for security and code quality scanning in this repository. + +## What each file does + +- `.github/workflows/codeql.yml` + - Defines when scans run and how GitHub Actions executes CodeQL for both frontend and backend. +- `.github/codeql/codeql-config.yml` + - Defines which folders to include and ignore during analysis for all supported languages in this repo. + +## CodeQL workflow breakdown (`.github/workflows/codeql.yml`) + +### `name: CodeQL` +The display name in the Actions tab. + +### `on.pull_request.branches` and `on.push.branches` +```yaml +on: + pull_request: + branches: [main] + push: + branches: [main] +``` +Runs scans when PRs target `main`, and when commits are pushed to `main`. + +### `permissions` +```yaml +permissions: + actions: read + contents: read + security-events: write +``` +Uses least-privilege permissions. `security-events: write` is required so CodeQL can upload findings. + +### Language setup (current) +```yaml +with: + languages: javascript-typescript, python +``` +This workflow currently runs analysis for both JavaScript/TypeScript (frontend) and Python (backend). + +### Checkout step +```yaml +with: + fetch-depth: 0 +``` +- `fetch-depth: 0` keeps full git history (safe default for analysis and troubleshooting). + +### Initialize CodeQL +```yaml +uses: github/codeql-action/init@v3 +with: + config-file: ./.github/codeql/codeql-config.yml +``` +Starts the CodeQL engine and loads `.github/codeql/codeql-config.yml`. + +### Analyze +```yaml +uses: github/codeql-action/analyze@v3 +``` +Executes queries and uploads results to GitHub Security. + +## Config breakdown (`.github/codeql/codeql-config.yml`) + +### `paths-ignore` +Generated/build/runtime artifact paths and cache folders are excluded to reduce noise and runtime: + +```yaml +paths-ignore: + - '**/node_modules/**' + - '**/dist/**' + - '**/build/**' + - '**/coverage/**' + - '**/logs/**' + - '**/.venv/**' + - '**/__pycache__/**' + - '**/*.min.js' + - '**/.pytest_cache/**' + - '**/.mypy_cache/**' + - '**/.next/**' +``` + +## Best practices + +1. **Keep trigger scope intentional.** + Use branch filters (`main`) to control cost and noise. +2. **Keep language list explicit.** + CodeQL should only review languages with meaningful source code. +3. **Exclude generated/vendor artifacts.** + Keep caches, dependencies, build outputs, logs, and minified files in `paths-ignore`. +4. **Pin to stable major action versions.** + `@v3` is the current stable major for CodeQL actions. +5. **Review alerts regularly.** + Handle high/critical findings made by the CodeQL bot first and solve with documented reasoning for accepting or rejecting the recommended fix. + +## Maintenance examples +Keeping this updated as code and language coverage evolve is important. Here are common maintenance changes. + +### Keep language scope aligned with this repository +This workflow currently analyzes JavaScript/TypeScript and Python: + +```yaml +with: + languages: javascript-typescript, python +``` + +Only change this value when this repository adds production code in another supported language. + +### Exclude another generated folder +Add a glob to `paths-ignore`, for example: + +```yaml +- '**/generated/**' +``` diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000..e78bce1 --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,14 @@ +# CodeQL config for The Method +# Exclude generated/build/runtime artifact paths and cache folders +paths-ignore: + - '**/node_modules/**' + - '**/dist/**' + - '**/build/**' + - '**/coverage/**' + - '**/logs/**' + - '**/.venv/**' + - '**/__pycache__/**' + - '**/*.min.js' + - '**/.pytest_cache/**' + - '**/.mypy_cache/**' + - '**/.next/**' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..ff4cbf2 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,32 @@ +name: CodeQL + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + actions: read + contents: read + security-events: write + +jobs: + analyze: + name: Analyze (javascript-typescript, python) + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: javascript-typescript, python + config-file: ./.github/codeql/codeql-config.yml + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/README.md b/README.md index 1f8bbae..60ec194 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,24 @@ # The Method A website that allows users to create, optimize, practice behavioral interviews, and apply for jobs all in one place. +- Create new latex based resumes that you can download +- Optimize resumes with key ideas and AI powered feedback +- Pratice inteviews questions that are commonly asked +- Apply to new jobs in your field + +## Features +### Current +- Home page +- Footer page contents +- Website theme switcher +- Basic resume generator + +### Work In Progress +- Login/signup system +- Supabase database system + +### Future +- Hosting website on Vercel +- Interview prep section ## Tech Stack

Frontend

@@ -11,6 +30,7 @@ A website that allows users to create, optimize, practice behavioral interviews, - Python + FastAPI - PostgreSQL + SQLAlchemy +- Supabase

DevOps

@@ -18,6 +38,58 @@ A website that allows users to create, optimize, practice behavioral interviews, - Docker +

Hosting

+ +- Vercel + +## Project Folder Structure + +```text +the-method/ +├── backend/ +│ ├── Dockerfile +│ ├── main.py +│ ├── models.py +│ ├── requirements.txt +│ ├── resume_analyzer.py +│ ├── database/ +│ │ ├── __init__.py +│ │ ├── engine.py +│ │ └── models.py +│ ├── interview/ +│ │ ├── refresh.py +│ │ └── service.py +│ └── llm/ +│ ├── client.py +│ ├── prompts.py +│ ├── service.py +│ └── test_llm.py +├── frontend/ +│ ├── Dockerfile +│ ├── index.html +│ ├── package.json +│ ├── vite.config.js +│ ├── src/ +│ │ ├── App.jsx +│ │ ├── main.jsx +│ │ ├── components/ +│ │ │ ├── FileUpload.jsx +│ │ │ ├── ResumePreview.jsx +│ │ │ └── ... +│ │ ├── pages/ +│ │ │ ├── HomePage.jsx +│ │ │ ├── FormPage.jsx +│ │ │ └── ... +│ │ └── styles/ +│ │ ├── styles.css +│ │ └── ... +├── docker-compose.yml +├── README.md +└── test-prompts/ + └── test.txt +``` + + ## Deploy the website ### App can be deployed via 4 method(3 with Docker & 1 with npm): - (1), (2), & (3): Testing frontend & backend logic, up to preference: diff --git a/backend/main.py b/backend/main.py index 4c03307..65f2df9 100644 --- a/backend/main.py +++ b/backend/main.py @@ -48,6 +48,8 @@ async def chat_endpoint(request: ResumeRequest): request (ResumeRequest): The request body containing the user's prompt. Returns: dict: The LLM's response or an error message. + Raises: + HTTPException: If the LLM returns an error response (500). """ # Prepend system prompt to messages @@ -71,6 +73,8 @@ async def generate_resume_endpoint(request: GenerateResumeRequest): request (GenerateResumeRequest): The request body containing the user's prompt. Returns: dict: The LLM's response or an error message. + Raises: + HTTPException: If the resume generation fails (500). """ # extract data from HTTP request @@ -92,9 +96,11 @@ async def optimize_resume_endpoint(request: OptimizeResumeRequest): Optimize resume for ATS according to job description. Args: - request (OptimizeResumeRequest): The request body containing the user's prompt. + request (OptimizeResumeRequest): The request body containing the user's prompt. Returns: - dict: The LLM's response or an error message. + dict: The LLM's response or an error message. + Raises: + HTTPException: If the resume optimization fails (500). """ resume_dict = request.resume.model_dump() @@ -117,6 +123,8 @@ async def analyze_resume_endpoint(request: AnalyzeResumeRequest): request (AnalyzeResumeRequest): The request body containing the user's prompt. Returns: dict: The analysis results or an error message. + Raises: + HTTPException: If the input is invalid (400) or an internal error occurs (500). """ try: @@ -140,9 +148,11 @@ async def generate_cover_letter_endpoint(request: CoverLetterRequest): Generate a cover letter based on resume and job description. Args: - request (OptimizeResumeRequest): The request body containing the user's prompt. + request (CoverLetterRequest): The request body containing the user's prompt. Returns: dict: The generated cover letter or an error message. + Raises: + HTTPException: If the cover letter generation fails (500). """ resume_dict = request.resume.model_dump() @@ -163,6 +173,16 @@ async def generate_cover_letter_endpoint(request: CoverLetterRequest): @app.get("/interview-questions/{company}") def get_interview_questions_endpoint(company: str): + """ + Retrieve interview questions for a specified company. + + Args: + company (str): The name of the company to retrieve interview questions for. + Returns: + dict: The interview questions data for the company, or an error message if not found. + Raises: + HTTPException: If the company is not found or has no data (404). + """ data = get_questions(company) diff --git a/backend/models.py b/backend/models.py index 07b83d9..00cd6dc 100644 --- a/backend/models.py +++ b/backend/models.py @@ -7,10 +7,14 @@ class ResumeRequest(BaseModel): + """Request model for sending a list of messages related to a resume.""" + messages: list class Education(BaseModel): + """Represents an education entry in a resume.""" + school: str | None = None major: str | None = None gpa: str | None = None @@ -20,6 +24,8 @@ class Education(BaseModel): class Experience(BaseModel): + """Represents a work experience entry in a resume.""" + company: str | None = None title: str | None = None location: str | None = None @@ -29,6 +35,8 @@ class Experience(BaseModel): class Project(BaseModel): + """Represents a project entry in a resume.""" + name: str | None = None description: str | None = None link: str | None = None @@ -37,23 +45,31 @@ class Project(BaseModel): class Link(BaseModel): + """Represents a link (e.g., LinkedIn, GitHub) in a resume.""" + type: str | None = None # linkedin, github, portfolio, other url: str | None = None class Certification(BaseModel): + """Represents a certification in a resume.""" + name: str | None = None issuer: str | None = None date: str | None = None class Award(BaseModel): + """Represents an award or honor in a resume.""" + name: str | None = None issuer: str | None = None date: str | None = None class Resume(BaseModel): + """Main resume model containing all user information.""" + name: str # required phone: str | None = None email: str | None = None @@ -70,20 +86,28 @@ class Resume(BaseModel): class GenerateResumeRequest(BaseModel): + """Request model for generating a resume.""" + resume: Resume class OptimizeResumeRequest(BaseModel): + """Request model for optimizing a resume for a job description.""" + resume: Resume job_description: str class AnalyzeResumeRequest(BaseModel): + """Request model for analyzing a resume against a job description.""" + resume: Resume job_description: str class AnalyzeResumeResponse(BaseModel): + """Response model for resume analysis results.""" + score: float confidence: str recommendation: str @@ -99,6 +123,8 @@ class AnalyzeResumeResponse(BaseModel): class CoverLetterRequest(BaseModel): + """Request model for generating a cover letter.""" + resume: Resume job_description: str company_name: Optional[str] | None = None @@ -107,6 +133,8 @@ class CoverLetterRequest(BaseModel): class CoverLetterResponse(BaseModel): + """Response model for a generated cover letter.""" + cover_letter: str word_count: int suggestions: list[str] | None = None diff --git a/frontend/README.md b/frontend/README.md index d1911c3..6ee67e8 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,20 +1,121 @@ -# React + Vite +# Frontend Folder & File Structure -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +## Recommended Structure -Currently, two official plugins are available: +The frontend is organized for scalability and maintainability. Follow these guidelines when adding new files or folders: -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +- **src/**: Main source code for the frontend React app. + - **components/**: Reusable UI components (e.g., buttons, forms, navbars). Each component should be in its own file, named in PascalCase (e.g., `MyComponent.jsx`). + - **pages/**: Top-level route components representing full pages (e.g., `HomePage.jsx`, `LoginPage.jsx`). + - **assets/**: Static assets such as images, fonts, or icons. + - **styles/**: CSS files for global styles and page/component-specific styles. Use a separate CSS file for each page or major component when possible. + - **specific-component/**: Styles specific to certain components (e.g., `resume-template.css`). +- **public/**: Static files served directly (e.g., `favicon.ico`, `robots.txt`). +- **App.jsx**: Main app component, sets up routing and layout. +- **main.jsx**: Entry point for React, renders the app. -## React Compiler +## Guidelines -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). +- Use clear, descriptive names for files and folders. +- Keep components small and focused; split into smaller components if needed. +- Place shared logic or hooks in a `hooks/` folder (create if needed). +- Place utility functions in a `utils/` folder (create if needed). +- Keep unrelated code separated by folder. +- Add a README.md to any new major folder to describe its purpose if it grows large. -## Expanding the ESLint configuration +This structure helps keep the codebase organized and easy to navigate as the project grows. +# The Method Frontend -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. +This is the frontend for **The Method**, a web application for resume building, AI-powered resume optimization, interview practice, and job search. +## Overview +- Built with **React** and **Vite** for fast development and hot module reloading. +- Modern, component-based architecture with dedicated pages for each major feature. +- Custom CSS and stylelint for consistent, accessible design. + +## Folder Structure + +```text +frontend/ +├── Dockerfile +├── index.html +├── package.json +├── vite.config.js +├── src/ +│ ├── App.jsx +│ ├── main.jsx +│ ├── assets/ +│ ├── components/ +│ │ ├── CallToAction.jsx +│ │ ├── ContactEmail.jsx +│ │ ├── FileUpload.jsx +│ │ ├── Footer.jsx +│ │ ├── Form.jsx +│ │ ├── HeroArea.jsx +│ │ ├── HomeStatistics.jsx +│ │ ├── HowItWorks.jsx +│ │ ├── NavBar.jsx +│ │ ├── Privacy.jsx +│ │ ├── RecommendProvr.jsx +│ │ ├── ResumePreview.jsx +│ │ └── Reviews.jsx +│ ├── pages/ +│ │ ├── AboutPage.jsx +│ │ ├── ContactPage.jsx +│ │ ├── DashboardPage.jsx +│ │ ├── DataPage.jsx +│ │ ├── FAQsPage.jsx +│ │ ├── FormPage.jsx +│ │ ├── HomePage.jsx +│ │ ├── LoginPage.jsx +│ │ ├── NewsPage.jsx +│ │ ├── PricingPage.jsx +│ │ ├── PrivacyPolicyPage.jsx +│ │ └── TermsOfServicePage.jsx +│ └── styles/ +│ ├── about-page.css +│ ├── contact-page.css +│ ├── dashboard-page.css +│ ├── data-page.css +│ ├── faq-page.css +│ ├── form-page.css +│ ├── home-page.css +│ ├── login-page.css +│ ├── news-page.css +│ ├── pricing-page.css +│ ├── privacy-policy-page.css +│ ├── styles.css +│ ├── terms-of-service-page.css +│ └── specific-component/ +│ └── resume-template.css +├── public/ +└── ... +``` + +## Development + +### Install dependencies +```bash +npm ci +``` + +### Run in development mode +```bash +npm run dev +``` + +### Linting +- **JSX:** `npm run lint` +- **CSS:** `npm run lint:css` +- **All:** `npm run lint:all` + +## Build for production +```bash +npm run build +``` + +## Docker +This frontend can be built and run using Docker. See the project root README for details. ## Attributions -Upload icons created by Ilham Fitrotul Hayat - Flaticon \ No newline at end of file +Upload icons created by Ilham Fitrotul Hayat - Flaticon \ No newline at end of file