- Site context is locked to the site from the current URL — no dropdown
switcher. If not on a site page, defaults to Organization context.
- Renamed "Workspace" to "Organization" in all user-facing text.
- Removed unused CaretDown import and dropdown state.
- 4 files imported from 'motion/react' which was the removed 'motion' package.
Replaced with 'framer-motion' (the package actually installed).
- Dashboard content area now has rounded corners, subtle border, and inset
margin creating a "panel inside shell" visual separation from the sidebar.
Consistency fixes:
- Extract getThisWeekRange/getThisMonthRange to shared lib/utils/dateRanges.ts
(removed 4 identical copy-pasted definitions)
- Add error boundaries for behavior, cdn, search, pagespeed pages
(4 new error.tsx files — previously fell through to generic parent error)
- Add "View setup guide" CTA to empty states on journeys and behavior pages
(previously showed text with no actionable button)
- Fix non-lazy useState initializer in funnel detail page
- Fix Bot & Spam settings header from text-xl to text-2xl (matches all other sections)
- Add useMinimumLoading to PageSpeed skeleton (consistent with all other pages)
Cleanup:
- Remove 438 redundant dark: class prefixes (app is dark-mode only)
text-neutral-500 dark:text-neutral-400 → text-neutral-400 (206 occurrences)
text-neutral-900 dark:text-white → text-white (232 occurrences)
- Remove dead @stripe/react-stripe-js and @stripe/stripe-js packages
(billing migrated to Polar, no code imports Stripe)
- Remove duplicate motion package (framer-motion is the one actually used)
Use opacity instead of bg-color swap for proper transition-opacity
animation on mobile backdrop. Add shimmer gradient to the sidebar
loading placeholder in DashboardShell.
Convert the sidebarContent(isMobile) closure function to a proper
SidebarContent component with explicit props, enabling correct React
reconciliation for both desktop and mobile sidebar instances.
- Replace dead frequency badge with inline dropdown selector
- Add "Next in Xh" indicator from next_check_at
- Demote "Disable" button to subtle text link (was competing with Run Check)
- Add cursor-pointer to prev/next history arrows
- Narrow filmstrip fade to avoid covering content
The share/[id] layout is a server component that imported FAVICON_SERVICE_URL
from icons.tsx, pulling in the entire React icon registry and triggering
createContext on the server. Moved the constant to its own favicon.ts module.
Replace three separate data structures (getReferrerIcon if-chain,
REFERRER_DISPLAY_OVERRIDES, REFERRER_PREFER_ICON) with a single
REFERRER_REGISTRY. All matching is now exact key/hostname lookup
via resolveReferrer() — no more substring includes() that caused
collisions like t.co matching reddit.com.
Detect Google's 16x16 default globe fallback via naturalWidth on load
and fall back to Phosphor icons. Add Chrome icon for googlechrome.github.io,
CursorClick for Direct, and abbreviation support (ig, fb, yt).
Revert inline frequency toggle from pagespeed page. Add PageSpeed
Monitoring section to site settings under the Data tab with a Select
dropdown for Daily/Weekly/Monthly. Shows "Not enabled" when PSI is off.
Replace static frequency badge with a pill toggle (Daily/Weekly/Monthly)
matching the Mobile/Desktop tab style. Updates config via API on click.
Read-only badge shown for non-admin users.
Navigate between historical checks using ◀ ▶ arrows in the hero
footer bar. Shows formatted date when viewing historical data,
"Last checked X ago" when on latest. Fetches full audit data via
getPageSpeedCheck when navigating to a historical check.
Group audits within each category by sub-group (e.g., "Names and
Labels", "Contrast") with small uppercase headers, matching the
pagespeed.web.dev layout.
- Hero: 4 equal 90px ScoreGauges in a row with screenshot on right
- Diagnostics: each category card gets a 56px gauge header with score
and issue count, matching pagespeed.web.dev's category sections
- Legend and metadata moved to footer bar in hero card
Use direct API fetch for polling instead of mutateLatest() which was
causing the page to flicker and clear data every 5 seconds. SWR cache
is only updated once when new results arrive.
- Hero card: large performance gauge + compact inline scores + screenshot
- Single metrics card with 2x3 grid and colored status dots
- Flat diagnostics list sorted by impact with severity indicators
- ScoreGauge accepts size prop for flexible gauge sizing
- Unicode severity markers (triangle/square/circle) per audit
- Page screenshot thumbnail next to score gauges
- Expandable audit rows with description and detail items table
- Shows URLs, HTML snippets, wasted bytes/ms for each failing element
- AuditRow component replaces flat diagnostic rows