Skip to content

feat: improve site performance and unify analytics - #87

Merged
remcostoeten merged 1 commit into
masterfrom
feature/site-performance-analytics
Aug 22, 2026
Merged

feat: improve site performance and unify analytics#87
remcostoeten merged 1 commit into
masterfrom
feature/site-performance-analytics

Conversation

@remcostoeten

@remcostoeten remcostoeten commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • integrate @remcostoeten/analytics-manager across Remco, PostHog, and Vercel
  • lazy-load contact and resume drawers and add viewport/reduced-motion hooks
  • refine layout, navigation, work experience, package, and miscellaneous UI behavior
  • remove unused dependencies and configuration

Validation

  • bun run typecheck
  • bun run test (131 passed)
  • bun run lint (passes with existing warnings)
  • bun run build:next
  • browser runtime smoke test

Summary by Sourcery

Improve site performance and consolidate analytics across supported providers.

New Features:

  • Unify Remco, PostHog, and Vercel analytics through a shared analytics manager with automatic pageview and engagement tracking.

Enhancements:

  • Reduce the initial client bundle by lazy-loading the contact and resume interactions and replacing always-mounted motion hooks with lightweight browser APIs.
  • Simplify work experience descriptions to support paragraphs and bullet lists without the markdown dependency.
  • Improve navigation, accessibility labeling, and UI text contrast across breadcrumbs, tools, packages, and mobile controls.

Build:

  • Remove unused Geist and React Markdown dependencies and related configuration.

@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
remcostoeten Ready Ready Preview Aug 22, 2026 5:12pm

@sourcery-ai

sourcery-ai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR unifies analytics across Remco, PostHog, and Vercel while reducing motion/analytics runtime in the initial bundle by lazy-loading heavy UI (contact/resume drawers) and replacing motion/react hooks with lightweight custom hooks, alongside small layout, accessibility, and styling refinements and removal of unused dependencies.

Sequence diagram for lazy-loading footer drawers

sequenceDiagram
    actor User
    participant Trigger as Footer trigger
    participant Loader as Lazy loader
    participant Drawer as Contact or resume drawer

    User->>Trigger: onPointerEnter or onFocus
    Trigger->>Loader: setLoad(true)
    Loader->>Drawer: Import component
    User->>Trigger: onClick
    Trigger->>Loader: setLoad(true), setOpen(true)
    Loader->>Drawer: Render with initialOpen=true
Loading

Flow diagram for motion-free viewport animation hooks

flowchart LR
    Component[AnimatedNumber or stagger layer] --> InView[useInViewOnce]
    InView --> Observer[IntersectionObserver]
    Observer --> Visible[Enable animation once visible]
    Component --> Reduced[useReducedMotion]
    Reduced --> MediaQuery[prefers-reduced-motion]
    MediaQuery --> Motion[Respect reduced motion preference]
Loading

File-Level Changes

Change Details Files
Unify analytics integration via @remcostoeten/analytics-manager and simplify runtime observers.
  • Replace lazy-loaded Remco, Vercel, and PostHog analytics components with a unified AnalyticsProvider setup using analytics-manager.
  • Add an analytics manager configuration that conditionally wires Remco ingest, PostHog client, and Vercel based on environment and keys.
  • Change PostHog initialization to disable automatic pageview capture so pageviews are driven by the analytics-manager hook.
  • Add explicit performance, scroll, and time-on-page observers using the Remco analytics SDK tied to the ingest URL and project ID.
src/core/analytics/index.tsx
src/core/analytics/manager.ts
src/core/analytics/posthog.tsx
Lazy-load contact and resume drawers to keep motion/vaul and related UI out of the initial footer bundle.
  • Add a lazy contact popover wrapper that preloads on hover/focus and opens with initial state, using React.lazy and Suspense.
  • Update the existing contact popover to accept an initialOpen prop so the lazy wrapper can control first-open state.
  • Add a lazy resume drawer wrapper that preloads on hover/focus and passes initialOpen into the resume drawer.
  • Update the resume drawer to support initialOpen via Drawer.Root defaultOpen and work with the lazy wrapper.
  • Switch the footer to render lazy contact and resume components instead of the eager versions.
src/components/contact/contact-popover.tsx
src/components/contact/lazy-contact-popover.tsx
src/components/layout/footer.tsx
src/components/lazy-resume-drawer.tsx
src/components/resume-drawer.tsx
Replace motion/react view and reduced-motion hooks with custom IntersectionObserver and media-query hooks to avoid pulling motion into always-mounted components.
  • Introduce a useInViewOnce hook that observes a ref via IntersectionObserver with configurable root margin and disconnects after first intersection.
  • Introduce a useReducedMotion hook that listens to the prefers-reduced-motion media query and exposes a boolean flag.
  • Update AnimatedNumber to use useInViewOnce and the new reduced-motion hook instead of motion/react’s useInView and useReducedMotion.
  • Update the stagger system hook to use useInViewOnce and the new reduced-motion hook, keeping behavior but removing motion dependency from these paths.
src/hooks/use-in-view-once.ts
src/hooks/use-reduced-motion.ts
src/components/ui/effects/animated-number.tsx
src/components/ui/stagger-system.tsx
Remove markdown and Geist font dependencies and implement a lightweight description renderer for work experience.
  • Drop Geist font imports and font variable usage from the root layout, reverting to a plain font-sans class.
  • Remove react-markdown and Geist from package.json and mark react-markdown as no longer transpiled in Next config.
  • Replace ReactMarkdown-based rendering of position descriptions in work experience with a simple parser that splits lines into paragraphs and bullet lists.
src/app/layout.tsx
next.config.ts
package.json
src/components/ui/work-experience.tsx
Refine layout, accessibility, and miscellaneous UI styling for breadcrumbs, skeletons, cards, tool content, and command button.
  • Simplify breadcrumbs by removing Suspense/useSearchParams, computing lang from window.location.search via a custom hook, and slightly increasing text contrast.
  • Adjust month label styling in activity skeleton and various tool content elements to use text-muted-foreground instead of lower-opacity foreground.
  • Remove redundant aria-label/id wiring from package and tool cards while adding an aria-label to the mobile command button to clarify its purpose.
  • Tweak link/card attributes and classes to better align with current design and accessibility expectations.
src/components/layout/breadcrumbs.tsx
src/components/ui/skeletons/section-skeletons.tsx
src/components/packages/package-card.tsx
src/components/vim-status-bar.tsx
src/features/miscellaneous/components/tool-card.tsx
src/features/miscellaneous/components/tool-seo-content.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3bc5fcad-1a22-4fe7-8e9b-7e1e0128c490


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@remcostoeten

Copy link
Copy Markdown
Owner Author

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/components/contact/lazy-contact-popover.tsx" line_range="22-25" />
<code_context>
+		<div className="relative inline-block text-left">
+			<button
+				type="button"
+				aria-haspopup="dialog"
+				aria-expanded={false}
+				onPointerEnter={onLoad}
+				onFocus={onLoad}
+				onClick={onOpen}
+				className="text-muted-foreground hover:text-foreground transition-colors text-sm font-medium"
</code_context>
<issue_to_address>
**issue (bug_risk):** The lazy contact trigger hard-codes `aria-expanded={false}`, and the resume trigger exposes no expanded state at all; while the lazy module is loading after activation, assistive technology is told that the control is closed even though the user has requested it to open.

**Triggers:** When a user activates the trigger before its lazy module has finished loading.

**Suggested fix:** Pass the open state into `Trigger` and expose it through `aria-expanded` (and an appropriate relationship to the pending dialog/drawer).
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and this changes production behavior to automatically send pageview, performance, scroll, time-on-page, and PostHog telemetry to external analytics services. Reverting stops future collection but cannot retract data already transmitted and retained by those services.

Blocking findings: src/components/contact/lazy-contact-popover.tsx:25


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +22 to +25
aria-haspopup="dialog"
aria-expanded={false}
onPointerEnter={onLoad}
onFocus={onLoad}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The lazy contact trigger hard-codes aria-expanded={false}, and the resume trigger exposes no expanded state at all; while the lazy module is loading after activation, assistive technology is told that the control is closed even though the user has requested it to open.

Triggers: When a user activates the trigger before its lazy module has finished loading.

Suggested fix: Pass the open state into Trigger and expose it through aria-expanded (and an appropriate relationship to the pending dialog/drawer).

@remcostoeten
remcostoeten merged commit c88bf0c into master Aug 22, 2026
4 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.

1 participant