{"id":50337249,"url":"https://github.com/saakeeb/hrinventory","last_synced_at":"2026-05-29T14:30:27.546Z","repository":{"id":343534578,"uuid":"1172477432","full_name":"saakeeb/hrinventory","owner":"saakeeb","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-10T18:17:19.000Z","size":105,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-10T23:57:43.650Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saakeeb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-04T10:59:41.000Z","updated_at":"2026-03-10T18:09:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/saakeeb/hrinventory","commit_stats":null,"previous_names":["saakeeb/hrinventory"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/saakeeb/hrinventory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saakeeb%2Fhrinventory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saakeeb%2Fhrinventory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saakeeb%2Fhrinventory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saakeeb%2Fhrinventory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saakeeb","download_url":"https://codeload.github.com/saakeeb/hrinventory/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saakeeb%2Fhrinventory/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33657690,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T14:30:26.852Z","updated_at":"2026-05-29T14:30:27.538Z","avatar_url":"https://github.com/saakeeb.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HR Inventory — Workforce System (Phase 1)\n\nA full-stack monorepo scaffold for the **HR Inventory** workforce management system.\n\n| Layer     | Stack                                                        | Port   |\n|-----------|--------------------------------------------------------------|--------|\n| Database  | PostgreSQL 15 (via Docker)                                   | `5432` |\n| Backend   | Express · TypeScript · `ts-node-dev` · JWT · WebSocket (`ws`) | `4000` |\n| Frontend  | Vite · React 18 · TypeScript · Tailwind CSS · React Query   | `5173` |\n\n---\n\n## Table of Contents\n\n- [Prerequisites](#prerequisites)\n- [Project Structure](#project-structure)\n- [Quick Start (Run Both Together)](#quick-start-run-both-together)\n- [Step-by-Step Setup](#step-by-step-setup)\n  - [1. Clone \u0026 Install](#1-clone--install)\n  - [2. Configure Environment Variables](#2-configure-environment-variables)\n  - [3. Start the Database](#3-start-the-database)\n  - [4. Start the Backend](#4-start-the-backend)\n  - [5. Start the Frontend](#5-start-the-frontend)\n- [Available Scripts](#available-scripts)\n- [Environment Variables Reference](#environment-variables-reference)\n- [Architecture Overview](#architecture-overview)\n\n---\n\n## Prerequisites\n\nMake sure the following tools are installed on your machine before proceeding:\n\n| Tool          | Minimum Version | Check Command         |\n|---------------|-----------------|-----------------------|\n| Node.js       | 18+             | `node -v`             |\n| npm           | 9+              | `npm -v`              |\n| Docker        | 24+             | `docker -v`           |\n| Docker Compose| v2+             | `docker compose version` |\n\n---\n\n## Project Structure\n\n```\nhrinventory/\n├── backend/                  # Express + TypeScript API server\n│   ├── src/\n│   │   ├── config/           # App config (port, DB URL, JWT secret)\n│   │   ├── database/         # DB connection utilities\n│   │   ├── middleware/        # Request logger, error handler\n│   │   ├── utils/            # Shared helpers\n│   │   └── server.ts         # Entry point\n│   ├── modules/              # Feature modules (auth, users, attendance)\n│   │   ├── auth/\n│   │   ├── users/\n│   │   └── attendance/\n│   ├── database/\n│   │   ├── migrations/       # SQL migration files\n│   │   └── seed/             # Seed data scripts\n│   ├── websocket/            # WebSocket server logic\n│   ├── docker-compose.yml    # PostgreSQL 15 service definition\n│   ├── .env.example          # Backend env template\n│   └── package.json\n│\n├── frontend/                 # Vite + React + Tailwind SPA\n│   ├── src/\n│   │   ├── App.tsx           # Root component \u0026 routing shell\n│   │   ├── router.tsx        # React Router definitions\n│   │   ├── AuthContext.tsx   # Global auth state (JWT)\n│   │   ├── axios.ts          # Pre-configured Axios instance\n│   │   ├── LoginPage.tsx\n│   │   ├── ProfilePage.tsx\n│   │   ├── ProfileForm.tsx\n│   │   ├── Layout.tsx\n│   │   ├── ProtectedRoute.tsx\n│   │   ├── lib/              # Shared utilities / hooks\n│   │   └── styles/           # Global CSS / Tailwind base\n│   ├── .env.example          # Frontend env template\n│   ├── vite.config.ts\n│   └── package.json\n│\n└── README.md\n```\n\n---\n\n## Quick Start (Run Both Together)\n\n\u003e **Recommended approach**: open **three terminal tabs** — one for each service.\n\n### Terminal 1 — Database (PostgreSQL via Docker)\n\n```bash\ncd backend\ndocker compose up -d\nsudo systemctl stop postgresql (Optional: if postgresql already exist)\n```\n\n### Terminal 2 — Backend (Express API)\n\n```bash\ncd backend\nnpm install          # first time only\ncp .env.example .env # first time only — then edit .env\nnpm run dev\n```\n\n### Terminal 3 — Frontend (Vite Dev Server)\n\n```bash\ncd frontend\nnpm install          # first time only\ncp .env.example .env # first time only\nnpm run dev\n```\n\nOnce all three services are running:\n\n| Service  | URL                          |\n|----------|------------------------------|\n| Frontend | http://localhost:5173         |\n| Backend  | http://localhost:4000         |\n| API Health Check | http://localhost:4000/health |\n\n---\n\n## Step-by-Step Setup\n\n### 1. Clone \u0026 Install\n\n```bash\n# Clone the repository\ngit clone \u003cyour-repo-url\u003e hrinventory\ncd hrinventory\n\n# Install backend dependencies\ncd backend \u0026\u0026 npm install \u0026\u0026 cd ..\n\n# Install frontend dependencies\ncd frontend \u0026\u0026 npm install \u0026\u0026 cd ..\n```\n\n---\n\n### 2. Configure Environment Variables\n\n#### Backend (`backend/.env`)\n\n```bash\ncd backend\ncp .env.example .env\n```\n\nOpen `backend/.env` and fill in the values:\n\n```env\nPORT=4000\nNODE_ENV=development\n\n# For local Docker Compose, use 'localhost' instead of 'db' for the host\nDATABASE_URL=postgres://postgres:postgres@localhost:5432/hrinventory\n\nJWT_SECRET=replace_this_with_a_strong_secret\n\n# Optional OAuth providers (leave blank to skip)\nGOOGLE_CLIENT_ID=\nGOOGLE_CLIENT_SECRET=\nAUTH0_DOMAIN=\nAUTH0_CLIENT_ID=\n```\n\n\u003e **Important:** When running the backend **outside** Docker (i.e., directly with `npm run dev`), use `localhost` as the DB host instead of `db`.\n\n#### Frontend (`frontend/.env`)\n\n```bash\ncd frontend\ncp .env.example .env\n```\n\n`frontend/.env` only needs one variable — it should already be correct:\n\n```env\nVITE_API_URL=http://localhost:4000\n```\n\n---\n\n### 3. Start the Database\n\nThe database runs as a Docker container. Start it from the `backend/` directory:\n\n```bash\ncd backend\ndocker compose up -d\n```\n\nVerify PostgreSQL is running:\n\n```bash\ndocker compose ps\n# You should see 'db' container with status: Up\n```\n\nTo stop PostgreSQL:\n\n```bash\ndocker compose down          # stop containers (data preserved)\ndocker compose down -v       # stop + destroy data volume\n```\n\n---\n\n### 4. Start the Backend\n\n```bash\ncd backend\nnpm run dev\n```\n\nThe backend starts with `ts-node-dev` (hot-reload on file changes). You should see:\n\n```\nBackend listening on http://localhost:4000\n```\n\nVerify it works:\n\n```bash\ncurl http://localhost:4000/health\n# → { \"status\": \"ok\" }\n```\n\n---\n\n### 5. Start the Frontend\n\n```bash\ncd frontend\nnpm run dev\n```\n\nVite will start the dev server and print:\n\n```\n  VITE v5.x.x  ready in Xms\n\n  ➜  Local:   http://localhost:5173/\n  ➜  Network: use --host to expose\n```\n\nOpen http://localhost:5173 in your browser.\n\n---\n\n## Available Scripts\n\n### Backend (`cd backend`)\n\n| Command          | Description                                 |\n|------------------|---------------------------------------------|\n| `npm run dev`    | Start dev server with hot-reload (`ts-node-dev`) |\n| `npm run build`  | Compile TypeScript to `dist/`               |\n| `npm start`      | Run compiled production build (`dist/server.js`) |\n| `npm run lint`   | Run ESLint on all `.ts` files               |\n| `npm run format` | Format codebase with Prettier               |\n\n### Frontend (`cd frontend`)\n\n| Command           | Description                                |\n|-------------------|--------------------------------------------|\n| `npm run dev`     | Start Vite dev server (HMR enabled)        |\n| `npm run build`   | Build production bundle to `dist/`         |\n| `npm run preview` | Serve the production build locally         |\n| `npm run lint`    | Run ESLint on `.ts` / `.tsx` files         |\n| `npm run format`  | Format codebase with Prettier              |\n\n### Docker (`cd backend`)\n\n| Command                     | Description                                 |\n|-----------------------------|---------------------------------------------|\n| `docker compose up -d`      | Start PostgreSQL in background              |\n| `docker compose down`       | Stop PostgreSQL (data preserved)            |\n| `docker compose down -v`    | Stop PostgreSQL and destroy volume (wipe DB)|\n| `docker compose logs -f db` | Follow PostgreSQL logs                      |\n\n---\n\n## Environment Variables Reference\n\n### Backend\n\n| Variable           | Default                                              | Required | Description                         |\n|--------------------|------------------------------------------------------|----------|-------------------------------------|\n| `PORT`             | `4000`                                               | No       | Port the Express server listens on  |\n| `NODE_ENV`         | `development`                                        | No       | Node environment                    |\n| `DATABASE_URL`     | —                                                    | **Yes**  | PostgreSQL connection string        |\n| `JWT_SECRET`       | `CHANGE_ME`                                          | **Yes**  | Secret for signing JWT tokens       |\n| `GOOGLE_CLIENT_ID` | —                                                    | No       | Google OAuth client ID              |\n| `GOOGLE_CLIENT_SECRET` | —                                                | No       | Google OAuth client secret          |\n| `AUTH0_DOMAIN`     | —                                                    | No       | Auth0 domain                        |\n| `AUTH0_CLIENT_ID`  | —                                                    | No       | Auth0 client ID                     |\n\n### Frontend\n\n| Variable       | Default                    | Required | Description                    |\n|----------------|----------------------------|----------|--------------------------------|\n| `VITE_API_URL` | `http://localhost:4000`    | **Yes**  | Base URL of the backend API    |\n\n\u003e All frontend env vars must be prefixed with `VITE_` to be accessible in the browser.\n\n---\n\n## Architecture Overview\n\n```\nBrowser\n  │\n  ▼\nVite Dev Server (localhost:5173)\n  │  HTTP/REST via Axios\n  │  (VITE_API_URL → localhost:4000)\n  ▼\nExpress API (localhost:4000)\n  │  ├─ GET /health\n  │  ├─ /auth routes   (JWT, Google OAuth, Auth0)\n  │  ├─ /users routes\n  │  ├─ /attendance routes\n  │  └─ WebSocket upgrade (ws)\n  │\n  ▼\nPostgreSQL 15 (localhost:5432)\n  └─ Docker volume: db_data\n```\n\n### Key Backend Files\n\n| File/Dir                         | Role                                           |\n|----------------------------------|------------------------------------------------|\n| `src/server.ts`                  | App bootstrap — Express setup, middleware, HTTP server |\n| `src/config/index.ts`           | Reads `.env` and exports typed config object   |\n| `src/middleware/request.logger`  | Logs every incoming HTTP request               |\n| `src/middleware/error.middleware`| Centralized error handling                     |\n| `modules/auth/`                  | Auth routes, JWT helpers, OAuth strategies     |\n| `modules/users/`                 | User CRUD                                      |\n| `modules/attendance/`            | Attendance records                             |\n| `websocket/`                     | WebSocket server for real-time features        |\n| `database/migrations/`           | Raw SQL migration scripts                      |\n| `database/seed/`                 | Seed data for development                      |\n\n### Key Frontend Files\n\n| File                   | Role                                                    |\n|------------------------|---------------------------------------------------------|\n| `src/main.tsx`         | React entry point — mounts `\u003cApp /\u003e` to the DOM        |\n| `src/App.tsx`          | Root component with `QueryClientProvider`               |\n| `src/router.tsx`       | All route definitions (React Router)                    |\n| `src/AuthContext.tsx`  | Global auth state (token storage, user info)            |\n| `src/axios.ts`         | Axios instance pre-configured with `VITE_API_URL`       |\n| `src/ProtectedRoute.tsx` | HOC that redirects unauthenticated users to login     |\n| `src/LoginPage.tsx`    | Login form UI                                           |\n| `src/ProfilePage.tsx`  | User profile view                                       |\n\n---\n\n## Troubleshooting\n\n| Problem | Solution |\n|---------|----------|\n| `ECONNREFUSED` on backend startup | Database isn't running — run `docker compose up -d` first |\n| `DATABASE_URL` host `db` not resolving | Change `db` → `localhost` in `backend/.env` when running outside Docker |\n| Frontend shows blank page | Check `VITE_API_URL` in `frontend/.env` points to `http://localhost:4000` |\n| Port `4000` already in use | Kill the conflicting process: `lsof -ti:4000 \\| xargs kill` |\n| Port `5173` already in use | Kill the conflicting process: `lsof -ti:5173 \\| xargs kill` |\n| `JWT_SECRET` default warning | Set a strong secret in `backend/.env` — never commit real secrets |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaakeeb%2Fhrinventory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaakeeb%2Fhrinventory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaakeeb%2Fhrinventory/lists"}