Design: Member Portal Modernization¶
Generated by /office-hours on 2026-06-05 Branch: codex/eng-45-mce-lane-a (session branch; work will get its own branch) Repo: rakletadmin/rakletv3 Status: APPROVED Mode: Startup (established product, has paying customers)
Problem Statement¶
Prospects evaluating Raklet say the member-facing portal looks outdated and ugly, and
this has cost named deals. The portal in question is the member experience served at
https://<org>.raklet.net/App/* — Profile, Payments, Donations, Tickets, Messages, and
the social network screens. This is the surface a prospect judges when asking "what will
my members actually experience," and it is the highest-blast-radius surface in the product
(every org's members see it).
The goal: make it look modern, on a path that recaptures near-term deals without breaking the paying customers who have built custom CSS/JS on top of the current markup.
Demand Evidence¶
Strongest possible signal: lost named deals where the dated look was the stated dealbreaker. This is not polish-chasing; it is revenue. It justifies committing engineering to the work and scoping it like a revenue initiative rather than a backlog nicety.
Open question carried forward (verify before assuming pixels alone recapture deals): when those deals walked, was it the look alone, or the look plus a competitor whose portal also did something Raklet's doesn't (e.g. bettermode-style modular community layout)? If the latter, the visual refresh is necessary but not sufficient, and Approach C (modular components) moves up the priority list.
Root Cause (grounded in code)¶
- The portal renders on Bootstrap v3.4.1
(
Raklet.Backend/Content/styles/third_party/bootstrap-sass-official/assets/stylesheets/bootstrap/_variables.scss:2). Bootstrap 3 (2013) has a default aesthetic — panel-cards, non-flex grid, dated button/form chrome, nav that isn't mobile-first by 2026 standards — that is the "2015 SaaS" look prospects react to. - Estimated ~60-70% of the "outdated" perception is Bootstrap-3 defaults + absent modern design tokens (no modern type scale, spacing rhythm, radius/shadow system, or motion), not deep structural rot. That means a large share of the win is recoverable at the theme/variable layer — exactly the layer that does not touch customer markup.
- Member portal view/JS layer lives under
Raklet.Backend/Content/scripts/core/social/. Note: edits underRaklet.Backend/Content/require the grunt build step (scripts/dev/invoke-backend-grunt.ps1) to deploy —build-fast.ps1only handles .NET.
Visual Evidence (captured live 2026-06-05, demo.raklet.net)¶
Driven headless via gstack browse, desktop 1440 + mobile 390. Screens captured:
logged-out Feed/home, Events, Login; and authenticated /App/*: Profile, Payments,
Settings/Profile, Donations, Messages (logged in as sales@raklet.com on demo.raklet.net).
Baseline /design-review scores (for the Success Criteria delta):
- Settings/Profile: ~6.5/10 — the strongest screen. Proper left sub-nav (active state),
labeled form, clear sections, Save CTA. Proves the team can do clean layout; the gap is
tokens + consistency, not capability. Still dated: native selects, flat card chrome.
- Member Login: ~6/10 — clean but generic-2015; hard border + flat shadow, bare social glyphs.
- Profile (/App/Profile): ~3.5/10 — worst offender, and the most-viewed member screen.
Empty data fields render as red "No Records" / "Missing" / "No data" alarm badges — the
page looks broken/error-filled when it's just empty. Contact info sits in a clashing
yellow callout vs the white card. Lone floating "Logout" text link.
- Payments: ~4/10 — four oversized white cards (Subscriptions/Invoices/Payments/Credit
Cards), each one line of "No Records." Massive dead space, blocky headers.
- Feed/home: ~4/10 — barren identical gated cards; weak nav contrast.
- Events: ~4/10 — raw native <select> filter, empty gray image placeholders reading as
broken, inconsistent badge system (outline vs solid pills).
Highest-impact findings (ranked by impact / effort):
1. Empty states styled as red error badges (profile, payments) — single biggest
"feels broken" signal; the fix is badge color + copy (red alarm -> neutral "Add your..."
prompt). Pure token/component, no DOM change. Do this first.
2. ~~Dual navigation~~ RETRACTED (CEO correction 2026-06-05): the dark icon rail is the
ADMIN panel, visible only because capture was done as an org owner (sales@raklet.com).
Regular members never see it — the member view is just the light sidebar. The member
experience is therefore cleaner than the as-admin screenshots show. No nav-consolidation
work needed for Phase 1.
3. Unstyled native <select> dropdowns everywhere (events filter, settings). Token layer.
4. Inconsistent surfaces/badges — yellow callout vs white cards; outline vs solid pills.
5. Bootstrap-3 chrome: flat pale-blue bars, hard 1px card borders, 2013 link blue, weak type
scale, oversized blocky headings, lots of dead space.
This evidence CONFIRMS hypothesis H1: the "outdated/broken" perception is dominated by token/component-layer issues (empty-state badges, selects, chrome, type scale), recoverable without touching the markup contract. The IA (sidebar + cards + proper settings form) is structurally sound and close to the bettermode model. The one partly-structural item is the ~~dual-nav consolidation~~ (retracted — admin-only chrome). Refined wedge: (a) empty-state redesign, (b) global token reskin, (c) mobile chrome — in that order.
Design Direction (design-shotgun 2026-06-05)¶
Three Profile reskins generated (hand-built HTML, markup-safe; AI-image path needs an
OpenAI key). Approved: Variant A "Calm Community" — airy bettermode-like, white/warm-gray
+ indigo, soft cards, neutral dashed "+ Add..." empty-state prompts replacing the red alarms,
clean single member sidebar, contact side-panel + profile-completion meter. Chosen as the
safest modern base across Raklet's diverse org range. Artifacts:
~/.gstack/projects/rakletadmin-rakletv3/designs/profile-20260605/ (variant-a/b/c.html +
profile-reskin-board.html). These HTML mockups double as the implementation head-start.
Screenshots: %TEMP%\portal-evidence\ (01-home, 02-login, 04-events, 20-app-profile,
21-app-messages, 22-app-payments, 23-app-donations, 24-app-settings; -desktop/-mobile).
Traffic Data (App Insights, 30d, all orgs — added after CEO challenge)¶
Prioritization was initially by design-eye; corrected with real traffic. Top user-facing
/App/* pages by request volume (API/XHR endpoints excluded):
| Rank | Page | Share | Design score | Reviewed |
|---|---|---|---|---|
| 1 | /App/Search | 21.0% | sparse (empty-state = yellow box) | added |
| 2 | /App/Profile | 19.9% | 3.5 (worst) | yes |
| 3 | /App (Feed) | 14.4% | 4.0 | yes |
| 4 | /App/Members | 6.8% | ~5 (decent grid, empty avatars) | added |
| 5 | /App/Payments | 5.4% | 4.0 | yes |
| 6 | /App/Membership (+create) | ~9% combined | not scored | partial |
| 7 | /App/Settings/Profile | 4.2% | 6.5 (best) | yes |
| 9 | /App/Messages | 3.0% | n/a | yes (over-weighted) |
Top 3 (Search + Profile + Feed) = ~55% of portal page views; top 5 ≈ 67%.
Corrections this forced: - Profile is BOTH the worst-scoring and #2 most-visited → confirmed Phase-1 anchor. - Search is the #1 page and was unreviewed initially → must be in Phase 1. - Members directory (#4) and the Membership flow (~9%) are high-traffic and were unreviewed. - Messages (3%) is NOT a Phase-1 priority despite earlier framing.
Revised Phase-1 screen set (traffic x ugliness): Profile, Search, Feed, Members, Membership — drop Messages from the front of the line. The global token + empty-state work covers all of them at once; per-screen polish follows this ranking.
Caveat: 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 cross-check
(engaged sessions, not raw requests) would tighten it.
Custom-Code Risk — QUANTIFIED (SQL pull 2026-06-05, the assignment, DONE)¶
SocialSettings over all orgs:
- 30,727 orgs total. 224 have CustomCss (0.73%). 52 have CustomJs (0.17%).
- The markup-contract risk touches under 1% of orgs. Phase 1 can ship to the other
~99.3% with zero custom-code risk immediately.
- Risk is concentrated and nameable, by CSS size:
- Heavy (>10k): brotherspubcoclub (474k), Eureka (164k), timothyoulton (142k),
sphere-ensim (37k), fba (26k), wms (11k) — ~6 orgs.
- Medium (2k–10k): ~25 orgs.
- Trivial (<2k, mostly 50–500 chars): ~190 — cosmetic tweaks, low risk.
- JS is the sharper risk (DOM manipulation > CSS in brittleness): craftsavvy (102k),
wms (80k), isssic (69k), fgasregister (27k), palliativecareqld (24k), un-port (20k),
iwra (20k), isikun (14k).
- Active protect-list (recently modified = live customers): fba (2026-02),
isssic (2026-05), iwra (2025-10), un-port (2026-03), isikun (2026-01),
monashrmosociety (2026-04), saltyturtlecycling (2025-12), lhg (2025-11), kume (2025-09),
rpni, ekoloji, cydd-mezunlar, rostelecom — ~13 orgs.
Strategic impact: no versioning system or migration story needed to START. Phase 1 ships broadly; the ~30 heavy-custom orgs get grandfathered onto the current theme via a per-org flag, or hand-verified. Phase 0 "rollout seam" blocker is now the only true gate.
Remaining pull (refines, not gates): query #3 (actual CustomCss/CustomJs content) for the top ~30 orgs → extract the exact class names + DOM queries they depend on = the literal "do-not-touch" selector list.
The Binding Constraint (most important section)¶
Customers write their own CSS and JS that targets Raklet's portal DOM and class names. The portal HTML is effectively an unversioned public API. Implications:
- Phase 1 may change appearance (Bootstrap variable overrides, a modern token layer, restyled components via existing selectors) but must preserve DOM structure and class names. Renaming a class or re-nesting an element silently breaks paying customers.
- Any change that alters the markup contract (Bootstrap 3->5, structural rebuild) requires an explicit versioning + customer-migration story built first. It cannot be the opening move.
- This constraint is why the recommended sequence front-loads the safe, appearance-only work and defers structural change until a versioned component layer exists.
Constraints¶
- Bootstrap 3.4.1, bootstrap-sass (SCSS) pipeline; grunt deploy required for Content/ edits.
- Live, shared, multi-tenant surface — every org's members are affected at once; rollout needs care (staged, ideally flag-gated where possible).
- Customer custom CSS/JS coupled to markup (see above).
- North-star design reference: bettermode.com — modular template/layout, modern community UX.
Premises¶
Confirmed by CEO: 1. The dated look is real and revenue-linked (lost named deals). 2. The markup contract exists and is the binding risk — phase 1 changes appearance only. (Its scope — how many orgs, which selectors — is unconfirmed; see the Assignment data pull.) 3. Navigation + mobile experience is the right first wedge (highest visibility, concrete Bootstrap-3 weakness). 4. Full rebuild is phase 2+, earned only after a versioned component layer exists.
Hypotheses to validate in the evidence sweep (NOT yet confirmed): - H1: ~60-70% of the "outdated" perception is recoverable at the Bootstrap-variable/token layer, with structural/IA issues the minority. The evidence sweep (Step 1) must explicitly test this split. If structural issues dominate, Phase 1 under-delivers and C moves up. - H2: A meaningful mobile improvement is achievable without DOM/grid changes. See the mobile-scope caveat under Recommended Approach.
Approaches Considered¶
Approach A: In-place Bootstrap theme refresh (RECOMMENDED — phase 1)¶
- Summary: Override Bootstrap-3 SCSS variables and add a modern design-token layer (type scale, spacing, color, radius, shadow, motion). Restyle navigation and mobile responsiveness first. Zero markup/selector changes.
- Effort: human ~2-4 weeks / CC accelerates the build, but live-customer QA + staged rollout dominate the timeline.
- Risk: Low.
- Pros: Recaptures near-term deal perception fast; breaks no customer custom code; proves the modern direction cheaply; becomes the token foundation for C and B.
- Cons: Appearance-only — can't fix layout/IA problems that need DOM changes (completeness ~6/10).
- Reuses: existing bootstrap-sass variable system, existing grunt SCSS pipeline, existing selectors/DOM.
Approach C: Strangler component layer (phase 2)¶
- Summary: Leave legacy markup untouched; introduce new, modern, namespaced, bettermode-style modular blocks (nav, profile header, cards) behind a per-org flag. Migrate orgs gradually; old portal remains as fallback.
- Effort: human ~4-8 weeks scaffolding / CC strong fit for component generation.
- Risk: Medium.
- Pros: New components use a scoped design system customer code never targeted — no contract to break; opt-in org by org de-risks rollout; this is how modular (bettermode-style) UX arrives without a big-bang rewrite.
- Cons: Two systems coexist during migration; needs a flag/rollout mechanism; only valuable after A establishes the token layer.
- Reuses: design tokens from A; org-level feature-flag patterns already in the platform.
Approach B: Bootstrap 3 -> 5 migration (phase 3 / destination)¶
- Summary: Upgrade the actual framework (flex grid, modern components, true mobile-first) behind a compatibility shim and a versioned theme contract with a customer-code migration path.
- Effort: human ~2-4 months / CC helps but breakage surface is large.
- Risk: High.
- Pros: The honest long-term answer; real modern framework; unlocks the eventual full rebuild.
- Cons: Bootstrap 3->5 renames classes and changes DOM — directly hits the markup contract; wrong as move #1; only safe once A + C have de-risked it and a migration story exists.
- Reuses: token layer and component layer from A + C as the migration target.
Recommended Approach¶
Approach A first, explicitly architected as the foundation for C, then B. The unifying design principle: never break the markup contract in phase 1; earn the right to restructure by first shipping design tokens (A) and a versioned, namespaced component layer (C). This recaptures near-term deals quickly and safely while building toward the bettermode-style modular portal without a big-bang rewrite.
Two caveats that bound Phase 1 honestly:
- Variable overrides are not automatically contract-safe. Changing
$font-size-base,$border-radius-base,$line-height, etc. changes computed dimensions. Customer CSS that pins to positions/sizes can break visually even though no class or DOM node moved. "Zero markup changes" does not equal "zero customer-visual-regression." This belongs in the regression scope, tested against sampled real customer overrides (see Phase 0). - Mobile within Bootstrap 3 has a ceiling. BS3's non-flex grid and non-mobile-first breakpoints mean Phase 1 can fix mobile chrome — touch targets, nav collapse styling, spacing, font sizing — but cannot deliver modern responsive layout without DOM/grid changes the contract forbids. Scope the mobile wedge to the chrome wins; flag true responsive layout as Approach C work.
Phase 0 Blockers (resolve before any Phase 1 build)¶
These are not "open questions to ponder" — they gate whether the strategy below is even feasible. Answer both before committing build time:
- Rollout seam. Does a per-org/staged rollout mechanism exist, or is Content/ CSS a single global grunt bundle that hits every tenant at once? If the latter, the "staged rollout" safety story collapses to "ship to everyone and watch" — and we need a rollback plan (revert the grunt-built CSS bundle; named owner triggers it) instead. The entire safety narrative, and Approach C's per-org opt-in, depend on the answer.
- Custom-code scope (the Assignment). Which paying orgs ship custom portal CSS/JS, and which selectors/computed positions do they depend on? Until this lands, "representative regression check" has no defined sample.
The Process (how this actually runs)¶
- Evidence sweep (do this first, ~1 session). Drive the live member portal on
raklet.net authenticated, screenshot every
/App/*screen at desktop + mobile widths, run/design-review, and produce a ranked ugliness-vs-effort map. This turns "looks old" into a concrete per-screen punch list and confirms where Bootstrap-3 defaults hurt most. - Design direction (~1 session). Run
/design-consultationto produceDESIGN.md— the design-system source of truth — with bettermode.com as the documented North Star (type scale, color, spacing, radius, shadow, motion, nav patterns). This is what every later change is measured against. - Token + nav/mobile build (Approach A). Implement variable overrides + modern token layer; restyle navigation and mobile responsiveness first. Selectors/DOM frozen.
- Verify safety. Before/after screenshots via the browse tool; spot-check that representative customer custom CSS/JS still renders correctly (the markup-contract regression check). Staged rollout.
- Measure. Re-run the same prospect demo flow; ideally re-engage a deal that cited the look, and watch conversion/feedback. Close the loop on the "look alone vs look + feature" open question.
- Phase 2+ decision. With tokens shipped and deals re-tested, decide whether to proceed to C (modular strangler components) and eventually B (framework migration).
Skills / Tooling to Leverage¶
Yes — we can run tests, capture screenshots, and run design review against raklet.net directly. The toolchain:
- gstack
browse(the$Bbinary) — headless browser, ~100ms/command, drives any URL and screenshots. Already proven against.raklet.net(the browse-tests migration). Auth into the member portal works the waybrowse-tests/smoke/07-portal-account-page-loads.ps1does (org permalink + member login). /design-review— designer's-eye visual QA on live screens; finds inconsistency, spacing, hierarchy, and AI-slop issues, and can iteratively fix + re-screenshot before/after./design-consultation— producesDESIGN.md(design-system source of truth); where bettermode becomes a documented standard./design-shotgun— generates modern visual variants of a screen for comparison./plan-design-review— reviews the modernization plan before implementation./qa— post-change functional + visual regression on the portal.
Open Questions¶
- Did the lost deals walk on the look alone, or look + a missing capability (e.g. bettermode-style modular community layout)? Determines whether A alone recaptures them or C is required.
- What share of paying orgs actually ship custom CSS/JS on the portal, and which selectors do they depend on most? This bounds how "frozen" the contract must be and where the real regression risk concentrates. (Needs a data pull, not a guess.)
- Is there a per-org feature-flag mechanism usable to stage the rollout, or does Content/ grunt deploy hit all tenants at once?
Success Criteria¶
- A prospect running the standard demo flow no longer cites the look as a blocker (qualitative, re-tested against a real deal where possible).
- Zero customer-custom-code regressions attributable to phase-1 changes.
- Nav + mobile member portal screens score baseline +3 or absolute >=8/10 on
/design-review, measured against the numeric baseline captured in the evidence sweep (Step 1 must record per-screen scores so "higher" is quantified, not vibes).
Distribution Plan¶
Existing deployment pipeline covers this (master -> test -> prod branch promotions; Content/ changes via grunt build). No new distribution channel. The one addition worth scoping: a staged/flag-gated rollout so a live visual change does not hit every tenant simultaneously without a verification window.
Dependencies¶
- Grunt deploy for
Raklet.Backend/Content/edits (scripts/dev/invoke-backend-grunt.ps1). - A populated member-portal org for capture/QA (e.g. the
gercek.raklet.org/ general-test-account member side). - Data pull on customer custom-CSS/JS usage for the regression-risk bound.
The Assignment¶
Before any code: pull the list of paying orgs that have custom portal CSS/JS and the selectors they depend on. That single data pull turns the scariest unknown (premise 3, the markup contract) into a concrete, bounded constraint — and tells you 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 and close the "look alone vs look + feature" question.
What I noticed about how you think¶
- You didn't accept "rebuild the portal" even though you'd just told me deals died over it. You said "it's tricky to rebuild because our customers write their own css/js and it ties back to the markup." That's the constraint a less careful operator discovers three months into a rewrite. You led with it.
- You reached for a concrete reference — "bettermode.com has a good modular template / layout" — instead of an abstract "make it modern." Specific North Stars are how teams actually converge on taste.
- "We can start by optimizing navigation, mobile experience" — you instinctively picked the narrowest high-visibility wedge over the maximalist play. That's the same instinct that keeps scope from eating the quarter.