Skip to main content

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).

VariablePurpose
VITE_BACKEND_URLBackend base URL with trailing slash; the app throws if unset
VITE_WEBSITE_URLThe 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_IDGoogle button on /login; your origin must be authorised on the web client. Empty hides it
VITE_HMR_HOSTOnly for hot reload through a tunnel such as ngrok

See Configuration.

Scripts​

ScriptDoes
npm run devVite dev server (--host)
npm run buildvite build → dist/
npm run previewserve dist/
npm run lintESLint (flat config; prop-types off)

Testing the hand-off locally​

  1. Run the backend (dev tunnel or localhost:8000), the website on 5173 with VITE_EMAW_APP_URL=http://localhost:5174, and the web app on 5174 with VITE_WEBSITE_URL=http://localhost:5173.
  2. Sign in on the website, open /app. You should land in the web app signed in, on /home or the next path.
  3. 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 from src/store/AxiosInstance.jsx. Do not call axios directly.
  • 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.