The web app both sides of the marketplace use: clients posting work and contractors bidding on it. It's a React + TypeScript single-page app built with Vite, styled with Tailwind and DaisyUI. All of its data comes from the backend through the API gateway.
One thing that trips people up: the Vite project root is this folder
(e-contractor/), but the app's source lives in frontend/src/. Run every
command from here, not from frontend/.
- Node.js 18+
- The backend running, or at least the API gateway on port 3000
npm install
npm run dev # dev server on http://localhost:5173
npm run build # production build
npm run preview # serve the production build locallyPoint the app at the gateway:
VITE_GATEWAY_API_URL=http://localhost:3000/api
Vite also reads .env.local and layers it on top of .env, which is handy for
per-machine overrides (a DevTunnels URL when you're testing on a phone, for
example). Restart the dev server after changing either file.
frontend/src/
pages/ route screens, lazy-loaded
components/ shared UI
hooks/ React Query data hooks (useAuth, useBids, useProfile, ...)
services/ API clients (authApi, bidApi, profileApi, ...)
config/ axios and gateway setup
constants/ shared option lists (trades, specialties)
graphql/ Apollo client for the admin GraphQL endpoint
A couple of conventions the codebase leans on:
- Data fetching lives in the React Query hooks under
hooks/. Components call a hook, they don't fetch on their own. - Every HTTP call goes through the exported API clients in
services/. Those wrap axios with cookie auth, automatic token refresh, and retry, so reaching for rawaxiosskips all of that. Use the clients. - Pages are lazy-loaded and wrapped in an error boundary, so a broken screen fails on its own instead of taking the app down.
There's more background in frontend/QUICK_START.md and
frontend/IMPROVEMENTS.md.