Using components
After @reframejs/cli add finishes, import the component from the managed
framer/components directory. The public component facade handles the normal
component styling, so a separate stylesheet import is not required.
If you initialized with the default path, the import looks like this:
import Button from "./components/framer/components/button";
export default function CallToAction() {
return <Button variant="Primary Button" buttonText="Get started" />;
}If you initialized with --path src/ui, use ./ui/framer/components/button instead. The import path always follows the parent directory selected during @reframejs/cli init.
Compose exported components
Each export is an independent React component. A small composition is usually enough to verify an installation:
import Button from "./components/framer/components/button";
import SmallContactCard from "./components/framer/components/small-contact-card";
export default function ContactSection() {
return (
<section>
<SmallContactCard
title="Have a question?"
description="Send us a message and we will get back to you."
linkText="Contact support"
link="/contact"
/>
<Button buttonText="Get in touch" variant="Primary Button" link="/contact" />
</section>
);
}This is an illustration, not a required page structure. Use the components you installed with your own layout, routes, and application logic. Your exports may expose different names, variants, or properties; in TypeScript, the generated facade provides autocomplete and reports invalid values.
Generated files
Reframe keeps generated files together so they are easy to identify and update:
framer/
components/
button.tsx # typed public facade in a TypeScript project
button.jsx # public JavaScript entry point
button.runtime.jsx # generated Framer runtime implementation
assets/ # images, fonts, and other export assets
meta/
reframe.json # local export registry, versions, and checksums
styles/
button.css # styles owned by the export, when present
styles.css # imports the generated component stylesThe CLI may add more component files and assets as you install more exports. A
TypeScript project receives a typed facade, a JavaScript entry point, and the
underlying runtime implementation. The runtime preserves Framer behavior while
the public facades provide the import path you use in application code. A
JavaScript project receives the public .jsx entry point without the typed
.tsx facade.
TypeScript and JavaScript
In a TypeScript project, import the component normally. The .tsx facade is resolved automatically:
import Button from "./framer/components/button";
export function SaveButton() {
return <Button buttonText="Save changes" variant="Primary Button" />;
}Do not import the .jsx runtime directly in application code unless you have a specific reason to bypass the typed facade. You do not need a separate TypeScript configuration for each component.
In a JavaScript project, the same import resolves to the generated JavaScript entry point:
import Button from "./framer/components/button";
export default function SaveButton() {
return <Button buttonText="Save changes" />;
}The CLI chooses the public entry point based on the project it detects.
TypeScript projects receive the .tsx facade, which imports the generated
runtime internally. JavaScript projects receive the public .jsx entry point.
These generated files stay inside the managed framer directory and are not
additional application entry points you need to configure.
Variants
Framer variants become a variant prop. For example, a button may expose values such as Primary Button and Secondary Button:
<Button buttonText="Learn more" variant="Secondary Button" />The available values are generated from the published component. Use your editor's TypeScript suggestions or inspect the component facade when you need the exact list.
Components that expose breakpoint-specific variants also provide a .Responsive entry point:
<Button.Responsive
variants={{
base: "Primary Button",
md: "Secondary Button",
}}
buttonText="Get started"
/>Breakpoint keys may include base, sm, md, lg, xl, and 2xl. Only use keys and variant values exposed by that component's generated facade.
Assets and nested dependencies
Images, fonts, and other files referenced by an export are copied into framer/assets. Generated modules resolve those assets relative to the component, so moving individual files out of the managed directory can break the component.
If a component uses another generated runtime dependency, the CLI includes the
required files and records them in framer/meta/reframe.json. It also scans the
generated imports and installs missing external packages with the package
manager detected in your project. This is important for exports that use
libraries such as three, gsap, or another package that is not already in
your package.json.
Install components with the CLI rather than copying one generated file by hand; this keeps the dependency and checksum metadata accurate. If your package manager asks you to approve a build script, follow that prompt and rerun the command.
Components that need a layout size
Some exports—especially WebGL, canvas, and other graphics components—cannot render until their container has a non-zero width and height. Give those components a real box in your application:
import InteractiveScene from "./framer/components/interactive-scene";
export default function SceneSection() {
// A width and height prevent a canvas from initializing at 0 × 0.
return (
<InteractiveScene style={{ width: "100%", height: 420 }} />
);
}If the generated facade exposes width and height props, you can pass those
instead. The CLI can install the component's imported packages, but it cannot
infer the dimensions your page design needs.
Updating safely
Your application should import generated components, but application-specific wrappers and styles should live outside framer/. When you run @reframejs/cli add again after a new publish, Reframe updates only files owned by the export and leaves your routes, pages, wrappers, and unrelated CSS alone.