Preparing your plugin for publishing
Learn how to check your plugin’s security, reliability, privacy, and user experience before publishing.
Use this checklist to make sure your plugin meets Framer’s expectations. Test its behavior, remove unfinished code, and explain clearly what users can expect.
Permissions and errors
Plugins can only perform actions the current user is allowed to perform. Check permissions before protected operations and handle failures when they happen.
Check the required permission with the Permissions API.
Hide or disable actions the user cannot perform.
Handle permission changes while the plugin is open.
Catch errors for individual operations, rather than the entire workflow.
Explain which permission is needed and how to continue.
For React interfaces, use useIsAllowedTo() when possible. For other workflows, use subscribeToIsAllowedTo() or isAllowedTo().
See Working with permissions for examples.
Code readiness
Your source code should match what your plugin does. Before publishing:
Remove unused code, imports, and assets.
Delete demo credentials, temporary feature flags, and development-only code.
Remove unfinished controls and actions.
Fix TypeScript and build errors.
Handle loading, empty, and error states.
Make sure every declared plugin mode works.
Include readable source files, not just a compiled bundle.
Privacy and external services
Only send data to external services when your plugin needs it. Explain what data leaves the project and why.
Send only the data needed for the action.
Tell users what you send, where it goes, and why.
Get consent before sending potentially sensitive content.
Disclose third-party services, including AI, analytics, and licensing providers.
Use HTTPS and provide a privacy policy that matches your plugin’s behavior.
Do not include project content, prompts, authentication data, or other sensitive information in analytics or diagnostic reports unless it is essential and clearly disclosed.
Secrets and credentials
People can inspect code shipped with your plugin. Never include secrets in it, such as:
API keys or access tokens.
OAuth client secrets or signing keys.
Backend administrative credentials.
URLs containing credentials.
Shared licensing tokens that grant privileged access.
Keep privileged operations on a backend you control. Expose only the operations your plugin needs. If you publish a secret, remove and rotate it immediately.
Dependencies
Your plugin should not rely on executable code that can change after publishing.
Bundle dependencies and pin their versions whenever possible.
Avoid loading scripts or modules from remote URLs.
Do not execute code returned by an API.
Document unavoidable runtime dependencies.
Handle external services being unavailable.
Take extra care with remote resources that can change the editor or run code on a published site.
Untrusted content
Treat HTML, SVG, JavaScript, and other executable markup from users or external services as untrusted.
Avoid:
Rendering untrusted content with
innerHTML.Inserting remote HTML into projects.
Adding arbitrary scripts to project custom code.
Executing JavaScript returned by an API.
Letting configurable URLs choose executable code.
Passing unsanitized markup between windows or iframes.
Use structured data and supported Framer APIs where possible. If HTML support is essential, allow only a strict set of elements and attributes.
Project changes
Explain what will change and let users cancel where practical. Show a confirmation before actions that:
Delete or replace content.
Remove CMS items or fields.
Overwrite code files or project custom code.
Move layers or change their parent.
Change many nodes at once.
Insert content where users may not expect it.
Update only content your plugin owns where possible. Do not label an action as a preview or scan if it immediately changes the project.
Data storage
Project and node plugin data can be shared with collaborators. Use it only for small amounts of shared configuration.
Never store the following in shared plugin data:
API keys, access tokens, or refresh tokens.
Passwords or license credentials.
Private user settings.
Sensitive results intended for one user.
Use localStorage or sessionStorage for user-specific preferences and authentication state.
See Storing plugin data for limits and implementation details.
Performance and stability
Your plugin should stay responsive, including in large projects. Check for:
Polling that continues after work finishes.
Overlapping requests or large unbounded loops.
Repeated requests that could be cached or batched.
Event subscriptions that are not removed.
Work that continues after the plugin closes.
Long operations without progress or cancellation.
Errors that leave the interface loading indefinitely.
When polling, wait for each request to finish before starting the next.
User experience
Your interface and Marketplace listing should accurately explain what your plugin does.
Disclose limits and paid restrictions before an action starts.
Report partial imports and truncated results.
Show success only after an operation finishes.
Explain errors and how to recover.
Use clear labels for actions that change a project.
Show progress during long operations.
Let users cancel where practical.
Make sure privacy explanations match actual network behavior.
Use framer.notify() or inline messages to communicate progress, results, and recoverable errors.
Updated
