# MIM4U (mim4u.org) — Technical UX/UI Review & Punch List **Last Updated:** 2026-02-26 **Document Version:** 1.0 **Status:** Active — Dev handoff **Context:** Hosted LXC content — VMID 7810 (mim-web-1), VMID 7811 (mim-api-1), NPMplus proxy --- ## Scope This document captures a technical UX/UI review of **mim4u.org** (Miracles in Motion) based on publicly indexable content. The site is largely JS-rendered (client-rendered), so the review focuses on patterns that commonly affect UX on modern marketing/nonprofit builds. It is intended as a **prioritized punch list** for the dev team working on the **miracles_in_motion** codebase and the LXC-hosted deployment. **Hosting (this repo):** | Asset | Detail | |-------|--------| | **Web frontend** | VMID 7810 (mim-web-1) — Nginx + static/SPA | | **API backend** | VMID 7811 (mim-api-1) — Azure Functions (port 3001) | | **Domains** | mim4u.org, www.mim4u.org, secure.mim4u.org, training.mim4u.org | | **Proxy** | NPMplus → `http://192.168.11.37:80` (see [NPMPLUS_SERVICE_MAPPING_COMPLETE.md](./NPMPLUS_SERVICE_MAPPING_COMPLETE.md)) | | **App source** | Submodule: [miracles_in_motion](https://github.com/Order-of-Hospitallers/miracles_in_motion) | **Related docs:** - [MIM4U_502_ERROR_RESOLUTION.md](./MIM4U_502_ERROR_RESOLUTION.md) — 502 resolution (nginx/service on 7810) - [MIM4U_FIRST_PARTY_ANALYTICS.md](./MIM4U_FIRST_PARTY_ANALYTICS.md) — First-party `/api/events` endpoint for ad-blocker-resistant analytics - [NPMPLUS_SERVICE_MAPPING_COMPLETE.md](./NPMPLUS_SERVICE_MAPPING_COMPLETE.md) — Domain → VMID mapping --- ## What’s Working (UX That’s Technically Sound) - **Clear information architecture + task-first nav**: Top-level items (Stories, Volunteers, Corporate, Get Help, Portals, Donate) map cleanly to user intents. - **Strong primary CTAs above the fold**: Donate now, Volunteer, Read stories — reduce decision friction and support conversion. - **Trust + transparency blocks**: “Where your donation goes (85/10/5)”, “Average grant: $48 / $72”, partners list, impact-report mention — good for credibility and SEO when implemented as real text (not only images). - **Process clarity**: “Designed with counselors… verified same-day… approved within 24 hours… no uploads required” — step-by-step flow that can reduce form abandonment. --- ## Technical UX Risks (Common on Client-Rendered Builds) ### 1) Performance (Core Web Vitals) - **LCP risk**: Hero sections often use large background images/video + web fonts; unoptimized they cause “blank screen” lag on mobile/slow networks. - **CLS risk**: Late-loading fonts, cookie banners, or impact counters can shift layout (conversion-negative). - **INP risk**: Heavy script bundles (analytics, donation widgets, sliders) can delay taps/scroll. **Actions:** - Hero image: responsive (`srcset`), compressed, and preloaded if it’s the LCP element. - Defer non-critical JS (chat, A/B, extra trackers). - Use `font-display: swap` and consider self-hosting fonts. ### 2) Accessibility (WCAG/ADA) From the visible structure (multiple CTAs, sections, cookie banner): - Keyboard: full tab flow through Donate / Get Help / Portals without traps. - Visible focus states on links/buttons (especially CTAs). - One H1, logical H2/H3. - Color contrast on hero text/buttons. - Cookie banner: fully operable by keyboard + screen reader; no blocking without focus management. **Actions:** - Add “Skip to content” link. - Ensure CTAs have accessible names (avoid repeated “Learn more” without context). - ARIA labels on nav/menu toggles (mobile). ### 3) Forms / “Get Help” Workflow Copy promises speed and dignity (“one-page referral, no uploads required”). Technically this depends on: - Inline, specific validation (not generic red banners). - Auto-save / resilience on mobile. - Spam protection that doesn’t punish legitimate users (avoid hostile CAPTCHAs). - Confirmation loop (“we confirm support reached the student”) — ensure privacy disclosures reflect data handling. ### 4) Security & Privacy (Especially “Portals”) Portals imply authenticated access: - HTTPS everywhere + HSTS. - Strong session cookie flags: `HttpOnly`, `Secure`, `SameSite`. - Content Security Policy (CSP) to reduce XSS (e.g. from embedded donation tools). - No PII in URLs/query strings (referrals, student needs). - Cookie choices must persist; don’t load marketing tags before consent. ### 5) SEO + Discoverability Key content is client-rendered; indexing can be inconsistent. Homepage text is indexable — maintain and improve: - Prefer SSR or static generation for public pages where feasible. - Clean metadata (title/description per page/section). - Structured data: Organization + DonateAction. - “Impact report” as a crawlable page (not only a modal). --- ## High-Impact Quick Wins 1. **Run Lighthouse on mobile** and fix: - LCP image optimization + preload - Reduce unused JS - Eliminate layout shift (banner/fonts) 2. **Accessibility pass**: keyboard flow, focus visibility, heading hierarchy. 3. **CTA instrumentation**: track Donate / Get Help / Volunteer separately; verify events fire with ad blockers in mind. 4. **Portals hardening**: CSP, secure cookie configuration, rate limiting on auth endpoints. --- ## Concrete Technical Checklist (Dev Handoff) | Area | Target / Requirement | |------|----------------------| | **Core Web Vitals** | LCP < 2.5s, CLS < 0.1, INP < 200ms (mobile) | | **Images** | Responsive, compressed, lazy-load below fold | | **Fonts** | `font-display: swap`, limit variants, preconnect if external | | **JS** | Defer non-critical, minimize third-party scripts | | **A11y** | Skip link, focus states, ARIA labels, contrast, form error messaging | | **Security** | HSTS, CSP, secure cookies, no PII in URLs, audit third-party embeds | | **SEO** | SSR/SSG for public pages where possible, metadata, sitemap/robots, schema.org Organization | --- ## Implemented (2026-02-26) - **A11y**: Skip-to-content link (focus-only, targets `#content`), focus-visible on hero CTAs and mobile nav links, ARIA labels on Donate/Get Help. - **SEO**: Canonical/OG URLs and schema.org base URL set to `https://mim4u.org`; DonateAction JSON-LD added alongside Organization. - **Performance**: Font preload for Inter (critical weights) in `index.html`; preconnect already present; `display=swap` in font URL. - **Deploy (proxmox)**: `scripts/deployment/deploy-transaction-mirror-and-pmm-pool-after-txpool-clear.sh` retries pool deploy on “Replacement transaction underpriced” with gas bump (up to 4 attempts) and short wait after first tx. - **www.mim4u.org**: Added to `update-npmplus-proxy-hosts-api.sh` (same backend as mim4u.org). Nginx server block includes `server_name mim4u.org www.mim4u.org ...` so both hosts are served. Optional: NPMplus Redirect for www → apex. - **HSTS/CSP**: Nginx snippet in MIM4U_502_ERROR_RESOLUTION.md adds X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy, Content-Security-Policy. HSTS enabled via NPMplus SSL tab when terminating HTTPS. - **Cookie consent**: Banner persists choice in `localStorage` (`mim_cookie_consent`); analytics/tracking only run when consent is `accept` (see `src/utils/analytics.ts`). Cookie banner is keyboard-accessible and links to legal/cookie policy. - **Get Help form**: Inline, field-level validation with specific error messages; draft auto-saved to `localStorage` (debounced); draft cleared on successful submit; `aria-invalid` and `aria-describedby` for errors. - **CTA instrumentation**: Hero Donate and Get Help fire `cta_clicked` with `button` and `location`; analytics only run when cookie consent is “accept”. - **SEO**: `robots.txt` and `sitemap.xml` use canonical `https://mim4u.org`; sitemap lists main routes (/, #/donate, #/request-assistance, #/volunteers, #/stories, #/legal). - **502 fix script**: `scripts/mim4u-install-nginx-and-fix-502.sh` installs nginx on VMID 7810, applies security headers + SPA + /api proxy; run from host that can SSH to Proxmox. --- ## Tech stack (documented) - **Frontend**: Vite + React + TypeScript; hash-based routing (`#/donate`, `#/request-assistance`, etc.); Tailwind CSS; Framer Motion. - **Backend**: Azure Functions (API on VMID 7811, port 3001). - **Hosting**: Static build served by nginx on VMID 7810 (LXC); NPMplus reverse proxy; optional Cloudflare Tunnel. ## Next Steps for Dev 1. **Lighthouse**: Run Lighthouse (mobile) and attach report JSON or screenshots to turn this into a **prioritized punch list with exact fixes** (what to change, where, how to validate). 2. **Infra**: Run `./scripts/mim4u-install-nginx-and-fix-502.sh` from a host that can SSH to Proxmox (r630-02) to install nginx on VMID 7810 and apply config — see [MIM4U_502_ERROR_RESOLUTION.md](./MIM4U_502_ERROR_RESOLUTION.md). --- ## Further recommendations and suggestions ### Performance & Core Web Vitals - **Lighthouse (mobile)** Run regularly; fix LCP (hero image `srcset`/preload), CLS (reserve space for cookie banner/fonts), INP (reduce main-thread work). See [Concrete Technical Checklist](#concrete-technical-checklist-dev-handoff) for targets. - **Self-host fonts** Consider serving Inter (or critical subset) from your origin to avoid Google Fonts latency and improve LCP; keep `font-display: swap`. - **Defer non-critical JS** Lazy-load or defer chat widgets, A/B scripts, and non-essential trackers so they don’t block INP. - **Images** Use `LazyImage` (or equivalent) with `sizes`/`srcset` for any hero or above-the-fold images; compress and prefer modern formats (e.g. WebP with fallback). ### SEO & discoverability - **Impact report as a real page** Add a crawlable route (e.g. `#/impact` or `#/impact-report`) and link “See the impact report” to it; add to sitemap. Avoid impact content only in a modal or PDF link so crawlers and users get a proper page. - **SSR/SSG (longer-term)** For key public pages (home, donate, get help, impact), consider SSR or static generation to improve indexing and first-paint; Vite SSR or a static export for critical routes is one option. - **Structured data** Organization and DonateAction are in place; add `WebPage` or `FAQPage` where it fits (e.g. Get Help or Legal). ### Forms & Get Help workflow - **Spam protection** Add a lightweight mechanism (e.g. honeypot field, or time-based check) so the form isn’t trivial to bot; avoid hostile CAPTCHA for school/counselor users. - **Confirmation & privacy** Ensure legal/cookie policy and Get Help copy clearly state how “we confirm support reached the student” works and where data is stored/processed; keep PII out of URLs and query params. - **Offline / resilience** Consider a simple “Save draft” affordance in addition to auto-save, and a clear message if submit fails (retry, contact number). ### Security & Portals - **Session cookies** For Portals (and any auth), use `HttpOnly`, `Secure`, and `SameSite=Lax` (or `Strict`) on session cookies; set at the API/auth layer (Azure Functions / Entra config or backend). - **Rate limiting** Apply rate limits on `/api/*` and auth endpoints (e.g. login, token). With **Cloudflare** in front: use WAF/custom rules (e.g. rate limit /api/ and auth paths). With **LXC/nginx only**: add `limit_req_zone` / `limit_req` in nginx for `/api/` and proxy to API. - **CSP** Nginx and staticwebapp.config already send security headers; keep CSP tight and avoid broad `unsafe-inline`/`unsafe-eval` where possible (may require build-time nonce or hashes for scripts). ### Analytics & instrumentation - **Volunteer CTA** Add `cta_clicked` (or equivalent) for “Volunteer” / “Volunteers” in nav and hero so Donate, Get Help, and Volunteer are tracked consistently; keep respecting cookie consent. - **Events with ad blockers** Document or test that key events (donation, form submit, CTA clicks) still fire when analytics is blocked (e.g. fallback to server-side or minimal first-party logging) so funnels are measurable. ### Operations & hosting - **Deploy real app to 7810** After nginx is in place, build the MIM4U frontend and deploy to `/var/www/html` (or the path nginx uses) so the live site replaces the placeholder. - **Backup** Back up nginx config and `/var/www/html` (or app deploy path) on 7810; include in any host/container backup runbook. - **Health check** Add a simple health URL (e.g. `/health` or `/.well-known/health`) that returns 200 for monitoring or load balancers; optional JSON with version or build id. - **Cloudflare (optional)** If mim4u.org is behind Cloudflare: use Full (strict) SSL, WAF rate limits for `/api/`, cache static assets; see `miracles_in_motion/docs/deployment/CLOUDFLARE_SETUP.md` for patterns. ### General best practices - **Repo-wide** Security, backups, monitoring, and script patterns in [OPTIONAL_RECOMMENDATIONS_INDEX.md](../OPTIONAL_RECOMMENDATIONS_INDEX.md) and [RECOMMENDATIONS_AND_SUGGESTIONS.md](../10-best-practices/RECOMMENDATIONS_AND_SUGGESTIONS.md) apply to MIM4U hosting (credentials, backups, monitoring, testing). Run `./scripts/mim4u-backup-7810.sh` periodically to back up nginx + app on 7810. - **Cloudflare checklist (optional)** When using Cloudflare in front of mim4u.org: Full (strict) SSL; WAF rate limit for `/api/` (e.g. 100 req/min); cache static assets; see `miracles_in_motion/docs/deployment/CLOUDFLARE_SETUP.md`. - **Lighthouse** Run performance audits where Chrome is available: `npm run lighthouse` (headless) or `npm run lighthouse:local` (interactive). In environments without Chrome (e.g. WSL without Chrome), run from a host with Chrome or use CI; fix any LCP/CLS/INP issues reported. --- **Source:** External technical UX/UI review of mim4u.org (publicly indexable content). **Hosting context:** Proxmox LXC — VMID 7810 (mim-web-1), VMID 7811 (mim-api-1); NPMplus; miracles_in_motion submodule.