Framer code components and overrides in a Next.js project

Framer code components and overrides in Next.js: where they land, how they load after hydration, and how to tighten their TypeScript types.

Published
Reading time
6 min
Deframer cover: “Components, still yours.” Beside it, a list of Components, Overrides and TypeScript with TypeScript selected
On this page7 sections

When Deframer converts a published Framer site to a Next.js App Router project in TypeScript, the site's own code components and overrides go into src/code/, and code that came from outside the project (marketplace components, shared modules, files imported from vendors' CDNs) goes into src/vendor/. Code that needs the browser loads after hydration: components through next/dynamic, overrides through the kit's lazyOverride. Because Framer's editor never type-checks code components, a project that contains them builds with typescript: { ignoreBuildErrors: true }, and you can tighten the types file by file with npx tsc --noEmit.

This post explains what each folder holds, how the code is loaded, what changes for React 19, and a practical path to strict types.

Two folders, two kinds of ownership

The split between src/code/ and src/vendor/ tells you who wrote the code, which in turn tells you how freely you should edit it.

Folder

What's in it

How to treat it

src/code/

The code components and overrides from the site's own code folders in Framer, kept in their folders, file names in kebab-case

Your code. Edit, refactor and type it like any other file in the project.

src/vendor/

Marketplace components, shared modules, and modules the site imported from a URL

Code from outside the project. Edit when needed, but note what you changed.

src/vendor/lib/

Helpers and libraries that only the vendored files import

Treat as third-party internals.

src/lib/deframer/

The runtime kit, imported as @/deframer

An original reimplementation of the runtime APIs the generated code uses. Part of your project; change it if you need to.

Modules a site imported from a URL at runtime are copied into src/vendor/, so the converted project does not fetch code from vendors' CDNs at runtime. Code modules a site imports from framer.com (for example icon packs) are an exception and stay remote by design.

What a converted code component looks like

Code components keep their original logic. Imports from the framer package point at the kit instead, and framer-motion imports become motion/react. A counter component from a real converted project starts like this:

tsx
"use client";

import { useState, useEffect, useRef } from "react";
import { motion } from "motion/react";
import { addPropertyControls, ControlType } from "@/deframer";

export function Counter({
  start = 0,
  end = 100,
  speed = 100,
  loop = false,
  startOnViewport = false,
  // …
}: any) {
  // the component's own logic, unchanged
}

addPropertyControls is still there, so the file stays close to its source, but there is no visual editor any more. The values Framer's property panel used to set are now passed as props by the generated views, and the defaults in the function signature apply when a prop is missing.

How browser-only code is loaded

Some code components need window, document, canvas or WebGL as soon as they load. Rendering them on the server would fail or produce markup that doesn't match the browser. Deframer finds this code statically during conversion (it never executes the site's code) and loads it after hydration:

  • Components are loaded with next/dynamic, so they render in the browser only.
  • Overrides are wrapped with the kit's lazyOverride, so the override applies once the page has hydrated.

The result page lists these under "Components that render only in the browser." That notice is information, not an error: the components still work, they just appear after the page's server HTML. If one sits above the fold, it is worth reserving its space in CSS so the layout doesn't jump when it mounts; the post on performance tuning covers that in more detail.

If you later make such a component safe for server rendering (by moving window access into useEffect, for example), you can import it normally and remove the dynamic wrapper.

React 19 and older packages

The converted project uses React 19 and Next.js 16. Some code components depend on npm packages that only declared support for React 18. Deframer handles this in two ways, and the result page tells you which happened:

  1. "Packages upgraded to support React 19." The package was moved to the closest version that accepts React 19. Check the package's changelog if the component behaves differently.
  2. "Components built for React 18 that may not render." No compatible version was found. Test these components first. Your options are to find a maintained alternative, update the package yourself, or replace the component.

The kit also bridges some React 18 behavior that Framer code relies on, such as defaultProps on function components. Other notices to watch for in this area are "Packages not found on npm" and "Imports that couldn't be resolved"; both point at specific files to review.

Why ignoreBuildErrors is on, and how to turn it off

Framer's code editor doesn't type-check code components, so real sites can contain genuine type errors that never mattered before. A project that contains code components therefore ships with this in next.config.ts, including the comment:

ts
const nextConfig: NextConfig = {
  // `next build` type-checks the project, as `npx tsc --noEmit` does. The site's code components
  // (src/code, src/vendor) were written in a site builder's editor, which never type-checks them: what
  // TypeScript reports in them must not block builds.
  typescript: { ignoreBuildErrors: true },
  // …
};

A project without code components builds with Next's type check on. Either way, npx tsc --noEmit reports every error, so you always know where you stand.

Tightening types gradually

You don't need to fix every error before you ship. A steady approach works better:

  1. Get a baseline. Run npx tsc --noEmit and save the output. Count errors per file.
  2. Start with src/code/. This is code your team will maintain. Replace any props with an interface:
tsx
   type CounterProps = {
     start?: number;
     end?: number;
     speed?: number;
     loop?: boolean;
     startOnViewport?: boolean;
   };

   export function Counter({ start = 0, end = 100, speed = 100, loop = false, startOnViewport = false }: CounterProps) {
     // …
   }

The addPropertyControls call in the same file is a good guide to which props exist and their types.

  1. Type refs and events. Untyped useRef(null) and implicit event parameters are common sources of errors; give them their element types.
  2. Leave library builds for last. Bundled or minified libraries in src/vendor/lib/ may carry // @ts-nocheck with the reason in their header. Replacing them with the npm package, where one exists, is usually better than typing them.
  3. Re-run npx tsc --noEmit after each file and keep the count going down.
  4. When the count reaches zero, remove ignoreBuildErrors from next.config.ts so next build enforces types from then on.

Doing this in small commits makes review easy. See maintaining a converted site with Git for a branch workflow.

Re-converting after code changes in Framer

If your team keeps editing code components in Framer, each republish and conversion produces fresh files in src/code/, without your type fixes. Convert into a branch and diff it against your edited code rather than overwriting it. Converting is free, but a republished site makes a new project, and downloading it uses a credit; how credits work explains when a download is free. (Deframer is an independent tool, not affiliated with Framer.)

When the remaining issues are about rendering rather than types, the post on common conversion issues goes through each notice.

FAQ

Do Framer overrides still work after conversion?

Yes. Overrides from the site's code files are carried over into src/code/ and applied to the same layers, and the ones that need the browser are applied after hydration through the kit's lazyOverride.

Does the project load any code from Framer at runtime?

The project contains no Framer runtime; the kit replaces it. Modules a site imported from vendors' CDNs are copied into src/vendor/, and only code modules imported from framer.com, such as icon packs, stay remote by design.

Is it safe to remove `ignoreBuildErrors` straight away?

Only if npx tsc --noEmit reports no errors. Otherwise next build will fail on the first type error, so fix the reported errors first.

Can I edit the kit in `src/lib/deframer`?

Yes. It is part of your project and you may use and change it. Only the kit modules your site uses are included.

What if a component renders blank after conversion?

Check the result page's notices for that component, then the browser console. Browser-only components and React 18 packages are the most common causes.