Publishing Apps and the Marketplace
|
This content was generated with the assistance of AI and should be verified against the official Webflow documentation before being relied on in production. This sub-section’s Webflow bibliography lists the reference material consulted while preparing these pages. |
This page describes how apps are published on Webflow as it was on 2026-10-28, the date on which its facts were checked
against the official developer documentation. The tools are pinned to the versions current on that date: the Webflow CLI
@webflow/webflow-cli 2.15.0 (Node 22.13 or later), @webflow/designer-extension-typings 2.2.2 and the JavaScript SDK
webflow-api 3.3.4. Registering an app is a Workspace feature, and uploading a bundle needs a workspace administrator
with two-factor authentication. Plans are named by tier only, and every example runs in a free Developer workspace.
The running example is Fernbrook Gardens, the fictitious botanical garden of the whole sub-section. Its agency builds the Plant Label Kit, a Designer Extension (with a small backend) that fills in the alt text of plant photos, builds printable plant labels from the CMS and handles the garden’s two extra locales, Spanish and German. This page follows that app from a local build to a Marketplace listing. How apps are built is covered in Apps Overview and OAuth and Designer Extensions and the Designer API; the credentials of a Data Client are in Data API: Authentication and Scopes.
Three ways an app reaches users
An app that works on the developer’s machine is visible only to users of the workspace that registered it. The official documentation states that sharing outside the workspace requires Marketplace submission. Three situations follow from that.
| Situation | What happens | Typical use |
|---|---|---|
Development in the registered workspace |
Only members of the workspace see the app. The Launch development app button loads the local development URL |
Building and debugging |
Private app |
A Marketplace submission with visibility set to private. After approval the developer receives an install URL, and only the people who hold it can install the app |
An internal tool for one organization or one client |
Public app |
A Marketplace submission, listed or unlisted, reviewed and published |
Software for any Webflow workspace |
Source: Apps: Publishing your app
Testing with a few external users before launch is a separate process, the user testing process of the Apps documentation. A private app is not a substitute for it, nor for public distribution.
Source: Apps: Private apps
The capability of the app decides what has to be shipped:
-
A Designer Extension ships a front-end bundle,
bundle.zip, that Webflow hosts. This is the part with the size limit and the version history. -
A Data Client ships no bundle. It runs on the developer’s own server and needs an install URL that starts the OAuth flow.
-
A hybrid app has both, and follows both sets of rules. See Hybrid Apps.
The bundle
A Designer Extension is a web application that Webflow serves inside an iframe in the Designer. The bundle is the production build of that application, zipped by the CLI.
Prerequisites
-
A complete, tested extension.
-
The Webflow CLI installed.
-
Admin access to the workspace where the app is registered.
-
Two-factor authentication enabled on the account.
Source: Apps: Publishing your app
Building the bundle
The sequence is a production build followed by webflow extension bundle. The build writes the application to a build
or dist folder, and the folder can be set in webflow.json; the bundle command run from the project root creates
bundle.zip. For frameworks such as Next.js or Astro the framework’s own production build runs first and its output
directory is bundled; both steps can be combined in a package.json script.
The package.json of the Plant Label Kit, with the pinned versions:
{
"name": "plant-label-kit",
"private": true,
"type": "module",
"engines": { "node": ">=22.13" },
"scripts": {
"build": "vite build",
"bundle": "npm run build && webflow extension bundle"
},
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@webflow/webflow-cli": "2.15.0",
"@webflow/designer-extension-typings": "2.2.2",
"vite": "5.4.11",
"typescript": "7.0.2"
}
}
Source: Apps: Publishing your app
The CLI itself is described in Webflow CLI.
The 5 MB limit
The documentation is explicit: the bundle must not exceed 5 MB. Webflow compiles the bundle and serves it from a unique URL, found under Edit App > Building Blocks > Designer Extension in the app’s settings. Every customer site that opens the app downloads it, which is why the limit exists and why a small bundle is also a faster app. The usual ways to stay under it:
-
Ship only what the panel needs. A label designer does not need a full charting library.
-
Import individual functions rather than whole utility libraries.
-
Keep images, fonts and sample data out of the bundle. Fetch them from the app’s backend, which is reachable over HTTPS.
-
Compare the size after every dependency upgrade. The check is cheap to automate, as shown below.
Source: Apps: Publishing your app
Source maps stay out of the production bundle
Source maps are useful for debugging, but the documentation says to keep them, and other review files, out of the bundle: bundles that ship source maps are not accepted. The maps still matter, because reviewers need them (see the review ZIP below). The build therefore produces them, a separate archive keeps them, and they are removed before the bundle is made.
Uploading a version
Uploading is done by hand in the Webflow dashboard, by a workspace administrator.
-
In Workspace settings, open the Apps & Integrations tab.
-
Under Develop, find the app and select Publish extension version.
-
Choose
bundle.zipand write notes that describe the change. -
A confirmation message appears and the version shows up in the version history.
Source: Apps: Publishing your app
The Publish extension version button is disabled for anybody who is not a workspace admin or who has not enabled two-factor authentication. A developer who cannot see an enabled button should check those two conditions first. This is also why the upload cannot be part of an unattended pipeline: the account that uploads is an administrator with 2FA, so the pipeline builds and verifies the artifact, and a person with the right role performs the upload.
Testing the uploaded version
The button names matter here. Open any Webflow site in the workspace, open the app and select Launch App. Do not select Launch development app: that one loads the local development URL and not the uploaded version, so a test through it proves nothing about the bundle that was uploaded.
Source: Apps: Publishing your app
Version history and the absence of rollback
Each upload creates a new versioned instance. The history is available from the … button in the app’s settings, then Version History. There is no one-click rollback. To revert, check out an earlier commit in version control, generate a new bundle from it and upload that as a new version.
Source: Apps: Publishing your app
Three practical consequences for the Fernbrook agency:
-
Tag every upload. The version notes carry the Git tag, for example
plant-label-kit-1.4.0, so that the version in the dashboard maps to a commit. -
Keep the lockfile committed. A rebuild from an old tag must reproduce the old bundle, which needs the old dependency versions.
-
Rehearse the revert. The procedure below is the whole rollback, and it takes as long as a build plus a manual upload.
git fetch --tags
git checkout plant-label-kit-1.3.2
npm ci
npm run bundle
# Then, in Workspace settings > Apps & Integrations > Develop:
# Publish extension version, choose bundle.zip, note "Revert to 1.3.2".
Source: Apps: Publishing your app
Updating an app
An update is a new bundle.zip uploaded the same way. The notes should mention any new required scope, because changing
the required scopes makes users authenticate again. For a published app the Marketplace has its own update path, covered
later: for Designer Extension changes the new version is published from the workspace as well.
A build and packaging pipeline
The pipeline below builds the extension, archives its source maps into the review ZIP, removes the maps, creates the bundle and fails if the bundle contains a source map or is too large. It does not upload anything: the upload remains the administrator’s step. The size check uses 5,000,000 bytes, the stricter reading of 5 MB, so a bundle that passes is under the limit under either reading.
#!/usr/bin/env bash
# scripts/package.sh: build, archive source maps, create bundle.zip
set -euo pipefail
rm -rf dist bundle.zip review.zip
npm ci
npm run build
# The review ZIP: maps of this exact build, the manifest and the lockfile.
(cd dist && zip -q -r ../review.zip . -i '*.map')
zip -q review.zip package.json package-lock.json
# The bundle itself must not carry source maps.
find dist -name '*.map' -delete
npx webflow extension bundle
if unzip -l bundle.zip | grep -E '\.map$'; then
echo "bundle.zip contains source maps" >&2
exit 1
fi
size=$(wc -c < bundle.zip)
limit=5000000
echo "bundle.zip: ${size} bytes (limit ${limit})"
if [ "${size}" -gt "${limit}" ]; then
echo "bundle.zip is over the size limit" >&2
exit 1
fi
Source: Apps: Publishing your app
The same script runs in CI, and the two archives are stored as workflow artifacts so that whoever uploads can download exactly what was built from the tagged commit:
name: package-plant-label-kit
on:
push:
tags: ["plant-label-kit-*"]
permissions:
contents: read
jobs:
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: bash scripts/package.sh
- uses: actions/upload-artifact@v4
with:
name: plant-label-kit-${{ github.ref_name }}
path: |
bundle.zip
review.zip
retention-days: 90
Source: Apps: Publishing your app
The workflow holds no Webflow secret, because nothing in it talks to Webflow. The CI side of the sub-section is in Testing, CI and DevOps.
Private apps
A private app is a custom app for one workspace or one specific implementation. It has the full API capability but is not meant for broad distribution. It is created through the same submission form as a public app: in the Marketplace Visibility section the developer selects Private, completes the app information and submits it. Private apps go through the same review as public apps.
After approval the developer receives a unique install URL. Only people with that URL can install the app, so the URL is shared directly with the intended users and the developer keeps track of who has it. A private app has no Marketplace listing page and is not visible on the public Marketplace, and it is not suited to multi-workspace distribution. Private apps can still be monetized under the standard Marketplace terms.
Source: Apps: Private apps
For Fernbrook Gardens this is the right choice if the Plant Label Kit stays an internal tool: the agency installs it on the garden’s workspace and on nobody else’s. It becomes a public app only if the agency decides to offer it to other gardens.
Submitting to the Marketplace
The steps are: prepare the technical requirements and assets, submit through the Webflow App submission form, respond to review feedback, and promote the app after publication.
Technical requirements
-
Two-factor authentication is enabled for an admin account of the workspace.
-
The app is fully tested and functional, not a beta or pre-release.
-
The app has clear documentation and error handling.
-
The app meets the security, authentication, OAuth, scope and data-handling rules of the Marketplace Guidelines.
Source: Apps: Submitting your app
What the submission contains
| Item | Content |
|---|---|
Install URL |
For Data Client and hybrid apps. The |
Production bundle |
Uploaded in the app settings, without source maps |
Review ZIP |
Required for new Designer Extension and hybrid apps and for updates that change the Designer Extension bundle. A Data Client-only app does not need it |
Published testing site |
A |
Review access |
Full access for reviewers: a demo account, gated features, test credentials and sample data, none of which may expire |
Backend |
Every backend service and third-party integration kept running throughout the review |
Demo video |
A walkthrough of 2 to 5 minutes from installation to use, in English or with English subtitles, on Loom, YouTube (unlisted or private) or Google Drive. A Data Client must also show OAuth approval and denial |
App Review Preflight receipt |
A code that starts with |
Listing |
Name, descriptions, features, logo, screenshots, links, support email and policies |
Source: Apps: Submitting your app
The submission form checks required fields and formats, listing rules (English copy, no Webflow name in the app name or domains, disclosed pricing, explained custom-code and workspace scopes), that links resolve and point to their own content, and that videos are hosted where the form allows. Complex features and pricing are documented in the review notes and the video.
The review ZIP with source maps
Webflow has to be able to review a Designer Extension from source, and a minified bundle is not reviewable. The review ZIP is the solution, and it is uploaded to the Source map artifact field of the form as a single ZIP:
-
The Source Map v3 files (
.map), thepackage.jsonand the lockfile, all from the exact build that produced the bundle. -
Alternatively, when the source ships unchanged, the source files plus a short README that explains how the bundle is packaged, and the
package.jsonand lockfile if they are used. -
The ZIP is uploaded directly; a link does not replace it.
The maps stay private to the review team and are never published. The pipeline above produces the first variant automatically, which is why it archives the maps of the same build before it deletes them from the bundle.
Source: Apps: Publishing your app
Preflight
The Preflight receipt is required for new apps and for updates that change code or scopes; a Data Client without the custom code scope does not need one. Every Blocker and Required update reported by Preflight has to be fixed first, and the resulting receipt is pasted into the form. The result is one of three values:
| Result | Effect |
|---|---|
|
Accepted |
|
Accepted, and a reviewer checks the flagged items |
|
Blocks the submission, as does a receipt the form does not recognize |
Source: Apps: Submitting your app
Install URL for a Data Client
The Plant Label Kit has a backend that edits CMS items, so it is a hybrid app and needs an install URL. The recommended route sends the user straight to Webflow OAuth. A URL that requests scopes beyond those configured makes the installation fail, while one that requests too few installs successfully and then fails on API calls, so the URL carries every scope the app uses. With placeholders:
https://webflow.com/oauth/authorize
?client_id=REPLACE_WITH_CLIENT_ID
&response_type=code
&scope=authorized_user%3Aread%20cms%3Aread%20cms%3Awrite%20assets%3Aread
Source: Apps: Submitting your app
The authorization-code flow, state handling and token exchange are in
Data API: Authentication and Scopes.
Listing requirements
The listing is a separate piece of work that the review checks against the guidelines.
| Field | Rule |
|---|---|
App name |
At most 30 characters |
Short description |
At most 100 characters |
Long description |
At most 10,000 characters; Markdown is supported but links are not |
Feature list |
At most 5 features |
App logo |
900x900 px, 1:1, PNG, at most 50 KB; a logomark, not a text logotype |
Screenshots |
3 to 5 images, 1280x846 px, PNG or JPG, at most 2 MB each |
Categories |
Up to 5, chosen from the list the form offers |
Support and policies |
A support email, a privacy policy URL and a terms of service URL |
Language |
English. If the app’s own interface is in another language, the long description says which |
Source: Apps: Listing your app
The English rule applies to the listing and not to the app. The Plant Label Kit interface can offer Spanish and German labels, and the long description states that the app operates in English, Spanish and German.
The Marketplace Guidelines
Review covers the Designer code, the calls to the Webflow API, OAuth and authorization, changes to Webflow data, handling of credentials and user data, and the connect, disconnect and uninstall behavior. It is not a security audit and not a complete list of defects: approval covers only the version, configuration, permissions and behavior that were reviewed, and material changes can require a new review.
Source: Apps: Marketplace guidelines
Scopes and OAuth
-
OAuth 2.0 is required. An app must not collect Webflow credentials by hand or bypass the flow.
-
Every requested scope must be needed for the advertised functionality and tied to a documented endpoint that the app calls. Read-only apps request
:readscopes, write-only apps:write, and both only when both are used. -
Site-level scopes are preferred over workspace-level ones. For identity alone, use
authorized_user:read, notsites:readorworkspace:read. -
custom_code:readandcustom_code:writeare elevated-risk scopes, requested only for a disclosed custom code feature. -
A unique
stateis sent with every authorization request and verified before the code is exchanged. The redirect URI matches the registered one exactly, and the code (single use, valid 15 minutes) is never retried, persisted or logged. -
The OAuth flow runs once, at install or on explicit re-authorization; signing out of the app does not revoke the Webflow authorization unless the user intends it.
Tokens and secrets
-
Tokens are stored server side in encrypted storage or a secret manager: never in browser storage, plaintext, client code, logs or responses.
-
The
client_secretstays out of client code, public repositories, build artifacts, image layers and pipeline logs. -
When a user revokes access, the app stops using the token and deletes it.
-
Credential headers are never sent to non-Webflow domains, and secrets are never hardcoded as string literals.
-
A Data Client gives three written attestations: the OAuth token is encrypted at rest, stored server side only and deleted on uninstall or revocation.
Injected scripts and custom code
Code that an app places on a customer’s site goes through the Custom Code API, so that the site owner can see, manage and
remove it. The listing states what code is applied, what it does, where it runs and why, and remotely loaded resources are
disclosed at submission. On uninstall the app removes the custom code it registered at site and page level, keeps the
customer’s unrelated scripts and deletes the Webflow-side data it added. The guidelines recommend immutable, versioned HTTPS
URLs with integrity and the crossorigin attribute set to anonymous, scoping the injection to the pages that need it, and never asking
users to paste scripts manually.
The Plant Label Kit does not inject scripts; if it later adds a visitor-facing widget, the widget is delivered this way. The API side is in Data API: Assets, Forms and Custom Code.
Designer Extension technical rules
-
No
eval(),new Function()or string arguments to timers, and no untrusted data inserted as raw HTML. -
Read or change the site only through the official Designer APIs, never by manipulating the Designer interface.
-
Stay compatible with the Webflow Content Security Policy: inline event handlers and
javascript:URIs fail review. -
Minification is fine, obfuscation is not (encoded string arrays, runtime
atob()decoding, scrambled self-invoking functions). -
No keyboard shortcuts that invoke the app or its features.
-
An external iframe may be used for authentication, not as the primary interface when its content can change without review.
Network and data handling
Every endpoint uses HTTPS and points to production: staging, localhost and private-network references are removed before
submission. A Data Client’s redirect URI is a single fully qualified HTTPS URL on a production domain, with no wildcard,
IP address, tunnel service or port other than 443. CORS allows only origins the developer controls, never a wildcard.
Backend endpoints verify identity with a session or signed token and never trust a client-supplied siteId. Data is read
and written only through the official APIs, rate limits are respected with exponential backoff, and Webflow remains the
source of truth: the app shows when data was fetched and never silently overwrites it.
Source: Apps: Marketplace guidelines
Performance
The app uses resources efficiently, avoids long-running background tasks that affect performance, and monitors and fixes performance problems; persistent problems can lead to removal. The 5 MB bundle limit is the hard edge of this guideline, and a bundle far below it is the practical target.
Accessibility
The app is designed for users with different abilities and follows WCAG practices, including alt text for images, keyboard navigation and sufficient color contrast. For an app whose purpose is to fix alt text this is also a matter of credibility. The wider topic is in Accessibility.
Localization
An app that writes to a locale-aware endpoint must handle localeId and cmsLocaleId correctly: it specifies the
localeId on every write and never overwrites localized content with primary-locale values without the user’s awareness. It
also preserves data-w-id and other Webflow identifiers when updating HTML. For Fernbrook Gardens, a bulk alt-text fix that
wrote the English text into the Spanish and German variants would break this rule. The model of locales and the API are in
Localization and
Data API: E-commerce and Localization.
Business, support and audit
Fees and in-app purchases are disclosed and ads are not displayed. Trademarks are used only with authorization, support contact information is accurate, and a developer may keep only one account for active Marketplace listings. Webflow may audit app access and activity, and the developer cooperates by providing the records requested.
Source: Apps: Marketplace guidelines
The review
After submission Webflow emails confirmation of receipt, usually to the account address, and aims to decide within 10 business days. The documentation for the publishing step describes the review as taking a few days and says that an email arrives on approval; the submission page gives the longer 10-business-day target, which is the figure to plan with. The outcome is approval, a request for changes or rejection.
-
When changes are requested, fix every listed item, retest the whole app end to end and resubmit. The feedback is not exhaustive.
-
Repeated submissions that ignore earlier feedback can pause new submissions for the app, with longer pauses, and may end in rejection. A rejected app can be submitted again when it is ready.
-
Hiding functionality, showing reviewers a different experience or submitting misleading information leads to removal and a ban from future publishing.
-
A blocking problem, such as a failed installation or OAuth, stops the review.
Source: Apps: Submitting your app
Updating a published app
After approval, material changes need a new review: changes to functionality, user-facing behavior, permissions, bundles, integrations and scripts delivered through the Custom Code API. The update goes through the same form with the submission type App Update.
-
Required fields are the app name and client ID, plus the published testing site.
-
When the Designer Extension bundle changed, the review ZIP is uploaded and the question about a new or changed bundle is answered Yes.
-
A Preflight receipt is needed when the update changes code or scopes. A listing-only update skips the artifacts.
-
An email arrives when the approved update is published, and for Designer Extension changes a new version is also published from the workspace.
-
Scopes are locked after publication. Adding one is an app update, and the
scopeof the install URL changes only after the update is approved; existing installs do not gain it and have to be asked to re-authorize.
Source: Apps: Submitting your app
A release checklist for the Plant Label Kit
-
Tag the commit and let the pipeline build
bundle.zipandreview.zip. -
Check that the bundle is under the limit and holds no source map.
-
Upload the bundle as a new extension version, with notes that name the tag and any new scope, and test with Launch App.
-
Run Preflight on the bundle and the review ZIP and fix every Blocker and Required update.
-
Prepare the testing site on
.webflow.io, the demo account that does not expire and the 2 to 5 minute video. -
Check the Spanish and German behavior, keyboard use and contrast.
-
Confirm that disconnecting and uninstalling remove what the app added.
-
Submit as a private or public app, and wait for the answer.
-
After approval, keep the tag. It is the only rollback there is.
Pitfalls checklist
-
Looking for a rollback button. There is none: rebuild from an earlier commit and upload it as a new version.
-
Testing the uploaded version with Launch development app and validating the local build instead.
-
Shipping source maps in
bundle.zip, or forgetting the review ZIP for a changed bundle. -
Building the maps and the bundle in two different builds, so that the review ZIP does not match.
-
A disabled Publish extension version button because the user is not an admin or has no 2FA.
-
Adding a scope in code or in the install URL before the app update is approved.
-
An install URL with fewer scopes than the code needs: installation works and the calls fail.
-
Writing to locale-aware endpoints without
localeId, overwriting Spanish and German content. -
Leaving staging or localhost URLs, or an expiring review account, in the submission.
-
Listing copy that is not in English, or that does not say which other language the app speaks.
Summary
-
A Designer Extension ships as
bundle.zip, created withwebflow extension bundleafter a production build. The bundle must not exceed 5 MB and must not contain source maps. -
Only a workspace admin with two-factor authentication can use Publish extension version. Every upload is a new version; there is no rollback, and a revert is a rebuild of an earlier commit.
-
Test the upload with Launch App, never with Launch development app.
-
A private app uses the same submission and review with visibility set to private and is installed through a unique URL.
-
A Marketplace submission needs a testing site, review access, a demo video, a Preflight receipt and, for new or changed Designer Extensions, a review ZIP with the source maps of the exact build.
-
The guidelines cover least-privilege scopes, server-side tokens, disclosed and removable injected scripts, performance, accessibility and correct locale handling. Webflow aims to decide within 10 business days, and material changes go through an App Update.