Skip to content

fix: mobile performance improvements - #156

Merged
appflowy merged 5 commits into
AppFlowy-IO:mainfrom
MayurSMahajan:fix/mobile-perf-impr
Oct 2, 2026
Merged

appflowy merged 5 commits into
AppFlowy-IO:mainfrom
MayurSMahajan:fix/mobile-perf-impr

Conversation

@MayurSMahajan

@MayurSMahajan MayurSMahajan commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

a. Improved the Mobile performance loading time by optimizing LCP images and compressing them, removed
b. Removed scroll-snap-type: mandatory with scroll-behavior: smooth, which makes
Chrome run an animated snap as the cards settle, thus fixing NO_LCP error on Lighthouse
c. Removed some unused css
d. Use next/font instead of google font

Feature Preview


PR Checklist

  • My code adheres to the AppFlowy Style Guide
  • I've listed at least one issue that this PR fixes in the description above.
  • I've added a test(s) to validate changes in this PR, or this PR only contains semantic changes.
  • All existing tests are passing.

MayurSMahajan and others added 5 commits October 1, 2026 22:40
PageSpeed Insights has been failing every mobile run on the homepage with
NO_LCP, and Search Console has been flapping between 0 and 140+ good URLs.
The mobile report failed because Chrome emitted no LCP candidate at all:
the trace showed four largestContentfulPaint::Invalidate events and zero
Candidates, so Lantern threw NO_LCP and aborted the whole insights pass —
which is why LCP *and* TBT both errored while FCP, SI and CLS still
reported.

The trigger was the testimonial carousel's track. A scroll-snap-type:
mandatory container with scroll-behavior: smooth makes Chrome run an
animated snap as its cards settle, and a scroll finalises LCP — so the
snap landed before any candidate was reported. Bisecting the SSR HTML with
JS stripped pinned it to that one element: removing it restored LCP 3/3,
and on the live site overriding scroll-snap-type alone was enough.
Dropping `scroll-smooth` fixes it without changing behaviour, because both
carousels already pass `behavior: 'smooth'` to scrollBy/scrollTo
explicitly — the arrows still glide and snapping is untouched. The same
pattern in platform-section gets the same treatment, and the unused
.testimonial-section__mobile-track rule carried the identical property
pair, so it goes too.

With LCP reporting again it measured 18.9s, because the hero carousel kept
displacing it: project-tracking.webp was 2560x1483 while the other four
slides were 2560x1480, so under object-contain the first slide painted
marginally smaller than every slide that followed and each swap became a
new, later candidate. Normalising it to 2560x1480 keeps the hero as the
LCP for good (and drops the file from 150KB to 92KB).

Separately, React preloads every <img> it renders on the server unless the
tag opts out, so the eager below-the-fold illustrations in the showcase
and dev-info sections were putting ~1.13MB into <head> ahead of the hero.
Marking them lazy leaves the hero alone on the high-priority path.

Lighthouse mobile, local production build, 3 runs:
  before: NO_LCP error, report unusable
  after:  score 91, FCP 1.8s, LCP 3.2s, TBT 0ms, CLS 0
  image preloads in <head>: 10 -> 1
  largestContentfulPaint::Invalidate events: 4 -> 0

Note: fetchPriority="low" on the carousel's later slides was tried first
and does not work — Chrome assigns High to any in-viewport image
regardless, confirmed via CDP initialPriority.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@appflowy
appflowy merged commit 0cb152a into AppFlowy-IO:main Oct 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants