Weird build time error

Hello, so I am building a POC using Nextjs, framer-motion, and react-spring, and I’ve encounterd a very weird problem.
I tried solving it by also migrating from app-router to pages-router (didn’t change anything).
So the issue I have is that I get a build-time error:

Creating an optimized production build ...

17:23:34.527

✓ Compiled successfully

17:23:34.528

Collecting page data ...

17:23:34.934

[ReferenceError: document is not defined]

17:23:34.936

17:23:34.937

> Build error occurred

17:23:34.951

[Error: Failed to collect page data for /] { type: 'Error' }

17:23:34.960

ELIFECYCLE Command failed with exit code 1.

17:23:34.982

Error: Command "pnpm build" exited with 1

17:23:35.379

The weirdest part is that I cannot reproduce this locally, I am able to succefully pnpm build && pnpm start

  1. I have also tried overriding the build and install commands to use pnpm
  2. When I was using app-router ALL OF THE LOGIC, that has react-spring and framer had “use client” (the parent component)
  3. Afterwards I migrated to pages-router, and I’ve added a dynamic lazy loading
export const CardLazy = dynamic(() => Promise.resolve(Card), {
  ssr: false,
});

and using it like:


import { LIST } from "../mock";
import { CardLazy } from "./Card";

export const CardList = () => {
  return (
    <ul className="flex flex-col gap-12 w-full max-w-5xl h-full p-4 mx-auto">
      {LIST.map((item) => (
        <li key={item._id}>
          <CardLazy item={item} />
        </li>
      ))}
    </ul>
  );
};

How can I debug this? I cannot reproduce this locally at all!

➜ user-engagement-poc git:(main) ✗ node -v
v20.13.1


  "dependencies": {
    "classnames": "^2.5.1",
    "framer-motion": "^12.0.5",
    "lottie-react": "^2.4.1",
    "moment": "^2.30.1",
    "next": "15.1.6",
    "react": "^19.0.0",
    "react-animated-counter": "^1.7.9",
    "react-dom": "^19.0.0",
    "react-intersection-observer": "^9.15.1",
    "react-spring": "^9.7.5"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.1.6",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"

Hi, @alex-firefly!

Thank you for sharing this much detail! The core problem seems to be that some browser-specific code is being executed during server-side rendering or build time.

Isolate all browser-specific code using dynamic imports and the useEffect hook. For your Card component that uses react-spring and framer-motion, try this approach:

  1. Create a separate file for the client-side only version of your Card component:
// CardClient.js
import { useEffect } from 'react';
import { useSpring, animated } from 'react-spring';
import { motion } from 'framer-motion';

const CardClient = ({ item }) => {
  // Your existing Card component code here
  // Wrap any initialization of react-spring or framer-motion in useEffect
  useEffect(() => {
    // Initialize animations here
  }, []);

  return (
    // Your JSX here
  );
};

export default CardClient;
  1. In your main Card file, use dynamic import:
// Card.js
import dynamic from 'next/dynamic';

const CardClient = dynamic(() => import('./CardClient'), {
  ssr: false,
  loading: () => <p>Loading...</p>,
});

const Card = (props) => {
  return <CardClient {...props} />;
};

export default Card;

This approach ensures that all browser-specific code is only executed on the client side. It should resolve the “document is not defined” error during the build process.

Let us know how you get on!

2 Likes

Thanks a lot, need to try this solution! What worked in the end was downgrading node 22 to node 20 :sweat_smile:

1 Like

Glad this worked for you too! Sometimes it’s that simple. :smiley:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.