Skip to content

v2.62.6

Choose a tag to compare

@github-actions github-actions released this 01 Aug 09:35
Immutable release. Only release title and notes can be modified.
bdd9785

Three fixes: two homepage layout bugs and one production 500 on /dev-console.

Intro copy overflowed its grid cell

The intro text card ran 400px tall against a 328px cell at 1440px wide, so its row grew and every neighboring card floated with a gap under it. Two causes: RichText gives each block a bottom margin (including a wasted one after the last paragraph), and body1 gets responsiveFontSizes scaling on top of the root font-size ramp, so at wide viewports the copy hit ~20px and the second paragraph wrapped onto a fifth line. The intro card now hands RichText its own vertical rhythm (one gap, no per-element margins) and renders paragraphs at the root font size. The Contentful copy is untouched.

Measured card height vs. the standard cell, before → after:

Viewport Cell Intro before Intro after (content)
768 293 326 286
1024 311 383 301
1440 328 400 315

Spotify loading skeleton was short

The Spotify card wraps its ContentCard in a shell for the gradient glow, so the shell is the grid item and the card sizes to its contents. The skeleton is shorter than a loaded track, so it left a visible gap next to the full-height neighbor. The loading card and the shell now pass the cell height through, which also fixes the loaded card sitting 8px short (320 → 328). Rebased onto #562, which moved the gradient shell into the client SpotifyCardWithGradient, so the height fill lands there.

/dev-console returned a 500 in production

listSubscriptions threw a bare Error for any non-ok response from Strava. With the Strava application marked Inactive, the API answers 403 and that throw escaped WebhookCard's server component, so the whole route 500'd even though every other card was fine.

  • Strava refusals now throw a typed StravaApiError carrying the status and a human-readable reason.
  • getWebhookSubscriptions converts that one error type into { subscriptions, error } for the card to render. Anything else still throws, so real bugs are not swallowed.
  • The error-message parser moved out of createSubscription so both call paths share it, and it now recognizes the inactive-application response.
  • The webhook card shows the reason and offers no create/delete action while the subscription state is unknown.
  • Each console card is wrapped in an error boundary, so any unexpected failure degrades to one broken card rather than the route.

A missing Spotify token was already handled — getLatestSong goes through withMissingTokenFallback and getOauthStatus catches its own failures — so that path only logs; it does not 500. There are now tests covering it.

Verification

turbo check, turbo check:types, and the full Jest suites pass locally against a real Postgres (@dg/web 113 tests, @dg/services 117, @dg/ui 38, @dg/shared-core 30, @dg/content-models 39). New tests resolve the console's cards with fetch returning Strava's actual 403 {"errors":[{"resource":"Application","field":"Status","code":"Inactive"}]} body and assert the card renders the reason instead of throwing; reverting the service fix makes them fail with the original unhandled StravaApiError.