### API Route Management with Hono (JavaScript)
Source: https://developers.framer.wiki/developers/fetch/examples
An example using the Hono framework to manage multiple API routes within a backend. It demonstrates setting up a basic Hono application, applying CORS middleware, and defining GET endpoints for a root path and a weather API.
```javascript
import { Hono } from 'hono'
import { cors } from 'hono/cors'
const app = new Hono()
app.use('*', cors())
app.get('/', (c) => {
return c.text('Hono!')
})
app.get('/weather', async (c) => {
const weather = await fetch("api.weather.com").then(d => d.json())
return c.json(weather)
})
export default app
```
--------------------------------
### Create a Basic React Button Component
Source: https://developers.framer.wiki/developers/components/examples
This snippet shows the creation of a fundamental React button component. It serves as a starting point for more complex components and has no external dependencies.
```jsx
export default function Button(props) {
return
Hello
}
```
--------------------------------
### Simple Backend Function for Fetch Requests (JavaScript)
Source: https://developers.framer.wiki/developers/fetch/examples
A basic backend function that returns a random greeting. It demonstrates a simple GET request handling and JSON response. This code is suitable for most JavaScript backend setups like Cloudflare Workers or Val Town.
```javascript
function worker(request) {
// Return a random greeting from this list
const greetings = ["Hello!", "Welcome!", "Hi!", "Heya!", "Hoi!"];
const index = Math.floor(Math.random() * greetings.length);
/* ...CORS Headers... */
return Response.json({ data: greetings[index] }, { headers });
}
```
--------------------------------
### Render Page Preview using usePublishInfo Hook (React)
Source: https://developers.framer.wiki/developers/plugins/site
An example demonstrating how to use the `usePublishInfo` hook to get the staging URL and render a preview of the current page within an iframe. It includes a conditional message if the site has not been published yet.
```javascript
const publishInfo = usePublishInfo()
const stagingUrl = publishInfo?.staging?.currentPageUrl
if (!stagingUrl) return "Publish your Site"
return (
)
```
--------------------------------
### Install Framer Plugin for Localization
Source: https://developers.framer.wiki/developers/plugins/localization
Installs the framer-plugin package, which is required to use the Localization Plugin APIs. Ensure your project is opted into the Beta channel before installation.
```bash
npm install framer-plugin
```
--------------------------------
### Make Authenticated Request with Bearer Token (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/oauth
Demonstrates how to make an authenticated API request using a 'Bearer' token in the Authorization header. This example specifically shows how to fetch user info from Google's API.
```javascript
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo",
{
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
}
);
const profile = await response.json();
console.log(profile); // Prints the user's profile info!
```
--------------------------------
### Add Styling to a React Button Component
Source: https://developers.framer.wiki/developers/components/examples
This example extends the basic React button component by incorporating inline styling using the `style` attribute. It demonstrates a standard React approach to component styling.
```jsx
export default function Button(props) {
const style = {
display: "inline-block",
backgroundColor: "orange",
padding: 8,
}
return
Hello
}
```
--------------------------------
### Manage Application State with React Store
Source: https://developers.framer.wiki/developers/overrides/examples
This example demonstrates managing application state using Framer's `createStore`. It includes two overrides: `withCount` to display the current count and `withIncrement` to update the count when an action is triggered. This is useful for creating interactive components and managing data flow within your application.
```typescript
import type { ComponentType } from "react"
import { createStore } from "https://framer.com/m/framer/store.js@^1.0.0"
const useStore = createStore({ count: 0 })
export const withCount = (Component): ComponentType => {
return (props) => {
const [store, setStore] = useStore()
return
}
}
export const withIncrement = (Component): ComponentType => {
return (props) => {
const [store, setStore] = useStore()
const onTap = () => setStore({ count: store.count + 1 })
return
}
}
```
--------------------------------
### Getting Nodes
Source: https://developers.framer.wiki/developers/plugins/nodes
This section details various methods for retrieving nodes from a Framer project, including getting the current selection, subscribing to selection changes, fetching a node by its ID, and querying nodes based on type or attributes.
```APIDOC
## Getting Nodes
### Description
Methods for retrieving nodes from the current selection or the entire project.
### Methods
- `framer.getSelection()`: Returns an array of currently selected nodes.
- `framer.subscribeToSelection(callback)`: Subscribes to changes in the node selection. The callback function receives the updated selection.
- `framer.getNode(nodeId)`: Retrieves a specific node by its unique ID.
- `framer.getNodesWithType(nodeType)`: Returns an array of all nodes of a specified type within the project.
- `framer.getNodesWithAttribute(attributeName)`: Returns an array of all nodes that have a specific attribute set.
- `framer.getNodesWithAttributeSet(attributeName)`: Returns an array of all nodes where a specific attribute has been explicitly set.
### Usage Examples
Get current selection:
```javascript
const selection = await framer.getSelection()
```
Subscribe to selection changes:
```javascript
function useSelection() {
const [selection, setSelection] = useState([])
useEffect(() => {
return framer.subscribeToSelection(setSelection)
}, [])
return selection
}
```
Get node by ID:
```javascript
const node = await framer.getNode("some-node-id")
```
Get all frame nodes:
```javascript
const frameNodes = await framer.getNodesWithType("FrameNode")
```
Get nodes with a background color:
```javascript
const nodes = await framer.getNodesWithAttribute("backgroundColor")
```
Querying within a selection:
```javascript
const selection = await framer.getSelection()
const selectedNode = selection.length === 1 ? selection[0] : null
if (selectedNode) {
const frameNodes = await selectedNode.getNodesWithType("FrameNode")
const nodes = await selectedNode.getNodesWithAttribute("backgroundColor")
const nodes = await selectedNode.getNodesWithAttributeSet("backgroundColor")
}
```
Example hook to get all background images:
```javascript
function useAllBackgroundImages() {
const [images, setImages] = useState([])
useEffect(() => {
let active = true
async function run() {
const nodes = await framer.getNodesWithAttributeSet("backgroundImage")
const uniqueImages = new Map()
for (const item of nodes) {
const image = item.backgroundImage
if (!image) continue
uniqueImages.set(image.id, image)
}
if (!active) return
setImages(Array.from(uniqueImages.values()))
}
run()
return () => {
active = false
}
}, [])
return images
}
```
```
--------------------------------
### Customize Component Instance Size
Source: https://developers.framer.wiki/developers/plugins/components
This example shows how to insert a component instance with specific dimensions. The `attributes` object within `framer.addComponentInstance` allows you to define properties like `width` and `height` for the component.
```javascript
framer.addComponentInstance({
url,
attributes: { width: "900px", height: "600px" }
})
```
--------------------------------
### Framer Component Sharing URLs
Source: https://developers.framer.wiki/developers/components/sharing
Examples of URLs for sharing Framer components. The first URL points to the latest version, while the second includes a Version ID for a specific version.
```text
https://framer.com/m/Button-5TDo.js
https://framer.com/m/Button-5TDo.js@rXSyWUm5fMakCtp8K3gM
```
--------------------------------
### Token Authentication for Fetch API Wrapper (JavaScript)
Source: https://developers.framer.wiki/developers/fetch/examples
An asynchronous JavaScript function showing how to securely use an API key with a Fetch request. It demonstrates fetching data from an API like IPinfo that requires a token, by storing the token in an environment variable and passing it in the request.
```javascript
async fetch(request, env) {
// Call to source API
const locationURL = new URL(`https://ipinfo.io/${clientIP}`)
const IPinfoToken = env.IPINFO_TOKEN
locationURL.searchParams.set("token", IPinfoToken)
const locationResponse = await fetch(locationURL.href)
/* ...CORS Headers... */
return new Response(locationResponse, { headers });
}
```
--------------------------------
### Image Processing with Canvas (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/assets
Provides an example of processing raw image bytes using an HTML canvas. It retrieves an image, loads its bitmap, draws it onto a canvas (with an example of horizontal inversion), and then converts the canvas content back into bytes for re-uploading as a new image.
```javascript
// Get the selected image in framer
const image = await framer.getImage()
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
// Load the image bytes into an ImageBitmap that canvas supports
const bitmap = await image.loadBitmap()
// Set the height of the canvas to the height of the image
ctx.canvas.width = img.width;
ctx.canvas.height = img.height;
// Here we horizontally invert the image bitmap.
ctx.scale(-1, 1);
ctx.drawImage(bitmap, -bitmap.width, 0);
const result = await bytesFromCanvas(canvas);
await framer.addImage({
image: { bytes: result, mimeType },
});
```
--------------------------------
### Removing Data
Source: https://developers.framer.wiki/developers/plugins/storing-data
Instructions on how to remove both project-level and node-level plugin data by setting the value to null. Includes examples for removing specific keys and all data.
```APIDOC
## Removing Data
### Description
Remove plugin data from either the project level or a specific node by setting the data value to `null`. This action effectively deletes the key-value pair.
### Method
`framer.setPluginData(key: string, value: null)` (for project data)
`node.setPluginData(key: string, value: null)` (for node data)
### Endpoint
N/A
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
N/A
### Request Example
```javascript
// Remove data from the project.
await framer.setPluginData('keyToRemove', null);
// Remove data from a node.
const node = await framer.getNode('nodeId');
await node.setPluginData('nodeDataToRemove', null);
// Remove all global project data.
const keys = await framer.getPluginDataKeys();
for (const key of keys) {
await framer.setPluginData(key, null);
}
// Remove all node data (similar loop using node.getPluginDataKeys() and node.setPluginData(key, null))
```
### Response
#### Success Response (200)
- `setPluginData`: void
#### Response Example
N/A (No response body for deletion operations)
```
--------------------------------
### Module URL for Specific Component Version
Source: https://developers.framer.wiki/developers/plugins/components
This example illustrates a Framer Module URL that points to a specific version of a component. The Save ID, located after the '@' symbol, ensures the URL consistently references that exact version.
```text
https://framer.com/m/user/component-name@save-id
```
--------------------------------
### Hiding and Conditionally Displaying Plugin UI
Source: https://developers.framer.wiki/developers/plugins/interface
These JavaScript examples illustrate how to hide the plugin's user interface using `framer.hideUI` and how to conditionally display it based on a `needsLogin` variable. This allows for dynamic control over UI visibility within the Framer environment.
```javascript
framer.hideUI()
// It's possible to conditionally display a UI
if (needsLogin) {
framer.showUI()
} else {
framer.hideUI()
}
```
--------------------------------
### Order Breakpoints Automatically (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/styles
Demonstrates how Framer automatically orders breakpoints from largest to smallest. This example shows the output after defining breakpoints in a non-sequential order, highlighting the automatic sorting.
```javascript
const textStyle = await framer.createTextStyle({
minWidth: 1280,
breakpoints: [
{ minWidth: 320 }
{ minWidth: 1024 },
{ minWidth: 960 },
{ minWidth: 720 },
]
})
console.log(textStyle.breakpoints)
// Output:
// [
// { minWidth: 1024 },
// { minWidth: 960 },
// { minWidth: 720 },
// { minWidth: 320 }
// ]
```
--------------------------------
### Image Processing with Canvas
Source: https://developers.framer.wiki/developers/plugins/assets
Provides utilities and examples for performing raw image manipulation using HTML canvas, allowing for operations like inverting images.
```APIDOC
## POST /framer/processImage
### Description
This section describes a conceptual process for manipulating image data using raw bytes and an HTML canvas. It involves getting an image, loading its bitmap, drawing it onto a canvas with transformations, and then converting the canvas content back into image bytes for re-uploading.
### Method
POST (Conceptual - actual implementation depends on `bytesFromCanvas` utility)
### Endpoint
Conceptual: Involves `framer.getImage()`, canvas operations, and `framer.addImage()`.
### Parameters
(No direct API parameters, relies on image object from `framer.getImage()` and custom `bytesFromCanvas` function)
### Request Example
```javascript
// Get the selected image in framer
const image = await framer.getImage();
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Load the image bytes into an ImageBitmap that canvas supports
const bitmap = await image.loadBitmap();
// Set the height of the canvas to the height of the image
ctx.canvas.width = bitmap.width;
ctx.canvas.height = bitmap.height;
// Here we horizontally invert the image bitmap.
ctx.scale(-1, 1);
ctx.drawImage(bitmap, -bitmap.width, 0);
// Assuming bytesFromCanvas is a utility function
const result = await bytesFromCanvas(canvas);
const mimeType = "image/png"; // Or determine dynamically
await framer.addImage({
image: { bytes: result, mimeType },
});
```
### Response
#### Success Response (200)
- **image** (object) - The processed and re-uploaded image object.
#### Response Example
```json
{
"image": {
"id": "img_jkl012",
"url": "https://framer.com/images/processed.png",
"name": "Processed Image",
"altText": ""
}
}
```
```
--------------------------------
### Set, Get, and Get Keys for Node Data with Framer
Source: https://developers.framer.wiki/developers/plugins/storing-data
This code illustrates how to manage data associated with a specific node on the Framer canvas. It includes functions to set plugin data (`setPluginData`), retrieve specific data (`getPluginData`), and obtain all available data keys for a node (`getPluginDataKeys`). Similar to global data, node data entries are limited to strings, with a 2kB limit per entry and 4kB per node.
```javascript
const node = await framer.getNode('nodeId');
await node.setPluginData('key', 'value');
const data = await node.getPluginData('key');
const keys = await node.getPluginDataKeys();
```
--------------------------------
### Dynamic Auto-Sizing with useLayoutEffect (React/JavaScript)
Source: https://developers.framer.wiki/developers/components/auto-sizing
Implement dynamic auto-sizing for a component based on state changes using the `useLayoutEffect` hook. This example shows how to manage internal state (`count`) and re-render the component, allowing its size to adapt. It includes Framer layout annotations for auto-sizing.
```javascript
import { addPropertyControls, ControlType } from "framer"
import { useState, useEffect, useLayoutEffect } from "react"
/*
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight auto
*/
export default function Test(props) {
const start = 0
const [count, setCount] = useState(0)
useLayoutEffect(() => {
if (start !== count) setCount(start)
}, [start])
return (
)
}
const containerStyle = {
display: "flex",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}
const squareStyle = {
margin: 10,
padding: 50,
color: "white",
fontWeight: 600,
borderRadius: 25,
backgroundColor: "#09F",
width: "max-content",
whiteSpace: "pre-wrap",
flexShrink: 0,
}
```
--------------------------------
### API Wrapper Backend for Fetch Requests (JavaScript)
Source: https://developers.framer.wiki/developers/fetch/examples
An asynchronous backend function that wraps an external API call. It fetches data from a specified API, parses the JSON response, and returns it. This pattern is useful for data preparation before use in Framer and is detailed in the Fetch tutorial video.
```javascript
async function worker() {
// Get from any API
const data = await fetch("https://api.fetch.tools/status")
const status = await data.json()
/* Adjust, filter, or manipulate the data */
return new Response(JSON.stringify(status));
}
```
--------------------------------
### Create a Configurable React Button Component with Property Controls
Source: https://developers.framer.wiki/developers/components/examples
This snippet demonstrates how to make a React component's properties configurable from the interface using Framer's `addPropertyControls`. It allows dynamic text display and sets a default value for the 'text' prop.
```jsx
import { addPropertyControls, ControlType } from "framer"
export default function Button(props) {
const style = {
display: "inline-block",
backgroundColor: "orange",
padding: 8,
}
return
{props.text}
}
Button.defaultProps = {
text: "My Title",
}
addPropertyControls(Button, {
text: {
title: "Text",
type: ControlType.String,
},
})
```
--------------------------------
### Get and List Text Styles in Framer
Source: https://developers.framer.wiki/developers/plugins/styles
Retrieves all Text Styles in a project or a specific Text Style by its ID. This allows for programmatic access and management of text formatting within Framer.
```javascript
// Lists all Text Styles in a project.
const textStyle = await framer.getTextStyles()
// Get a specfic Text Style by it's ID.
const textStyle = await framer.getTextStyle("text-style-id")
```
--------------------------------
### Storing Global Project Data
Source: https://developers.framer.wiki/developers/plugins/storing-data
This section details how to store and retrieve data at the project level, shared across all users. It covers setting, getting, and the limitations of data entries.
```APIDOC
## Storing Global Project Data
### Description
Store and retrieve data at the project level that is shared between users. Data entries support strings only, with a maximum of 2kB per entry and 4kB total per project.
### Method
`framer.setPluginData(key: string, value: string | null)`
`framer.getPluginData(key: string): Promise`
`framer.getPluginDataKeys(): Promise`
### Endpoint
N/A (Internal API)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
N/A
### Request Example
```javascript
// Set global data on the project.
await framer.setPluginData('userPreferences', JSON.stringify({ theme: 'dark' }));
// Get global data from the project.
const data = await framer.getPluginData('userPreferences');
const preferences = JSON.parse(data);
console.log(preferences.theme);
// Get all global data keys
const keys = await framer.getPluginDataKeys();
```
### Response
#### Success Response (200)
- `setPluginData`: void
- `getPluginData`: `string | null` - The value associated with the key, or null if not found.
- `getPluginDataKeys`: `string[]` - An array of all keys stored.
#### Response Example
```json
// Example for getPluginData
"{\"theme\": \"dark\"}"
// Example for getPluginDataKeys
["userPreferences", "lastSessionId"]
```
```
--------------------------------
### Get Fonts Information (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/reference
Retrieves a list of all available fonts and their variations (weight, style) that can be used in plugins. It differs from the Font Picker by listing each font file individually. Returns null if a font does not exist.
```javascript
await framer.getFonts()
[
//..
{
family: "Inter",
weight: 900,
style: "normal"
},
{
family: "Noto Sans",
weight: 400,
style: "normal"
},
//..
]
```
```javascript
// Get Noto Sans with a weight of 400 in a normal style.
const font = await framer.getFont("Noto Sans")
// Get Noto Sans with a weight of 800 in an italic style.
const font = await framer.getFont("Noto Sans", {
weight: 800,
style: "italic"
})
```
--------------------------------
### Accessing Parent and Child Layers with Async APIs (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/nodes
Demonstrates how to use `getParent()` and `getChildren()` async functions to access layer relationships. This example combines multiple async operations using `Promise.all` to efficiently retrieve child layers and parent dimensions, handling cases of no selection or multiple selections.
```javascript
useEffect(() => {
let active = true;
async function run() {
if (!active) return;
const parentNode = selection[0];
if (!parentNode || selection.length !== 1) {
setState(null);
return;
}
const layerPromises = [parentNode.getChildren(), parentNode.getRect()]
const [children, parentRect] = await Promise.all(layerPromises)
// Exit to not support no selection or multiselect
if (children.length !== 1 || !parentRect) {
setState(null);
return;
}
const singleChild = children[0];
const childRect = await singleChild.getRect()
if (!childRect) {
setState(null);
return;
}
setState({
parent: parentNode,
child: singleChild,
parentRect,
childRect,
});
}
run()
// cleanup function
return () => {
active = false;
};
}, selection)
```
--------------------------------
### Insert Detached Component Layers with Layout
Source: https://developers.framer.wiki/developers/plugins/components
This example shows how to insert detached component layers with a layout flag enabled. Setting `layout: true` in `framer.addDetachedComponentLayers` allows Framer to attempt to match component variants with web page breakpoints.
```javascript
framer.addDetachedComponentLayers({ url, layout: true })
```
--------------------------------
### Configuring CORS for Fetch API Endpoints (JavaScript)
Source: https://developers.framer.wiki/developers/fetch/examples
A JavaScript function demonstrating how to configure CORS headers for API endpoints used with Fetch. This is essential for safely accessing endpoints from the Framer editor and published sites. It sets common CORS headers like Access-Control-Allow-Origin.
```javascript
function worker() {
// CORS headers
const headers = new Headers();
headers.set('Access-Control-Allow-Origin', '*')
headers.set('Access-Control-Allow-Methods', 'GET, PUT, DELETE, OPTIONS')
headers.set('Access-Control-Allow-Headers', 'Content-Type')
return new Response({ data: "Hi!" }, { headers });
}
```
--------------------------------
### Check Node Rotation Support - Framer Plugin
Source: https://developers.framer.wiki/developers/plugins/concepts
This example shows how to check if a Framer node supports rotation using the `supportsRotation` function from the `framer-plugin` library. If the node supports rotation, its rotation property can be safely accessed. This illustrates the use of 'traits' to determine a node's capabilities without needing to know its specific type.
```javascript
import { supportsRotation } from "framer-plugin"
if (supportsRotation(node)) {
console.log(node.rotation) // Will not error
}
```
--------------------------------
### Update Text Style Breakpoints (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/styles
Shows how to update a text style's attributes, specifically overriding existing breakpoints with a new set. This example replaces all previous breakpoints with a single new one.
```javascript
// Make a new Text Style with breakpoints.
const textStyle = await framer.createTextStyle({
fontSize: "24px",
minWidth: 1280,
breakpoints: [
{ minWidth: 1024, fontSize: "18px" },
{ minWidth: 320, fontSize: "16px" }
]
})
// Update the created Text Style with new breakpoints.
await textStyle.setAttributes({
// Only one breakpoint will now exist on the Text Style.
breakpoints: [
{ minWidth: 320, fontSize: "24px" }
]
})
```
--------------------------------
### Set and Get Global Project Data with Framer
Source: https://developers.framer.wiki/developers/plugins/storing-data
This snippet demonstrates how to store and retrieve global data at the project level using Framer's `setPluginData` and `getPluginData` methods. Data entries are limited to strings, with a maximum of 2kB per entry and 4kB total per project. Exceeding these limits will cause `setPluginData` to throw an error.
```javascript
await framer.setPluginData('key', 'value');
const data = await framer.getPluginData('key');
```
--------------------------------
### Implement Click Tracking with React
Source: https://developers.framer.wiki/developers/overrides/examples
This override facilitates click tracking by calling a tracking API when an element is clicked. It also ensures that any existing `onClick` event handler is preserved. This is a common use case for understanding user interactions within Framer.
```typescript
import type { ComponentType } from "react";
export function withButtonTracking(Component): ComponentType {
return (props) => {
const handleClick = () => {
// Call to tracking API
void fetch("api.example.com/tracking/button")
// Call normal onClick event if exists
props?.onClick()
}
return
}
}
```
--------------------------------
### Remove Plugin Data (Project and Node) in Framer
Source: https://developers.framer.wiki/developers/plugins/storing-data
This example shows how to remove plugin data, both at the project level and for specific nodes, by setting the data value to `null`. It also includes a loop to remove all global project data by iterating through all keys and setting their values to `null`. The same approach can be applied to remove all data from a node.
```javascript
// Remove data from the project.
await framer.setPluginData('key', null);
// Remove data from a node.
const node = await framer.getNode('nodeId');
await node.setPluginData('key', null);
// Remove all global project data.
const keys = await framer.getPluginDataKeys();
for (const key of keys) {
await framer.setPluginData(key, null);
}
```
--------------------------------
### Framer Array Controls for Images, Components, and Objects
Source: https://developers.framer.wiki/developers/components/property-controls
This example showcases the `ControlType.Array` in Framer for managing collections of properties. It demonstrates how to create array controls for images (`ControlType.Image`), component instances (`ControlType.ComponentInstance`), and objects (`ControlType.Object`). Each array control can specify a `control` type and a `maxCount`. The object control allows defining nested properties.
```javascript
export function MyComponent(props) {
const frames = props.images.map(image => {
return
})
return
{frames}
}
// Add a repeatable image property control
addPropertyControls(MyComponent, {
images: {
type: ControlType.Array,
control: {
type: ControlType.Image
}
},
// Allow up to five items
maxCount: 5,
})
// Add a multi-connector to your component to connect components on the canvas
addPropertyControls(MyComponent, {
children: {
type: ControlType.Array,
control: {
type: ControlType.ComponentInstance
},
maxCount: 5,
},
})
// Add a list of objects
addPropertyControls(MyComponent, {
myArray: {
type: ControlType.Array,
control: {
type: ControlType.Object,
controls: {
title: { type: ControlType.String, defaultValue: "Employee" },
avatar: { type: ControlType.Image },
},
},
defaultValue: [
{ title: "Jorn" },
{ title: "Koen" },
],
},
})
// For multiple values, you can pass in an array of single values as the React default prop.
MyComponent.defaultProps = {
paddings: [5, 10, 15],
}
```
--------------------------------
### Dynamically Replace Text Content with React
Source: https://developers.framer.wiki/developers/overrides/examples
This override enables dynamic replacement of text content for text elements by utilizing the `text` property. The specified text will appear on the preview or published site. For more complex data fetching, consider using Framer's Fetch API or external data sources.
```typescript
import type { ComponentType } from "react";
export function withText(Component): ComponentType {
return (props) => {
return
}
}
```
--------------------------------
### Get Nodes by Type
Source: https://developers.framer.wiki/developers/plugins/nodes
Retrieves all nodes of a specified type within the project. For example, this can be used to get all 'FrameNode' instances.
```typescript
// Get all frame nodes in a project.
const frameNodes = await framer.getNodesWithType("FrameNode")
```
--------------------------------
### Initiate Login and Poll for Tokens (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/oauth
This function initiates the login process by fetching an authorization URL and then polls for tokens using the `pollForTokens` function. It stores the received tokens in local storage and updates the component's state.
```javascript
const [tokens, setTokens] = useState(null);
const login = async () => {
// Retrieve the authorization URL & set of unique read/write keys
const response = await fetch("https://localhost:8787/authorize", {
method: "POST",
});
if (response.status !== 200) return;
const authorize = await response.json();
// Open up the provider's login window.
window.open(authorize.url);
// While the user is logging in, poll the backend with the
// read key. On successful login, tokens will be returned.
const tokens = await pollForTokens(authorize.readKey);
// Store tokens in local storage to keep the user logged in.
window.localStorage.setItem("tokens", JSON.stringify(tokens));
// Update the component state.
setTokens(tokens);
};
```
--------------------------------
### Displaying and Configuring Plugin UI with framer.showUI
Source: https://developers.framer.wiki/developers/plugins/interface
This JavaScript code shows how to display the plugin's user interface in Framer using `framer.showUI`. It allows for optional configuration of the UI's position, dimensions, and resizability. The UI is hidden by default and needs to be explicitly shown.
```javascript
framer.showUI({
position: "top left", // Optional, Allowed: "top left", "center", etc.
width: 240, // Optional
height: 245, // Optional
resizable: true, // Optional (default false). Allowed: true, false, "width", "height"
minWidth: 100, // Optional
minHeight: 100, // Optional
maxWidth: 300, // Optional (default Infinity)
maxHeight: 300, // Optional (default Infinity)
})
```
--------------------------------
### Inserting Component Instances
Source: https://developers.framer.wiki/developers/plugins/components
Demonstrates how to insert a component instance into Framer using its module URL. You can optionally provide attributes to customize its size and control properties.
```APIDOC
## POST /framer/addComponentInstance
### Description
Inserts a component instance into the Framer canvas using its module URL. Allows for customization of attributes like size and control properties.
### Method
POST
### Endpoint
/framer/addComponentInstance
### Parameters
#### Request Body
- **url** (string) - Required - The module URL of the component to insert.
- **attributes** (object) - Optional - An object containing attributes to customize the component instance.
- **width** (string) - Optional - The width of the component instance (e.g., "900px").
- **height** (string) - Optional - The height of the component instance (e.g., "600px").
- **controls** (object) - Optional - An object to set component-specific control properties.
- **url** (string) - Optional - Example for a video component, sets the video source URL.
### Request Example
```json
{
"url": "https://framer.com/m/framer/Video.js",
"attributes": {
"width": "900px",
"height": "600px",
"controls": {
"url": "https://path/to/video.mp4"
}
}
}
```
### Response
#### Success Response (200)
- **instance** (object) - The newly inserted component instance.
#### Response Example
```json
{
"instance": { /* ... component instance details ... */ }
}
```
```
--------------------------------
### Read Installed Custom Code - Framer Plugin
Source: https://developers.framer.wiki/developers/plugins/custom-code
Retrieves the currently installed custom code snippets. It allows checking if code was disabled by the user and accessing the HTML content of the injected snippets for different locations.
```javascript
const customCode = await framer.getCustomCode();
if (customCode.bodyStart.disabled) {
// Custom code was disabled by the user in settings.
// Your plugin has no control over enabling this
// But you could display some UI to indicate it.
}
const html = customCode.bodyStart.html
```
--------------------------------
### Module URLs
Source: https://developers.framer.wiki/developers/plugins/components
Explains Framer's Module URLs, which uniquely identify component versions. Covers how to obtain them and how to reference the latest version.
```APIDOC
## Module URLs
### Description
Module URLs are unique identifiers for Framer components, used for sharing and insertion via plugins. They can point to a specific version or the latest version.
### Obtaining Module URLs
1. Locate your code component in the **Assets Panel**.
2. Right-click on the component and select **“Copy URL…”**.
### URL Formats
- **Specific Version URL:** `https://framer.com/m/user/project/component@SaveID`
- The `@SaveID` part ensures the URL always points to that exact version.
- **Latest Version URL:** `https://framer.com/m/user/project/component`
- Remove the `@SaveID` portion to have the URL dynamically point to the most recent version of the component.
```
--------------------------------
### Upload File for Component Control (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/assets
Demonstrates uploading a file (e.g., a video) using `framer.uploadFile` and then assigning it to a component's control. This is useful for configuring components that accept file inputs, such as video players.
```javascript
const uploadedFile = await framer.uploadFile({
// You can also pass "File" objects
// To accept inputs.
file: "https://example.com/video.mp4",
name: "Example Video"
})
// Insert a Video Component with the uploaded file
await framer.addComponentInstance({
url: "https://framerusercontent.com/modules/lRDHiNWNVWmE0lqtoVHP/Z4QJ2YpzpVnWRfR6Ccgg/Video.js#Video",
attributes: {
controls: {
srcType: "Upload",
srcFile: uploadedFile,
},
},
})
```
--------------------------------
### Getting Image from Selection
Source: https://developers.framer.wiki/developers/plugins/assets
Retrieves the image associated with the current selection on the canvas.
```APIDOC
## GET /framer/getImage
### Description
Gets the image of the current selection on the canvas, if an image exists.
### Method
GET
### Endpoint
/framer/getImage
### Parameters
None
### Response
#### Success Response (200)
- **image** (object | null) - The image object of the selection, or null if no image is selected.
#### Response Example
```json
{
"image": {
"id": "img_ghi789",
"url": "https://framer.com/images/selected.png",
"name": "Selected Image",
"altText": "Description"
}
}
```
```
--------------------------------
### Node Replicas
Source: https://developers.framer.wiki/developers/plugins/nodes
Explanation of replica nodes, their properties, and how they inherit and override attributes from primary nodes.
```APIDOC
## Node Replicas
### Description
Replica nodes are special nodes that inherit attributes from a primary variant or breakpoint. Overridden attributes are set directly on the replica.
### Property
- `isReplica` (boolean): Indicates if the node is a replica. This property is `true` for replica nodes and `false` otherwise.
### Behavior
Replica nodes inherit attributes from their primary counterpart. When an attribute is modified on a replica, that modification is stored directly on the replica node, breaking the inheritance for that specific attribute.
```
--------------------------------
### Get Current Node Selection
Source: https://developers.framer.wiki/developers/plugins/nodes
Retrieves an array of nodes currently selected on the canvas. This is a common operation for plugins that interact with user-defined content.
```typescript
const selection = await framer.getSelection()
```
--------------------------------
### Get Node by ID
Source: https://developers.framer.wiki/developers/plugins/nodes
Fetches a specific node from the project using its unique identifier. This is useful when you know the exact ID of the node you need to access.
```typescript
const node = await framer.getNode("some-node-id")
```
--------------------------------
### Get Nodes with Specific Attribute
Source: https://developers.framer.wiki/developers/plugins/nodes
Finds all nodes that possess a particular attribute, such as 'backgroundColor'. This allows for querying nodes based on their properties, regardless of their specific type.
```typescript
// Get any kind of node that has a background color set.
const nodes = await framer.getNodesWithAttribute("backgroundColor")
```
--------------------------------
### Deploy Backend Worker with Wrangler (Bash)
Source: https://developers.framer.wiki/developers/plugins/oauth
This command uses `wrangler`, a Cloudflare tool, to deploy a backend worker. It's a simple command-line interface for managing and deploying Cloudflare Workers.
```bash
npx wrangler deploy
```
--------------------------------
### Get Image from Selection (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/assets
Retrieves the image associated with the current selection in Framer using the `getImage()` function. This is the most straightforward method for accessing selected image data.
```javascript
const image = await framer.getImage();
```
--------------------------------
### Get Current CMS Collection
Source: https://developers.framer.wiki/developers/plugins/cms
Retrieves the currently viewed collection in the CMS. This is useful for context-specific operations within a plugin. It requires the `framer` object to be available.
```javascript
const collection = await framer.getCollection()
```
--------------------------------
### Check for Local Development Environment (JavaScript)
Source: https://developers.framer.wiki/developers/plugins/oauth
A simple utility function to determine if the plugin is currently running in a local development environment by checking the hostname. This is useful for toggling between local and production API endpoints.
```javascript
const isLocal = () => window.location.hostname.includes("localhost")
```
--------------------------------
### Get Managed Collection in Framer
Source: https://developers.framer.wiki/developers/plugins/cms
Retrieves the active managed collection when a plugin is launched in configure or sync mode. This is the primary method to access and manipulate collection data.
```javascript
const collection = await framer.getManagedCollection()
```
--------------------------------
### Inserting Detached Component Layers
Source: https://developers.framer.wiki/developers/plugins/components
Explains how to insert components as detached layers instead of instances. This method allows setting attributes and optionally arranging them as a layout section.
```APIDOC
## POST /framer/addDetachedComponentLayers
### Description
Inserts a component as detached layers into the Framer canvas. Allows setting attributes and optionally enabling layout mode.
### Method
POST
### Endpoint
/framer/addDetachedComponentLayers
### Parameters
#### Request Body
- **url** (string) - Required - The module URL of the component.
- **attributes** (object) - Optional - An object containing attributes to set for the detached layers (e.g., `title`).
- **layout** (boolean) - Optional - If true, inserts the layers as a layout section, attempting to match component variants with breakpoints.
### Request Example
```json
{
"url": "https://framer.com/m/framer/ExampleComponent.js",
"attributes": {
"title": "User Name"
},
"layout": true
}
```
### Response
#### Success Response (200)
- **frame** (object) - The root frame representing the detached component layers.
#### Response Example
```json
{
"frame": { /* ... frame details ... */ }
}
```
```
--------------------------------
### Show Plugin UI - Framer API
Source: https://developers.framer.wiki/developers/plugins/concepts
This code snippet demonstrates how to display a plugin's user interface within the Framer editor. It utilizes the `framer.showUI` function to define the initial position and dimensions of the plugin window. This is crucial for plugins that require user interaction or visual feedback.
```typescript
framer.showUI({ position: "top left", width: 240, height: 245 })
```
--------------------------------
### Get and List Color Styles in Framer
Source: https://developers.framer.wiki/developers/plugins/styles
Retrieves all Color Styles in a project or a specific Color Style by its ID. This is useful for accessing and managing color definitions within your Framer project.
```javascript
// Lists all Color Styles in a project.
const colorStyles = await framer.getColorStyles()
// Get a specfic Color Style by it's ID.
const colorStyle = await framer.getColorStyle("color-style-id")
```
--------------------------------
### Creating Nodes
Source: https://developers.framer.wiki/developers/plugins/nodes
This section covers the methods available for creating new nodes within a Framer project, such as generic frame nodes and text nodes.
```APIDOC
## Creating Nodes
### Description
Methods for creating new nodes on the canvas.
### Methods
- `framer.createFrameNode()`: Creates a generic frame node on the canvas.
- `framer.addText()`: Adds a text node to the canvas.
### Usage Examples
Create a frame node:
```javascript
framer.createFrameNode()
```
Add a text node:
```javascript
framer.addText()
```
Other specific node types (Code Components, Images, SVGs) can be created following their respective documentation.
```
--------------------------------
### Get List of All CMS Collections
Source: https://developers.framer.wiki/developers/plugins/cms
Fetches a list of all available collections within the Framer CMS. This function allows plugins to enumerate and access different data sets. It relies on the `framer` object.
```javascript
await framer.getCollections()
```
--------------------------------
### Basic HTML Structure for Framer Plugin UI
Source: https://developers.framer.wiki/developers/plugins/interface
This HTML snippet demonstrates a basic structure for a plugin's user interface within Framer. It uses semantic HTML elements like ``, ``, ``, and `