feat: home page redesign + role redirect + fix Sign In (Phase 10f-1, 10f-2, 10f-3) #29
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-landing!29
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "28-home-page-redesign-role-redirect-fix-sig"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Replace the raw API stats dashboard with a proper landing page for unauthenticated visitors, ported from the west-side-basketball static site. Authenticated users now get redirected to their role-appropriate dashboard. The broken Sign In button (double-nested
<button>from<SignIn>component) is replaced with a direct form POST.Changes
src/routes/+page.server.js— Rewrote from API stats fetch to session-based role redirect. Authenticated users go to/admin,/coach, or/player. Unauthenticated users see the landing page with no API call.src/routes/+page.svelte— Complete rewrite. Replaced stats dashboard with full landing page: hero with logo, about section (3 cards + Marcus quote), tryout details, how-it-works steps, FAQ, bottom CTA. Uses direct<form method="POST" action="/signin">instead of the broken<SignIn>component. All styles useapp.cssdesign tokens, no hardcoded hex values.src/routes/+layout.svelte— Conditionally hideAuthStatusnav component on the/route for unauthenticated visitors to avoid duplicate/broken sign-in buttons.static/logo.jpeg— Copied fromwest-side-basketballrepo for the hero section.Test Plan
/unauthenticated -- should see full landing page with hero, about, tryouts, FAQ sections/admin/coach/player<button>elements in the sign-in form/admin,/coach,/playerpages/for unauthenticated visitorsnpm run buildpassesReview Checklist
app.cssdesign tokenswest-side-basketball/index.html<SignIn>component not used -- direct form POST avoids broken double-nested buttonsnpm run buildpassesRelated
Self-Review (Dev Agent)
Reviewed the diff for code quality, SOP compliance, and issue constraints.
Finding: Hardcoded
#fffhex values (FIXED)Two instances of
color: #fffin.btn-primaryand.step-numberviolated the issue constraint "NO new hardcoded hex values." Replaced withvar(--color-text)in commit5791631.Other observations (no action needed)
rgba(212, 32, 38, ...)in radial gradients -- These reference the brand red for the hero/CTA glow effects. CSS custom properties cannot be interpolated insidergba()withoutcolor-mix()(limited browser support). The reference CSS (style.css) uses the same pattern. Acceptable./signinwithproviderId-- The/signinroute's action issignInfrom Auth.js, which readsproviderIdfrom form data. Only one provider (Keycloak) is configured, so this is correct and explicit.+layout.svelteconditional AuthStatus -- Uses$derivedwith$page.data.session?.user || $page.url.pathname !== '/'. Since authenticated users always redirect away from/, this correctly hides the nav sign-in button only on the unauthenticated landing page.VERDICT: APPROVED (after self-fix)
PR #29 Review
DOMAIN REVIEW
Tech stack: SvelteKit 5 (Svelte 5 runes), Auth.js/SvelteKit, Keycloak OIDC. This is a frontend landing page rewrite with server-side role redirect logic.
Server-side redirect (
+page.server.js)The redirect logic is correct: authenticated users get role-based redirect (admin -> /admin, coach -> /coach, fallback -> /player), unauthenticated users see the landing page with no API call. Clean simplification from the previous stats-fetching approach.
DRY observation (non-blocking): The role-priority redirect pattern (
admin > coach > player) is now duplicated acrosssrc/routes/+page.server.jsandsrc/routes/signin/+page.server.js. Both files have identical logic:This is NOT in an auth/security enforcement path (it is convenience routing, not access control -- the actual guards live in each route's own
+page.server.js), so it does not trigger the DRY-in-auth-path BLOCKER. However, if the role priority ever changes, both files must be updated in lockstep. Worth extracting to a shared utility eventually.Sign-in form approach
Using
<form method="POST" action="/signin">with<input type="hidden" name="providerId" value="keycloak" />is a clean fix for the double-nested<button>problem from the<SignIn>component. The/signin/+page.server.jshasexport const actions = { default: signIn }which correctly processes this form submission via Auth.js'ssignInaction. TheproviderIdfield name is what Auth.js expects.CSRF consideration: Auth.js/SvelteKit handles CSRF protection automatically through SvelteKit's built-in form actions mechanism (the
__superform_id/ SvelteKit action token). The direct form POST to/signinwill be processed by SvelteKit's action handler which includes CSRF protection. No issue here.Layout conditional (
+layout.svelte)The
showAuthStatusderived value uses a sound approach: show AuthStatus when the user has a session OR when the pathname is not/. Since authenticated users hitting/get server-redirected before the page renders, the landing page is only ever seen by unauthenticated visitors. The logic is correct.The import of
pagefrom$app/storesis the correct SvelteKit 5 pattern for accessing page data in components.Landing page markup (
+page.svelte)<section>,<blockquote>,<footer>, and heading hierarchy (h1 -> h2 -> h3). The FAQ section uses plain divs rather than<details>/<summary>-- acceptable for a static FAQ but noted below as a nit.width="80" height="80"attributes to prevent layout shift (CLS). Good.var(--color-*)design tokens. Thergba(212, 32, 38, ...)values in the gradient backgrounds are the only raw color values. These are the brand red (#d42026=rgb(212, 32, 38)) used at very low opacity for decorative radial gradients. There is no CSS custom property for semi-transparent brand overlays inapp.css, so inline rgba is the pragmatic choice here. Noted as a minor nit.<script>block: The page has no JavaScript at all -- pure SSR HTML + CSS. This is ideal for a public landing page (zero JS bundle for this route).Accessibility audit:
<img>has descriptive alt text ("Westside Kings and Queens logo"). Good.sectionelements haveidattributes for potential anchor navigation.--color-text: #f0f0f0on--color-bg: #0a0a0awhich passes WCAG AAA.--color-text-muted: #a3a3a3on#0a0a0agives ~7:1 contrast ratio, passes AA.<main>landmark wrapping the page content. The layout has AuthStatus nav + page content but no<main>tag. This is a pre-existing issue in the layout, not introduced by this PR.aria-labelon the form elements. Minor -- the button text is self-describing.BLOCKERS
None.
/signinroute pattern.+page.server.js.NITS
Hardcoded rgba brand color in gradients (
rgba(212, 32, 38, ...)appears 3 times in the<style>block). Consider adding--color-brand-glowor--color-brand-overlaytokens toapp.cssfor these semi-transparent brand usages. Low priority since the values are purely decorative.FAQ section could use
<details>/<summary>for progressive disclosure. The current flat list works fine for 7 items, but collapsible FAQ is a common UX pattern that would reduce visual density on mobile. Non-blocking.Copyright year hardcoded ("2026 Westside Kings & Queens"). If the app lives beyond this year, the footer will go stale. Consider
new Date().getFullYear()-- though this would require adding a<script>block to an otherwise zero-JS page, so the tradeoff may not be worth it.Extract redirect helper (future): The
admin > coach > playerredirect pattern in both+page.server.jsandsignin/+page.server.jscould be a shared$lib/server/redirectByRole.jsutility. Not blocking since it is convenience routing, not security enforcement.@ts-ignorecomment in+page.server.jsline 9 (// @ts-ignore -- roles added via Auth.js callback). This is a pre-existing pattern used consistently across the codebase, so not a regression, but worth noting that a proper type augmentation for the session would eliminate all these suppressions project-wide.SOP COMPLIANCE
28-home-page-redesign-role-redirect-fix-sig-- derived from issue #28)Closes #28plan-2026-03-08-tryout-prep). The PR body saysCloses #28but does not mention the plan. Minor -- the issue title itself references "Phase 10f-1, 10f-2, 10f-3" which provides traceability.PROCESS OBSERVATIONS
package.json, no test directories). The lack of tests for this specific PR is consistent with the repo's current state. The Test Plan in the PR body is comprehensive (13 manual verification items including responsive breakpoints). A future issue should address adding a test framework to this repo.VERDICT: APPROVED