From a8c1a673a8b39b90f4e0b5303da259ad72a74b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?andr=C3=A9s=20gonz=C3=A1lez?= Date: Thu, 11 Jun 2026 11:46:40 +0200 Subject: [PATCH 1/4] :books: Add MCP server block and setup videos to docs (#10121) --- docs/css/index.css | 3 +++ docs/index.njk | 18 +++++++++++------ docs/mcp/index.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/docs/css/index.css b/docs/css/index.css index 63282f168a..9737456609 100644 --- a/docs/css/index.css +++ b/docs/css/index.css @@ -848,6 +848,9 @@ a[href].post-tag:visited { .illus-techguide { background-image: url(/img/home-technical-guide.webp); } +.illus-mcp { + background-image: url(/img/home-mcp-server.webp); +} .illus-plugins { background-image: url(/img/home-plugins.webp); } diff --git a/docs/index.njk b/docs/index.njk index ef15854588..908d2f00b0 100644 --- a/docs/index.njk +++ b/docs/index.njk @@ -18,24 +18,30 @@ eleventyNavigation:

Everything you need to know about how Penpot works.

-
  • - -

    Contributing guide →

    -

    How to report bugs, add translations and more.

    -
    -
  • Technical guide →

    Installation, configuration and architecture.

  • +
  • + +

    MCP server →

    +

    Connect AI agents to your Penpot files for design and development workflows.

    +
    +
  • Plugins →

    All about Penpot plugins.

  • +
  • + +

    Contributing guide →

    +

    How to report bugs, add translations and more.

    +
    +
  • FAQs →

    diff --git a/docs/mcp/index.md b/docs/mcp/index.md index e0d31fe6ce..466144b3f1 100644 --- a/docs/mcp/index.md +++ b/docs/mcp/index.md @@ -309,6 +309,38 @@ For client-specific setup, use the shared section **Connect your MCP client**. For remote mode, use the URL shown in **Your account → Integrations → MCP Server**, which includes your `userToken`. +### Setup videos + +
    + +
    Penpot MCP Server – Remote setup with OpenCode and OpenRouter
    +
    + +
    + +
    Penpot MCP Server – Remote setup with Cursor
    +
    +
    ### Use @@ -391,6 +423,23 @@ Leave this terminal running while you use MCP. For advanced or repository-based workflows, see the [MCP README](https://github.com/penpot/penpot/blob/main/mcp/README.md) in the Penpot repository. +### Setup video + +
    + +
    Penpot MCP Server – Local setup
    +
    + ### Connect From 935fd85e9c9eef847a821bf970ed356d69168f51 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 11 Jun 2026 12:42:08 +0200 Subject: [PATCH 2/4] :bug: Fix exporter deps install script --- exporter/scripts/build | 1 + 1 file changed, 1 insertion(+) diff --git a/exporter/scripts/build b/exporter/scripts/build index 3daa2cf6f5..40eba8f44c 100755 --- a/exporter/scripts/build +++ b/exporter/scripts/build @@ -14,6 +14,7 @@ rm -rf target pnpm run build; cp pnpm-lock.yaml target/; +cp pnpm-workspace.yaml target/; cp package.json target/; touch target/pnpm-workspace.yaml; From 38d12b33634526173d51674c4d99c4cad7369fa6 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 11 Jun 2026 13:16:09 +0200 Subject: [PATCH 3/4] :sparkles: Add hard reload path for renderer menu A/B test (#10133) --- .../src/app/main/ui/workspace/main_menu.cljs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/main_menu.cljs b/frontend/src/app/main/ui/workspace/main_menu.cljs index d4d0dd9f28..20a50c729a 100644 --- a/frontend/src/app/main/ui/workspace/main_menu.cljs +++ b/frontend/src/app/main/ui/workspace/main_menu.cljs @@ -30,6 +30,7 @@ [app.main.data.workspace.versions :as dwv] [app.main.features :as features] [app.main.refs :as refs] + [app.main.repo :as rp] [app.main.store :as st] [app.main.ui.components.dropdown-menu :refer [dropdown-menu* dropdown-menu-item*]] @@ -938,15 +939,29 @@ (fn [event] (dom/stop-propagation event) (let [renderer (or (-> profile :props :renderer) :svg) - next-renderer (if (= renderer :wasm) :svg :wasm)] - (st/emit! (ev/event {::ev/name (if (= next-renderer :wasm) - "enable-webgl-rendering" - "disable-webgl-rendering") - ::ev/origin "workspace:menu"}) - (du/update-profile-props {:renderer next-renderer}) - (ntf/success (tr (if (= next-renderer :wasm) - "webgl.toast.webgl-render-enabled" - "webgl.toast.webgl-render-disabled"))))))) + next-renderer (if (= renderer :wasm) :svg :wasm) + ev-name (if (= next-renderer :wasm) + "enable-webgl-rendering" + "disable-webgl-rendering")] + (if (cf/external-feature-flag "renderer-hard-reload" "test") + ;; Bare RPC + hard reload: skips `du/update-profile-props`, so + ;; `features/recompute-features` is not run here; bootstrap + ;; after reload resolves render-wasm/v1 from the saved profile. + (do + (st/emit! (ev/event {::ev/name ev-name + ::ev/origin "workspace:menu"})) + (->> (rp/cmd! :update-profile-props {:props {:renderer next-renderer}}) + (rx/subs! (fn [_] (dom/reload-current-window true)) + (fn [_] + (st/emit! (ntf/error (tr "errors.generic"))))))) + ;; `update-profile-props` WatchEvent calls + ;; `features/recompute-features`. + (st/emit! (ev/event {::ev/name ev-name + ::ev/origin "workspace:menu"}) + (du/update-profile-props {:renderer next-renderer}) + (ntf/success (tr (if (= next-renderer :wasm) + "webgl.toast.webgl-render-enabled" + "webgl.toast.webgl-render-disabled")))))))) open-plugins-manager (mf/use-fn From 331e66c1c690693ea0ebbfa8f1c017fb2e4cfda2 Mon Sep 17 00:00:00 2001 From: Luis de Dios Date: Thu, 11 Jun 2026 13:23:41 +0200 Subject: [PATCH 4/4] :sparkles: Update company size options in in-app onboarding (#10110) --- .../src/app/main/ui/onboarding/questions.cljs | 75 ++++--------------- .../src/app/main/ui/onboarding/questions.scss | 2 +- frontend/translations/en.po | 20 ++++- frontend/translations/es.po | 20 ++++- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index d3974ed2f2..64fff7896e 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -208,53 +208,28 @@ [:and [:map {:title "QuestionsFormStep3"} [:team-size - [:enum "more-than-50" "31-50" "11-30" "2-10" "freelancer" "personal-project"]] - - [:planning ::sm/text] - - [:planning-other {:optional true} - [::sm/text {:max 512}]]] - - [:fn {:error/field :planning-other} - (fn [{:keys [planning planning-other]}] - (or (not= planning "other") - (and (= planning "other") - (not (str/blank? planning-other)))))]]) + [:enum "1" "2-100" "101-500" "501-1000" "1001-5000" "5001+"]]]]) (mf/defc step-3 {::mf/props :obj} [{:keys [on-next on-prev form show-step-3]}] (let [team-size-options (mf/with-memo [] - [{:label (tr "labels.select-option") :value "" :key "team-size" :disabled true} - {:label (tr "onboarding.questions.team-size.more-than-50") :value "more-than-50" :key "more-than-50"} - {:label (tr "onboarding.questions.team-size.31-50") :value "31-50" :key "31-50"} - {:label (tr "onboarding.questions.team-size.11-30") :value "11-30" :key "11-30"} - {:label (tr "onboarding.questions.team-size.2-10") :value "2-10" :key "2-10"} - {:label (tr "onboarding.questions.team-size.freelancer") :value "freelancer" :key "freelancer"} - {:label (tr "onboarding.questions.team-size.personal-project") :value "personal-project" :key "personal-project"}]) - - planning-options - (mf/with-memo [] - (-> (shuffle [{:label (tr "labels.select-option") - :value "" :key "questions:what-brings-you-here" - :disabled true} - {:label (tr "onboarding.questions.reasons.exploring") - :value "discover-more-about-penpot" - :key "discover-more-about-penpot"} - {:label (tr "onboarding.questions.reasons.fit") - :value "test-penpot-to-see-if-its-a-fit-for-team" - :key "test-penpot-to-see-if-its-a-fit-for-team"} - {:label (tr "onboarding.questions.reasons.alternative") - :value "alternative-to-figma" - :key "alternative-to-figma"} - {:label (tr "onboarding.questions.reasons.testing") - :value "try-out-before-using-penpot-on-premise" - :key "try-out-before-using-penpot-on-premise"}]) - (conj {:label (tr "labels.other-short") :value "other"}))) - - current-planning - (dm/get-in @form [:data :planning])] + [{:label (tr "labels.select-option") + :value "" :key "team-size" + :disabled true} + {:label (tr "onboarding.questions.team-size.just-me") + :value "1" :key "1"} + {:label (tr "onboarding.questions.team-size.2-100") + :value "2-100" :key "2-100"} + {:label (tr "onboarding.questions.team-size.101-500") + :value "101-500" :key "101-500"} + {:label (tr "onboarding.questions.team-size.501-1000") + :value "501-1000" :key "501-1000"} + {:label (tr "onboarding.questions.team-size.1001-5000") + :value "1001-5000" :key "1001-5000"} + {:label (tr "onboarding.questions.team-size.more-than-5001") + :value "5001+" :key "5001+"}])] [:& step-container {:form form :step 3 @@ -267,26 +242,8 @@ [:h1 {:class (stl/css :modal-title)} (tr "onboarding.questions.step3.title")] - [:div {:class (stl/css :modal-question)} - [:h3 {:class (stl/css :modal-subtitle)} - (tr "onboarding.questions.step1.question2")] - - [:& fm/select - {:options planning-options - :select-class (stl/css :select-class) - :default "" - :name :planning - :dropdown-class (stl/css :question-dropdown)}]] - - (when (= current-planning "other") - [:& fm/input {:name :planning-other - :class (stl/css :input-spacing) - :placeholder (tr "labels.other") - :show-error false - :label ""}]) [:div {:class (stl/css :modal-question)} - [:h3 {:class (stl/css :modal-subtitle)} (tr "onboarding.questions.step3.question3")] [:& fm/select {:options team-size-options :default "" :select-class (stl/css :select-class) diff --git a/frontend/src/app/main/ui/onboarding/questions.scss b/frontend/src/app/main/ui/onboarding/questions.scss index 9265788c98..4438dcc1fb 100644 --- a/frontend/src/app/main/ui/onboarding/questions.scss +++ b/frontend/src/app/main/ui/onboarding/questions.scss @@ -119,7 +119,7 @@ // STEP-3 .step-3 { - grid-template-rows: deprecated.$s-20 auto auto auto auto deprecated.$s-32; + grid-template-rows: deprecated.$s-20 auto auto deprecated.$s-32; } .image-radio { diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 5ee25e2d7b..2a89b87596 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -4314,7 +4314,7 @@ msgstr "What's the size of your company?" #: src/app/main/ui/onboarding/questions.cljs:270 msgid "onboarding.questions.step3.title" -msgstr "Tell us about your job" +msgstr "What is your company size?" #: src/app/main/ui/onboarding/questions.cljs:345 msgid "onboarding.questions.step4.title" @@ -4325,6 +4325,24 @@ msgstr "Where would you like to get started?" msgid "onboarding.questions.step5.title" msgstr "How did you hear about Penpot?" +msgid "onboarding.questions.team-size.just-me" +msgstr "Just me" + +msgid "onboarding.questions.team-size.2-100" +msgstr "2-100" + +msgid "onboarding.questions.team-size.101-500" +msgstr "101-500" + +msgid "onboarding.questions.team-size.501-1000" +msgstr "501-1,000" + +msgid "onboarding.questions.team-size.1001-5000" +msgstr "1,001-5,000" + +msgid "onboarding.questions.team-size.more-than-5001" +msgstr "5,001+" + #: src/app/main/ui/onboarding/questions.cljs:233 msgid "onboarding.questions.team-size.11-30" msgstr "11-30" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 3014b64d4d..24291c4d57 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -4222,7 +4222,7 @@ msgstr "¿Cuál es el tamaño de tu empresa?" #: src/app/main/ui/onboarding/questions.cljs:270 msgid "onboarding.questions.step3.title" -msgstr "Háblanos de tu trabajo" +msgstr "¿Cuál es el tamaño de tu empresa?" #: src/app/main/ui/onboarding/questions.cljs:345 msgid "onboarding.questions.step4.title" @@ -4233,6 +4233,24 @@ msgstr "¿Por dónde te apetecería empezar?" msgid "onboarding.questions.step5.title" msgstr "¿Cómo nos has descubierto?" +msgid "onboarding.questions.team-size.just-me" +msgstr "Sólo yo" + +msgid "onboarding.questions.team-size.2-100" +msgstr "2-100" + +msgid "onboarding.questions.team-size.101-500" +msgstr "101-500" + +msgid "onboarding.questions.team-size.501-1000" +msgstr "501-1000" + +msgid "onboarding.questions.team-size.1001-5000" +msgstr "1001-5000" + +msgid "onboarding.questions.team-size.more-than-5001" +msgstr "5001+" + #: src/app/main/ui/onboarding/questions.cljs:233 msgid "onboarding.questions.team-size.11-30" msgstr "11-30"