MPA strategy: public site vs Angular app¶
Decision¶
WorkWingman runs two front-end strategies on purpose:
| Product surface | Architecture | Primary job |
|---|---|---|
| Public content site | Multi-page app: ASP.NET Razor Pages + htmx | Marketing, SEO, CMS content, public info |
| Desktop app product | Angular SPA | Logged-in product experience, rich client state |
Standing rule: htmx + Razor for content sites, CMS, and admin; Angular SPA for the desktop app. Do not collapse both into one SPA stack.
Why MPA/htmx for the content site¶
Speed¶
- Server-rendered HTML means visitors get usable content on first response.
- No large Angular bootstrap tax for brochure/content pages.
- htmx adds progressive enhancement (e.g. boosted public nav) without shipping a full SPA runtime for every content hit.
SEO¶
- Search engines and social previews consume real HTML from the server.
- CMS content is rendered server-side, so rankings and link previews do not depend on client-side hydration of an empty shell.
- Stable multi-page URLs match how content and marketing sites are discovered and indexed. TODO(verify): current indexing/analytics baseline vs SPA alternative.
Cost¶
- Cheaper to operate for mostly-read content: render page, cache at edge (Cloudflare), serve.
- Content edits flow through WingCMS (GCS as source of truth)—writers and operators change content without a full app release cycle for every copy tweak.
- Smaller public JS surface than an Angular SPA for the same marketing/content job → less frontend complexity to staff and maintain on the public lane.
- Hosted as a Cloud Run service behind Cloudflare; scale-to-demand fits content traffic better than always-on SPA infra assumptions. TODO(verify): comparative Cloud Run cost model vs SPA hosting path.
Why Angular SPA stays for the app¶
- The product needs rich client state, complex UI flows, and app-like navigation that SPA frameworks are built for.
- Conflating app UX with the public site would either:
- over-engineer the marketing/content site, or
- under-serve the product UX.
- Clear boundary: content/admin/CMS = MPA; product app = Angular.
Security posture (business relevance)¶
- Strict CSP reduces XSS and third-party script risk on the public brand surface.
- Tradeoffs accepted: no Angular-style inlineCritical CSS; some deferred CSS onload patterns are incompatible with nonce CSP.
- Admin deliberately opts out of htmx boost so admin forms are not accidentally enhanced in ways that break under CSP or create unexpected form behavior. That is an operational risk control, not a polish omission.
Version and delivery posture¶
- htmx 2.0 migration complete (WING-207 on
wt/WT-e33f/WING-207-mpa). - htmx 4.x beta exists upstream (WING-244/245) and is not adopted—stability over bleeding edge on the revenue-facing content site.
- New site work should base on the WING-207 MPA line to avoid unrelated-histories merge risk from older site lanes.
What “good” looks like¶
- Public pages load as HTML with CMS content already in place.
- Public navigation stays fast via htmx boost where intentional.
- Admin remains unboosted and predictable.
- Deploy path stays Cloud Run + Cloudflare (see release-pipeline doc).
- Angular investment stays on the product app, not re-spent rebuilding the content site as an SPA.
Non-goals¶
- Replacing the public MPA with Angular “for consistency.”
- Adopting htmx 4 beta on the public site without a deliberate product decision.
- Inventing a single universal frontend for both marketing content and the desktop product.
Summary¶
MPA/htmx wins on the content site for first-paint speed, SEO-friendly HTML, lower content-ops cost, and a smaller public attack/maintenance surface. Angular SPA wins on the product app for interactive depth. The split is strategy, not temporary tech debt.