Local development
git clone https://github.com/Every-Man-A-Warrior/emaw-web-app.git
cd emaw-web-app
git checkout develop
npm install
npx vite --port 5174 # the website owns 5173; the backend allows http://localhost:5174
npm run dev runs vite --host on the default port; pass --port 5174 (or add it to .env.development.local via VITE_PORT if you prefer) so the website and web app can run together and the dev backend's CORS and hand-off origin lists accept you.
Environment
The build reads the committed .env.development (used by the develop deploy with vite build --mode development) or .env.production. Override per machine in .env.development.local (gitignored).
| Variable | Purpose |
|---|---|
VITE_BACKEND_URL | Backend base URL with trailing slash; the app throws if unset |
VITE_WEBSITE_URL | The website, no trailing slash. Sign-up links go to <website>/account/sign-up?next=app. Empty keeps the app's own /signup |
VITE_GOOGLE_CLIENT_ID | Google button on /login; your origin must be authorised on the web client. Empty hides it |
VITE_HMR_HOST | Only for hot reload through a tunnel such as ngrok |
See Configuration.
Scripts
| Script | Does |
|---|---|
npm run dev | Vite dev server (--host) |
npm run build | vite build → dist/ |
npm run preview | serve dist/ |
npm run lint | ESLint (flat config; prop-types off) |
Testing the hand-off locally
- Run the backend (dev tunnel or
localhost:8000), the website on 5173 withVITE_EMAW_APP_URL=http://localhost:5174, and the web app on 5174 withVITE_WEBSITE_URL=http://localhost:5173. - Sign in on the website, open
/app. You should land in the web app signed in, on/homeor thenextpath. - Replay the same URL: the code is single-use, so you get a toast and
/login.
Backend origins: localhost:5174 is in the development APP_ALLOWED_ORIGINS; for anything else add APP_EXTRA_ORIGINS in the backend .env. Full matrix: docs/accounts-sandbox.md.
Conventions
- Every API call is a small function in
src/utils/that imports the shared axios instance fromsrc/store/AxiosInstance.jsx. Do not callaxiosdirectly. - Requests that are sign-ins pass
{skipAuthRefresh: true}so a 401 never triggers the interceptor's refresh-or-logout. - Keep the mobile app and web app feature-compatible: the curriculum JSON (
src/constants/bookInfo.json,locales/*/book_info.json) must match the backend's exported data.