A full-stack, from-scratch implementation of the UW-Madison CS571 — Building User Interfaces assignment sequence: a course-style REST API server, a React web client, and a React Native (Expo) mobile client, all built around BadgerChat — part of a csdiy.wiki full-catalog build.
CS571 teaches modern UI engineering by having students build BadgerChat, a multi-chatroom forum, first as a React web app and then as a React Native mobile app, both talking to a course REST API with JWT authentication. This repository implements the whole stack independently and runs entirely on one machine with no external services:
packages/server— the BadgerChat REST API (Express + JWT + bcrypt), faithful to the CS571 F23 HW6 (web, httpOnly-cookie JWT) and HW9 (mobile, bearer-token JWT) contracts. In-memory data store (10 seeded chatrooms, rolling 100-message window, 25/page pagination).packages/web— the React (Vite) client: components, hooks,react-routerrouting, auseAuthcontext, forms, fetch, pagination, register/login/logout, and a BadgerBook directory. Covers the skills of HW3–HW6.packages/mobile— the React Native (Expo) client: native-stack navigation,FlatList,TextInputforms,AsyncStorage-persisted sessions, and the bearer-token API client. Covers the skills of HW7–HW9.
79 automated tests pass across the three packages, plus a live end-to-end
API smoke test and a real in-browser run. Full logs in results/.
| Package | Test runner | Suites | Tests | What it verifies |
|---|---|---|---|---|
| server | jest + supertest | 4 | 34 | every endpoint, auth, pagination, 400/401/404/409/413 paths, JWT + bcrypt, ownership checks |
| web | vitest + React Testing Library | 7 | 24 | API client, auth context, forms, message list, delete-own, routing, BadgerBook filtering |
| mobile | jest-expo + React Native Testing Library | 6 | 21 | API client, AsyncStorage session persistence, screens, FlatList, forms, delete-own |
| Total | 17 | 79 |
Additional real-run evidence:
- Live API smoke test — 10/10 steps (
results/api-smoke.txt): boots the Express server and drives register → whoami → post → read → delete over HTTP, asserting the unauthenticated and out-of-range rejections too. - Web production build (
results/web-build.txt):vite buildtransforms 46 modules (gzip JS 57.3 kB). - Live browser verification: the built React app + API were served on one
origin and driven headlessly — registering a user and posting a message
through the real API. The rendered DOM
(
results/web-ui-authenticated.html, CSS inlined — open it in a browser) shows the logged-in header, the New post form, and the user's own message carrying a Delete control; the network trace (results/web-ui-network.txt) shows every request returning 200 OK.
The course's homework skills, grounded from the CS571 F23 curriculum and API docs:
- HW2/HW3 — BadgerBook — state, controlled inputs, list rendering + filtering (web
BadgerBookPage) - HW4/HW5 — React components & hooks —
useState/useEffect/useContext, customuseAuth, routing - HW6 — BadgerChat (web) — fetch from the REST API, JWT auth (register/login/logout via httpOnly cookie), post/delete, pagination
- HW7/HW8 — React Native basics — Expo app, navigation,
FlatList,TextInputforms - HW9 — BadgerChat (mobile) — bearer-token JWT,
AsyncStoragesession, post/delete, pagination - HW11/HW12 — the backend — the BadgerChat REST API itself (Express + JWT + bcrypt) with the full HW6/HW9 contract
cs571-react-native/
├── packages/
│ ├── server/ # BadgerChat REST API (Express + JWT + bcrypt)
│ │ ├── src/ # app, store, auth, seed, server
│ │ ├── scripts/ # smoke.js (e2e), serve-web.js (static + API)
│ │ └── tests/ # 34 jest + supertest tests
│ ├── web/ # React + Vite client
│ │ └── src/ # api, context, components, pages, __tests__ (24 vitest)
│ └── mobile/ # React Native + Expo client
│ ├── src/ # api, context, components, screens
│ └── __tests__/ # 21 jest-expo + RNTL tests
├── results/ # measured evidence (test logs, smoke, build, browser run)
├── LICENSE · README.md · package.json (npm workspaces)
Requires Node 18+ (developed on Node 22). From the repo root:
# --- Server (BadgerChat API) ---
cd packages/server && npm install
npm test # 34 jest + supertest tests
npm run smoke # live 10-step end-to-end API smoke test
npm start # serve the API on http://localhost:53710
# --- Web client (React + Vite) ---
cd ../web && npm install
npm test # 24 vitest + React Testing Library tests
npm run build # production build -> dist/
npm run dev # dev server on http://localhost:5173 (proxies /api -> :53710)
# --- Single-origin preview (built web + API together) ---
cd ../web && npm run build
cd ../server && npm run serve:web # http://localhost:53730
# --- Mobile client (React Native + Expo) ---
cd ../mobile && npm install
npm test # 21 jest-expo + React Native Testing Library tests
npm start # Expo dev server (open in Expo Go / simulator)On this machine
npmis invoked as usual; dependencies and caches live underD:and nothing is installed toC:.
- Server:
npm --workspace packages/server test→Tests: 34 passed(results/server-tests.txt);npm run smoke→ALL PASS(results/api-smoke.txt). - Web:
npm --workspace packages/web test→Tests 24 passed(results/web-tests.txt);npm run buildsucceeds (results/web-build.txt); verified live in a browser (results/web-ui-*). - Mobile:
npm --workspace packages/mobile test→Tests: 21 passed(results/mobile-tests.txt). Run serially (jest --runInBand) so the RN/Expo transform doesn't starve parallel workers.
A one-line summary of every number lives in
results/measured-results.txt.
- Server: Node.js, Express 4,
jsonwebtoken(HS256),bcryptjs,cookie-parser,cors; jest + supertest. - Web: React 18, Vite 5, React Router 6; Vitest + React Testing Library + jsdom.
- Mobile: React Native 0.74 / Expo SDK 51, React Navigation (native-stack),
@react-native-async-storage/async-storage; jest-expo + React Native Testing Library.
- Designing one REST API that serves both auth models the course uses — an
httpOnly-cookie JWT for the web app and an
Authorization: BearerJWT for mobile — behind a shared router with anX-CS571-IDgate. - React data-flow: a
useAuth/useBadgercontext overuseContext, effect-driven fetching keyed on route params, and ownership-aware delete controls. - React Native equivalents:
FlatList,TextInput, and session persistence throughAsyncStorage, tested without a device via jest-expo mocks. - Testing UIs for real: React Testing Library / RNTL queries by role and label,
mocked
fetch/modules, and a live browser + HTTP smoke test for end-to-end proof.
Based on the assignments of CS571 — Building User Interfaces at the University of Wisconsin–Madison (course site: https://cs571.org/). BadgerChat, the chatroom names, and the API contract are the course's; this repository is an independent educational reimplementation that talks to its own local server, not the course's hosted API. All course materials belong to their original authors. Original code here is released under the MIT License.