Repository source: docs/plans/nav_links_load_stability/nav_links_load_stability_step4_implementation_summary.md
Debug mode: enabled
Step 4: Implementation Summary — Stable Messages/Invite Nav Buttons
Stage 1 - Diagnose late nav buttons
Changes:
None to application code (read-only diagnosis).
Verification:
Code reading only; no browser run yet.
FrontController::resolveStaticArtifactPath()serves prebuilt static HTML only for GET requests with no query string and no cookies at all; any cookie (session,identity_hint, theme hint) falls through to the dynamicApplication.Static HTML is built with no viewer, so it never contains Messages/Invite. Dynamic pages include them only when
resolveViewerProfileFromIdentityHint()finds an approved viewer with_authenticated_identity === true(needs a live PHP session; anidentity_hintcookie alone givesfalseand no items).No script found that inserts Messages/Invite on a normal page load.
feature_flags.jspatches Messages only after a flag toggle;private_site_auth.jsreloads the page after authenticating, and is loaded only in members-only/public-resume modes.
Notes:
Step 2 assumption not confirmed: there is no client-side post-load insertion in the code. Plausible explanations, each unverified: (a) navigating between cookie-less static pages and dynamic pages makes the items appear/disappear between page loads; (b) a viewer with an
identity_hintbut no live session gets no items until a session is established; (c) site.css loads non-blocking (media="print"swap) so nav styling/icons for these links arrive after first paint.Needs the user's observation (which pages, signed-in how, which theme) or a browser repro before Stage 2 so the fix targets the real cause.
Stage 1 (revised plan) - Remove visible unread text, keep state in attributes/ARIA
Changes:
templates/partials/nav.php: dropped the visible…count span; Messages caption is now exactlyMessages. The hidden status span (aria-describedby) stays.private_message_unread.js,feature_flags.js: stop writing visible count text (?,(N)); state still set viadata-unread-state,data-unread-count,title, and the hidden status text.Browser tests updated to assert the caption stays
Messagesand the status description is populated, instead of…/?.
Verification:
node tests/browser/private_message_live_navigation.mjspassed.node tests/browser/private_message_list_browser.mjspassed (includes unread UI checks).php tests/run.phpexit 0, 1225 passes, no FAIL lines.
Notes:
Outline highlight is Stage 2; until then there is no visible unread signal.
Plan revision commit
5931a5daprecedes this stage; the earlier Stage 1 diagnosis (commit7dc7856f) is retained as history.
Stage 2 - Outline highlight for unread Messages
Changes:
public/assets/site.css: layout-neutraloutlineon.nav-link[data-unread-count]when the count is not0.public/assets/theme-sticker.css: override (double outline) because sticker already uses a 2px outline as its resting nav style, which would hide the highlight.New
tests/browser/nav_unread_outline.mjs: for every theme sheet, asserts Messages/Invite boxes are identical across no-count,0, and3, that unread outline differs from the resting style and is visible, and that zero adds nothing.
Verification:
node tests/browser/nav_unread_outline.mjs: passed in 16 themes.php tests/run.php: exit 0, 1225 passes. A first run failed 3 tests because the selector included the stringdata-private-message-unreadin shared CSS (guarded by release-isolation/nav tests); rekeyed ondata-unread-countand reran clean.git diff --checkpassed.
Notes:
Contrast/aesthetics of the outline per theme were checked structurally (differs from resting, visible), not by eye; worth a visual look.
Stage 3 - Final verification
Changes:
tests/browser/private_message_unread_ui.mjs: added assertions that the caption staysMessagesand ARIA (aria-describedby→ hidden status text) reportsN unread conversation(s)once ready.
Verification:
node tests/browser/private_message_list_browser.mjs,private_message_live_navigation.mjs,nav_unread_outline.mjsall passed.php tests/run.php: exit 0, 1225 passes (run after Stage 2; Stage 3 changed only a browser test).git diff --checkpassed.Deployment/external checks: not applicable (local CSS/JS/template change, no schema, no external systems).
Notes:
Guest/disabled messaging paths covered by existing availability and live-navigation tests.
The originally reported "buttons appear late" symptom was not reproducible from code (Stage 1); the fixed jank is the width shift. Not visually reviewed by eye per theme.