Lottie Animations in Next.js: Quick Practical Guide

Discover how to integrate Lottie animations in Next.js with lottie-react, without the classic react-lottie errors

Allan Ransau
Allan RansauFounder of RANSAU SYSTEME — Engineer & Developer
19 September 20254 min read
Cover image for article Lottie Animations in Next.js: Quick Practical Guide

Web

Next.js

#nextjs

#react

#lottie

#react-lottie

#lottie-react

#typescript

You downloaded a great Lottie animation, installed the react-lottie library, and now your Next.js build fails with a document is not defined error. Classic. The problem? The react-lottie library has not been maintained since 2020 and does not support Next.js Server-Side Rendering. The solution exists and it is simple: lottie-react.

Install the Right Library: React-Lottie

The first step is to install the right library. Forget react-lottie, use lottie-react instead:

bash
npm install lottie-react

Next, place your animation JSON files in the public folder of your Next.js project. By convention, create a dedicated subfolder:

plaintext
public/
  └── animations/
      └── loading.json
      └── success.json

If you are working in TypeScript, create a types file for your Lottie components. In your types folder (or src/types), add:

ts
// types/index.ts
export interface LottieProps {
  jsonData: object;
  loop?: boolean;
  className?: string;
}

These types will give you autocompletion and TypeScript validation on your components.

The Solution: Loading the Animation on the Client Side

Here is where most developers go wrong. If you use lottie-react directly in a Next.js Server Component, you will get the dreaded error:

bash
ReferenceError: document is not defined

Why? Because lottie-react depends on lottie-web, which attempts to access the DOM during server-side rendering. Next.js 13+ uses Server Components by default, and the DOM does not exist on the server.

The elegant solution is to split your Lottie component into two separate files: a wrapper that handles dynamic loading, and a client component that does the actual rendering.

The Two-File Pattern

First, create the client component that uses lottie-react:

ts
// components/animations/LottieClient.tsx
'use client'
 
import { LottieProps } from '@/types';
import { useLottie } from 'lottie-react';
 
const LottieClient = ({
    loop = true,
    jsonData,
    className = "w-full",
}: LottieProps) => {
    const defaultOptions = {
        animationData: jsonData,
        loop: loop,
    };
 
    const { View } = useLottie(defaultOptions);
 
    return (
        <div className={className}>{View}</div>
    );
}
 
export default LottieClient;

This component is marked 'use client' on the first line. It contains all the Lottie-related logic and can access the DOM without any issues.

Next, create the wrapper that uses Next.js's dynamic import:

ts
// components/animations/LottieAnimation.tsx
'use client'
 
import { LottieProps } from '@/types';
import dynamic from 'next/dynamic';
import { ComponentType } from 'react';
 
const LottieWrapper: ComponentType<LottieProps> = dynamic(
  () => import('@/components/animations/LottieClient'),
  { ssr: false }
);
 
const LottieAnimation = (props: LottieProps) => {
  return <LottieWrapper {...props} />;
}
 
export default LottieAnimation;

The { ssr: false } parameter is crucial: it tells Next.js to only load this component on the client side, after hydration. During server rendering, Next.js completely ignores this component.

Why It Works

This pattern solves three problems simultaneously:

SSR: The dynamic import with ssr: false prevents Lottie code from executing on the server.

Tree-shaking: The lottie-react library (and its ~82kb minified weight) is only downloaded if the component is actually used on the page.

Maintainability: You always import LottieAnimation, never LottieClient directly. This ensures that no one on your team accidentally uses the component without the protection wrapper.

Using It in Your App

Now that the architecture is in place, using your animations becomes effortless. Import your LottieAnimation component and pass it your animation JSON.

Basic Import and Usage

ts
// app/page.tsx
import LottieAnimation from '@/components/animations/LottieAnimation';
import loadingAnimation from '@/public/animations/loading.json';
 
export default function Home() {
  return (
    <div className="flex justify-center items-center min-h-screen">
      <LottieAnimation 
        jsonData={loadingAnimation}
        loop={true}
        className="w-64"
      />
    </div>
  );
}

The JSON is imported directly as a JavaScript object. Next.js automatically handles the import of .json files without any additional configuration.

Your LottieAnimation component accepts three essential props:

jsonData (required): Your animation's JSON object. Import it from your public/animations/ folder.

loop (optional, default: true): Determines whether the animation should loop indefinitely. Pass false for an animation that plays only once.

className (optional, default: "w-full"): Tailwind or CSS classes to control the size and style of the container.

Usage stays simple and predictable. You control the size via CSS classes, the behavior via the loop prop, and conditional rendering with standard React patterns.

Pro Tips

A few common errors and classic pitfalls:

Error: "Module not found: Can't resolve 'lottie-react'"

You probably installed react-lottie instead of lottie-react. Uninstall and reinstall the correct version:

bash
npm uninstall react-lottie
npm install lottie-react

Error: "document is not defined"

You are using lottie-react directly without the dynamic wrapper. Make sure you import LottieAnimation and not LottieClient.

The animation is not displaying

Check that your JSON file is a valid Lottie export. Test it first on LottieFiles to confirm it works.

The animation is choppy

The JSON is probably too heavy. Reduce the number of keyframes or simplify the shapes in After Effects.

Conclusion

Integrating Lottie animations in Next.js is not complicated when you use the right tools. In summary: install lottie-react, create your two components with the dynamic import pattern, and use them everywhere in your app without worrying about SSR.

This approach works equally well with Next.js 13, 14, or 15, and with both the App Router and the Pages Router. Lottie animations bring real added value to the user experience, and now you know how to implement them properly.

Give it a try.


Are you developing a web application or business software and need technical support? Discover our web and software development services or contact us to discuss your project.

Was this article helpful?

Share this article with your network

In brief

Integrating Lottie animations in Next.js requires avoiding the react-lottie library, which is unmaintained and incompatible with server rendering, in favor of lottie-react. The recommended pattern uses two components: LottieClient.tsx marked 'use client' for DOM rendering, and LottieAnimation.tsx which imports it via next/dynamic with the ssr: false option, eliminating hydration errors. This approach works with Next.js 13, 14, and 15 with the App Router.

Key takeaways

  • Use lottie-react (not react-lottie) because react-lottie has been unmaintained since 2020 and is incompatible with Next.js server rendering.
  • The two-file pattern (LottieClient.tsx + LottieAnimation.tsx with ssr:false) eliminates hydration errors by isolating lottie-web on the client side.
  • This pattern is compatible with Next.js 13, 14, and 15 in both App Router and Pages Router without additional configuration.