CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-gatsby

Blazing fast modern site generator for React with GraphQL data layer and plugin ecosystem

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

browser-apis.mddocs/

Browser APIs

Client-side plugin APIs for handling routing, service workers, rendering customization, and user interactions through the gatsby-browser.js file.

Capabilities

GatsbyBrowser Interface

Main interface for client-side plugin APIs that control browser behavior, routing, rendering, and user interactions.

/**
 * Main interface for gatsby-browser.js plugin APIs
 */
interface GatsbyBrowser {
  /** Client-side entry point */
  onClientEntry?: (args?: object, pluginOptions?: PluginOptions) => void;
  /** Initial client render complete */
  onInitialClientRender?: (args?: object, pluginOptions?: PluginOptions) => void;
  /** Route change occurred */  
  onRouteUpdate?: (args: RouteUpdateArgs, pluginOptions?: PluginOptions) => void;
  /** Before route change */
  onPreRouteUpdate?: (args: RouteUpdateArgs, pluginOptions?: PluginOptions) => void;
  /** Delayed route update */
  onRouteUpdateDelayed?: (args: RouteUpdateDelayedArgs, pluginOptions?: PluginOptions) => void;
  /** Disable core prefetching */
  disableCorePrefetching?: (args?: object, pluginOptions?: PluginOptions) => boolean;
  /** Before prefetch pathname */
  onPrefetchPathname?: (args: PrefetchPathnameArgs, pluginOptions?: PluginOptions) => void;
  /** After prefetch pathname */
  onPostPrefetchPathname?: (args: PrefetchPathnameArgs, pluginOptions?: PluginOptions) => void;
  /** Register service worker */
  registerServiceWorker?: (args?: object, pluginOptions?: PluginOptions) => boolean;
  /** Service worker active */
  onServiceWorkerActive?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;
  /** Service worker installed */
  onServiceWorkerInstalled?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;
  /** Service worker redundant */
  onServiceWorkerRedundant?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;
  /** Service worker update found */
  onServiceWorkerUpdateFound?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;
  /** Service worker update ready */
  onServiceWorkerUpdateReady?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;
  /** Replace hydrate function */
  replaceHydrateFunction?: () => (element: React.ReactElement, container: Element, callback?: () => void) => void;
  /** Control scroll behavior */
  shouldUpdateScroll?: (args: ShouldUpdateScrollArgs, pluginOptions?: PluginOptions) => boolean | string | [number, number];
  /** Wrap page element */
  wrapPageElement?: (args: WrapPageElementBrowserArgs, pluginOptions?: PluginOptions) => React.ReactElement;
  /** Wrap root element */
  wrapRootElement?: (args: WrapRootElementBrowserArgs, pluginOptions?: PluginOptions) => React.ReactElement;
}

Client Lifecycle APIs

Handle client-side initialization and rendering lifecycle events.

/**
 * Client entry point - called when the app first loads
 */
onClientEntry?: (args?: object, pluginOptions?: PluginOptions) => void;

/**
 * Initial client render complete - called after React hydration
 */
onInitialClientRender?: (args?: object, pluginOptions?: PluginOptions) => void;

/**
 * Replace the default React hydrate function
 */
replaceHydrateFunction?: () => (
  element: React.ReactElement,
  container: Element,
  callback?: () => void
) => void;

Usage Examples:

// gatsby-browser.js - Client lifecycle
exports.onClientEntry = () => {
  // Initialize analytics
  if (typeof window !== "undefined" && window.gtag) {
    window.gtag("config", "GA_MEASUREMENT_ID");
  }
  
  // Load polyfills
  if (!window.IntersectionObserver) {
    import("intersection-observer");
  }
};

exports.onInitialClientRender = () => {
  // Set up global event listeners
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
      console.log("Page is hidden");
    } else {
      console.log("Page is visible");
    }
  });
  
  // Initialize third-party libraries
  if (typeof window !== "undefined" && window.Prism) {
    window.Prism.highlightAll();
  }
};

// Custom hydration for React 18
exports.replaceHydrateFunction = () => {
  return (element, container, callback) => {
    const { hydrateRoot } = require("react-dom/client");
    hydrateRoot(container, element);
    if (callback) callback();
  };
};

Routing APIs

Handle navigation, route changes, and prefetching behavior.

/**
 * Route update arguments
 */
interface RouteUpdateArgs {
  location: WindowLocation;
  prevLocation?: WindowLocation;
}

/**
 * Delayed route update arguments  
 */
interface RouteUpdateDelayedArgs {
  location: WindowLocation;
  prevLocation?: WindowLocation;
}

/**
 * Called on every route change
 */
onRouteUpdate?: (args: RouteUpdateArgs, pluginOptions?: PluginOptions) => void;

/**
 * Called before route change
 */
onPreRouteUpdate?: (args: RouteUpdateArgs, pluginOptions?: PluginOptions) => void;

/**
 * Called when route update is delayed
 */
onRouteUpdateDelayed?: (args: RouteUpdateDelayedArgs, pluginOptions?: PluginOptions) => void;

Usage Examples:

// gatsby-browser.js - Route handling
exports.onRouteUpdate = ({ location, prevLocation }) => {
  // Track page views
  if (typeof window !== "undefined" && window.gtag) {
    window.gtag("config", "GA_MEASUREMENT_ID", {
      page_location: window.location.href,
      page_path: location.pathname,
    });
  }
  
  // Close mobile menu on navigation
  const mobileMenu = document.querySelector(".mobile-menu");
  if (mobileMenu && mobileMenu.classList.contains("open")) {
    mobileMenu.classList.remove("open");
  }
  
  // Scroll to top on new page
  if (prevLocation && location.pathname !== prevLocation.pathname) {
    window.scrollTo(0, 0);
  }
};

exports.onPreRouteUpdate = ({ location }) => {
  // Show loading indicator
  const loader = document.querySelector(".page-loader");
  if (loader) {
    loader.style.display = "block";
  }
};

exports.onRouteUpdateDelayed = ({ location }) => {
  // Handle slow navigation
  console.log("Route update delayed for:", location.pathname);
  
  // Show network error message
  const errorMsg = document.querySelector(".network-error");
  if (errorMsg) {
    errorMsg.style.display = "block";
  }
};

Prefetching APIs

Control and customize resource prefetching behavior.

/**
 * Prefetch pathname arguments
 */
interface PrefetchPathnameArgs {
  pathname: string;
  loadableReady?: Promise<void>;
}

/**
 * Disable core prefetching - return true to disable
 */
disableCorePrefetching?: (args?: object, pluginOptions?: PluginOptions) => boolean;

/**
 * Called before prefetching pathname
 */
onPrefetchPathname?: (args: PrefetchPathnameArgs, pluginOptions?: PluginOptions) => void;

/**
 * Called after prefetching pathname
 */
onPostPrefetchPathname?: (args: PrefetchPathnameArgs, pluginOptions?: PluginOptions) => void;

Usage Examples:

// gatsby-browser.js - Prefetching
exports.disableCorePrefetching = () => {
  // Disable prefetching on slow connections
  return (
    typeof navigator !== "undefined" &&
    navigator.connection &&
    (navigator.connection.effectiveType === "slow-2g" ||
     navigator.connection.effectiveType === "2g")
  );
};

exports.onPrefetchPathname = ({ pathname }) => {
  console.log("Prefetching:", pathname);
  
  // Custom prefetch logic
  if (pathname.startsWith("/blog/")) {
    // Prefetch blog-specific assets
    const link = document.createElement("link");
    link.rel = "prefetch";
    link.href = "/assets/blog-styles.css";
    document.head.appendChild(link);
  }
};

exports.onPostPrefetchPathname = ({ pathname, loadableReady }) => {
  console.log("Prefetched:", pathname);
  
  // Track prefetch completion
  if (typeof window !== "undefined" && window.gtag) {
    window.gtag("event", "prefetch_complete", {
      page_path: pathname,
    });
  }
};

Service Worker APIs

Handle service worker lifecycle and events.

/**
 * Service worker arguments
 */
interface ServiceWorkerArgs {
  serviceWorker?: ServiceWorker;
}

/**
 * Register service worker - return true to register
 */
registerServiceWorker?: (args?: object, pluginOptions?: PluginOptions) => boolean;

/**
 * Service worker became active
 */
onServiceWorkerActive?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;

/**
 * Service worker was installed
 */
onServiceWorkerInstalled?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;

/**
 * Service worker became redundant
 */
onServiceWorkerRedundant?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;

/**
 * Service worker update found
 */
onServiceWorkerUpdateFound?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;

/**
 * Service worker update ready
 */
onServiceWorkerUpdateReady?: (args: ServiceWorkerArgs, pluginOptions?: PluginOptions) => void;

Usage Examples:

// gatsby-browser.js - Service Worker
exports.registerServiceWorker = () => {
  // Only register in production
  return process.env.NODE_ENV === "production";
};

exports.onServiceWorkerActive = () => {
  console.log("Service worker is active");
  
  // Show app ready message
  const updateBanner = document.querySelector(".update-banner");
  if (updateBanner) {
    updateBanner.textContent = "App is ready for offline use";
    updateBanner.classList.add("show");
    setTimeout(() => updateBanner.classList.remove("show"), 3000);
  }
};

exports.onServiceWorkerUpdateReady = () => {
  console.log("Service worker update ready");
  
  // Show update available message
  const updateBanner = document.querySelector(".update-banner");
  if (updateBanner) {
    updateBanner.innerHTML = `
      <div>
        New version available!
        <button onclick="window.location.reload()">Update</button>
      </div>
    `;
    updateBanner.classList.add("show");
  }
};

exports.onServiceWorkerUpdateFound = () => {
  console.log("Service worker update found");
  
  // Show downloading message
  const updateBanner = document.querySelector(".update-banner");
  if (updateBanner) {
    updateBanner.textContent = "Downloading update...";
    updateBanner.classList.add("show");
  }
};

Scroll Management APIs

Control scroll behavior during navigation.

/**
 * Scroll update arguments
 */
interface ShouldUpdateScrollArgs {
  routerProps: {
    location: WindowLocation;
    navigate: NavigateFn;
  };
  getSavedScrollPosition: (location: WindowLocation) => [number, number] | null;
}

/**
 * Control scroll behavior on navigation
 * @returns boolean - true to update scroll, false to prevent
 * @returns string - element selector to scroll to
 * @returns [number, number] - x,y coordinates to scroll to
 */
shouldUpdateScroll?: (
  args: ShouldUpdateScrollArgs,
  pluginOptions?: PluginOptions
) => boolean | string | [number, number];

Usage Examples:

// gatsby-browser.js - Scroll management
exports.shouldUpdateScroll = ({ routerProps, getSavedScrollPosition }) => {
  const { location } = routerProps;
  
  // Don't scroll on hash changes
  if (location.hash) {
    return false;
  }
  
  // Restore saved position for browser back/forward
  const savedPosition = getSavedScrollPosition(location);
  if (savedPosition) {
    return savedPosition;
  }
  
  // Custom scroll behavior for specific routes
  if (location.pathname.startsWith("/docs/")) {
    // Scroll to top for docs pages
    return [0, 0];
  }
  
  if (location.pathname.startsWith("/blog/")) {
    // Preserve scroll position for blog
    return false;
  }
  
  // Default behavior - scroll to top
  return true;
};

Element Wrapping APIs

Wrap page and root elements with custom components.

/**
 * Wrap page element arguments (browser)
 */
interface WrapPageElementBrowserArgs {
  element: React.ReactElement;
  props: PageProps;
}

/**
 * Wrap root element arguments (browser)
 */
interface WrapRootElementBrowserArgs {
  element: React.ReactElement;
}

/**
 * Wrap each page with custom elements
 */
wrapPageElement?: (
  args: WrapPageElementBrowserArgs,
  pluginOptions?: PluginOptions
) => React.ReactElement;

/**
 * Wrap the root element
 */
wrapRootElement?: (
  args: WrapRootElementBrowserArgs,
  pluginOptions?: PluginOptions
) => React.ReactElement;

Usage Examples:

// gatsby-browser.js - Element wrapping
import React from "react";
import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components";
import Layout from "./src/components/Layout";
import store from "./src/store";
import theme from "./src/theme";

// Wrap root with global providers
exports.wrapRootElement = ({ element }) => (
  <Provider store={store}>
    <ThemeProvider theme={theme}>
      {element}
    </ThemeProvider>
  </Provider>
);

// Wrap each page with layout
exports.wrapPageElement = ({ element, props }) => (
  <Layout {...props}>
    {element}
  </Layout>
);

docs

browser-apis.md

components-hooks.md

configuration.md

graphql.md

index.md

node-apis.md

ssr-apis.md

tile.json