Design Review ยท Office Hours

Member Portal Modernization

Prospects call the member portal outdated โ€” and it cost named deals. We drove the live portal, captured every screen, and traced the look back to its root cause. Here's what's actually wrong and the safe path to fix it.

Driven live on demo.raklet.net ๐Ÿ“… 2026-06-05 ๐Ÿงฑ Root cause: Bootstrap v3.4.1 (2013) ๐Ÿ“Š Priorities ranked by App Insights traffic ๐Ÿ“ธ 13 screens ยท desktop + mobile
โœ…
The verdict

It's a reskin, not a rebuild.

The "outdated / broken" perception is dominated by design-token and component issues โ€” empty-state badges, unstyled dropdowns, dated chrome โ€” that we can fix without touching the markup your customers' custom CSS/JS depends on. The underlying structure (sidebar + cards + a real settings form) is sound and already close to the bettermode model.

~65%of "outdated" is token-layer
(fixable, no DOM change)
3.5worst screen (Profile /10)
the most-viewed one
6.5best screen (Settings /10)
proves the team can do clean
2โ€“4 wkPhase 1 (appearance only)
low blast radius
Baseline

Where each screen scores today

A designer's-eye rating per screen. These are the baselines we measure the redesign against โ€” the goal for Phase 1 screens is +3 or โ‰ฅ8/10.

Profile /App/Profile
3.5
Feed / Home
4.0
Payments
4.0
Events
4.0
Login
6.0
Settings / Profile
6.5
Grounded in traffic, not taste

What members actually use

App Insights, 30 days, all orgs. Bar = share of portal page views. Color = current design score (red = worst). High traffic + low quality = fix first.

Search #1
21.0%
Profile #2 ยท 3.5/10
19.9%
Feed #3 ยท 4.0/10
14.4%
Members #4 ยท ~5/10
6.8%
Payments #5 ยท 4.0/10
5.4%
Membership #6
~9%*
Settings #7 ยท 6.5/10
4.2%
Messages #9
3.0%

Top 3 = ~55% of all portal views

Search + Profile + Feed carry the majority of member eyeballs. Top 5 โ‰ˆ 67%. Fix these and the global token layer, and most members feel the change.

The honest correction

Search is the #1 page and was missed in the first pass. Messages is only 3% โ€” not a Phase-1 priority. Profile being #2 AND worst-scoring confirms it as the anchor.

* Membership = create + view combined. Counts aggregate all orgs and may include bot/monitoring traffic; client_IP is anonymized so per-user dedup wasn't possible. Directional, not exact โ€” a GA4 engaged-sessions cross-check would tighten it.

Ranked by impact รท effort

The findings that matter

1

Empty states are styled as red error alarms

On Profile and Payments, empty fields render as red No Records / Missing / No data badges. The most-viewed member screen looks broken and error-filled when the data is simply empty. Biggest perceived-quality jump per hour: swap red alarms for neutral "Add your work history" prompts.

โœ“ Token / component onlyโœ“ No markup changeDo this first
2

Clashing surfaces & barren cards

A yellow contact callout fights the white cards; Payments is four oversized cards each holding one line of "No Records" โ€” vast dead space. One consistent surface + card system with a real type scale fixes the "empty and unfinished" feel.

โœ“ Token / component only

Note: an earlier draft flagged a "dual nav." That dark icon rail is the admin panel, only visible to org admins โ€” members never see it. Retracted.

3

Unstyled native dropdowns & inconsistent components

Raw browser <select> menus (events filter, settings) are the loudest "unfinished" signal. Badges mix outline and solid pills; surfaces clash (a yellow contact callout against white cards). One consistent component set fixes all of it.

โœ“ Token / component only
4

Bootstrap-3 chrome throughout

Flat pale-blue bars, hard 1px card borders, 2013-era link blue, weak type scale, oversized blocky headers, and large dead-space gaps. This is the framework's 2013 default aesthetic โ€” exactly what reads as "old."

โœ“ Variable / token overrides
The evidence

What we actually saw

Captured headless against the live portal. Annotations call out the specific issues.

Top-traffic screens (Search #1, Members #4 โ€” the ones the first pass missed)

Search results
#1 ยท 21%YELLOW BOXSearch. The most-visited page is a thin results wrapper; empty state is the same clashing yellow callout.
Members directory
#4 ยท 7%DECENT GRIDMembers. Core community screen โ€” bettermode-like card grid, but empty avatars + dated hard-bordered cards.

Profile โ€” the worst offender (#2 traffic, lowest score)

Profile desktop
RED ALARMSADMIN-ONLY RAILDesktop. Empty fields shown as red "No Records / Missing / No data". (The dark rail is the admin panel โ€” members don't see it; captured here as an owner.)
Profile mobile
RED ALARMSMobile. Same alarm badges; a clashing yellow contact callout. Bottom tab bar is the one modern touch.

Payments & Settings โ€” barren vs. the one good screen

Payments desktop
DEAD SPACEPayments. Four oversized cards, each one line of "No Records". Massive empty space, blocky headers.
Settings desktop
STRONGESTSettings. Proper sub-nav, labeled form, Save CTA. Proof the team can build clean โ€” the gap is tokens, not capability.

Public surfaces โ€” Feed, Events, Login

Feed desktop
Feed. Barren, identical gated cards; weak nav contrast; debug-looking test titles.
Events desktop
NATIVE SELECTEvents. Unstyled dropdown, empty gray image placeholders, mixed badge styles.
Login desktop
~6/10Login. Cleanest of the public pages, but generic-2015: hard border, flat shadow, bare social glyphs.
Feed mobile
Feed (mobile). Functional stack; hamburger nav. Headings wrap mid-token.
The one hard constraint

Why we can't just rebuild it

Customers write their own CSS/JS that targets the portal's markup. The HTML is effectively an unversioned public API โ€” change a class name or DOM nesting and you silently break paying customers.

Customer custom CSS/JS
targets your class names + DOM
โ†’
Portal markup
the implicit contract

โœ“ Phase 1 โ€” Safe

Change appearance only: Bootstrap variable overrides, a modern token layer, restyled components via existing selectors. DOM + class names frozen โ†’ customer code keeps working.

โœ— Phase B โ€” Needs a migration story first

A Bootstrap 3โ†’5 jump renames classes and restructures DOM โ€” it breaks the contract. Only safe once a versioned component layer + customer migration path exist.

One caveat we're honest about: even variable overrides change computed dimensions (font size, radius, line-height), so customer CSS pinned to positions can still break visually. That's why the data pull below gates everything.

โœ… The risk is tiny and nameable (SQL pull, 2026-06-05)

30,727orgs total
224have custom CSS (0.7%)
52have custom JS (0.17%)
~30heavy-custom orgs
to grandfather/verify

Phase 1 ships to the 99.3% with zero custom-code risk today. The heavy customizers (brotherspubcoclub 474k, Eureka 164k, timothyoulton 142k CSS; craftsavvy 102k, wms 80k, isssic 69k JS) get grandfathered onto the current theme via a per-org flag. No versioning system needed to start โ€” the scariest unknown is now a 30-row list.

The plan

Three phases, in sequence

Each phase earns the right to the next. Ship value and recapture deals early; defer the risky structural work until it's de-risked.

START HERE
Phase 1 ยท Approach A

In-place theme refresh

  • Empty-state redesign (red โ†’ neutral prompts)
  • Modern design tokens: type, spacing, color, radius, shadow, motion
  • Restyle nav + mobile chrome
  • Zero markup/selector changes
human ~2โ€“4 wks ยท risk Low ยท recaptures near-term deals
Phase 2 ยท Approach C

Strangler components

  • New, namespaced, bettermode-style modular blocks
  • Consolidate the dual nav
  • Per-org opt-in; legacy markup untouched
human ~4โ€“8 wks ยท risk Med ยท modular UX, no big-bang
Phase 3 ยท Approach B

Bootstrap 3 โ†’ 5

  • Real flex grid, modern components, true mobile-first
  • Versioned theme contract + customer migration path
  • The destination โ€” once A + C de-risk it
human ~2โ€“4 mo ยท risk High ยท long-term answer
Before any code

The gate on everything

๐Ÿ“‹ The assignment

Pull the list of paying orgs that ship custom portal CSS/JS and the selectors they depend on. That single data pull turns the scariest unknown โ€” the markup contract โ€” into a bounded, known constraint, and tells us how aggressively Phase 1 can move. In parallel: name the 2โ€“3 deals that cited the look, so we can re-test them after the refresh.

Phase 0 blockers

  • Rollout seam: per-org/staged, or one global grunt CSS bundle? Defines the safety story + rollback.
  • Custom-code scope: which orgs, which selectors? (the assignment)

Suggested next moves

  • /design-shotgun on Profile โ€” 3 modern reskins of the worst screen, bettermode as reference
  • /plan-eng-review โ€” lock Phase 0 + token architecture before building