Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2026-06-11 13:27:43 +02:00
commit 70cbb65f9c
9 changed files with 146 additions and 79 deletions

View File

@ -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);
}

View File

@ -18,24 +18,30 @@ eleventyNavigation:
<p>Everything you need to know about how Penpot works.</p>
</a>
</li>
<li class="illus illus-contributing">
<a href="/contributing-guide/">
<h2>Contributing guide →</h2>
<p>How to report bugs, add translations and more.</p>
</a>
</li>
<li class="illus illus-techguide">
<a href="/technical-guide/">
<h2>Technical guide →</h2>
<p>Installation, configuration and architecture.</p>
</a>
</li>
<li class="illus illus-mcp">
<a href="/mcp/">
<h2>MCP server →</h2>
<p>Connect AI agents to your Penpot files for design and development workflows.</p>
</a>
</li>
<li class="illus illus-plugins">
<a href="/plugins/">
<h2>Plugins →</h2>
<p>All about Penpot plugins.</p>
</a>
</li>
<li class="illus illus-contributing">
<a href="/contributing-guide/">
<h2>Contributing guide →</h2>
<p>How to report bugs, add translations and more.</p>
</a>
</li>
<li class="illus illus-faq">
<a href="https://community.penpot.app/c/faq/17">
<h2>FAQs →</h2>

View File

@ -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
<figure>
<iframe
width="672px"
height="378px"
src="https://www.youtube.com/embed/hBn1iutWSq4?rel=0"
title="Penpot MCP Server: Remote Setup in 5 Min | OpenCode + OpenRouter"
frameborder="0"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen>
</iframe>
<figcaption>Penpot MCP Server Remote setup with OpenCode and OpenRouter</figcaption>
</figure>
<figure>
<iframe
width="672px"
height="378px"
src="https://www.youtube.com/embed/QeSFO0h7GGY?rel=0"
title="Penpot MCP Server Remote Setup in 1 Minute | Cursor"
frameborder="0"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen>
</iframe>
<figcaption>Penpot MCP Server Remote setup with Cursor</figcaption>
</figure>
<a id="use-remote"></a>
### 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
<figure>
<iframe
width="672px"
height="378px"
src="https://www.youtube.com/embed/xfgf0kKGOoc?rel=0"
title="Penpot MCP Server Local Setup"
frameborder="0"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen>
</iframe>
<figcaption>Penpot MCP Server Local setup</figcaption>
</figure>
<a id="connect-local"></a>
### Connect

View File

@ -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;

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -4873,7 +4873,7 @@ msgstr "What's the size of your company?"
#: src/app/main/ui/onboarding/questions.cljs:269
msgid "onboarding.questions.step3.title"
msgstr "Tell us about your job"
msgstr "What is your company size?"
#: src/app/main/ui/onboarding/questions.cljs:344
msgid "onboarding.questions.step4.title"
@ -4884,7 +4884,25 @@ msgstr "Where would you like to get started?"
msgid "onboarding.questions.step5.title"
msgstr "How did you hear about Penpot?"
#: src/app/main/ui/onboarding/questions.cljs:232
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"

View File

@ -4742,7 +4742,7 @@ msgstr "¿Cuál es el tamaño de tu empresa?"
#: src/app/main/ui/onboarding/questions.cljs:269
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:344
msgid "onboarding.questions.step4.title"
@ -4753,7 +4753,25 @@ msgstr "¿Por dónde te apetecería empezar?"
msgid "onboarding.questions.step5.title"
msgstr "¿Cómo nos has descubierto?"
#: src/app/main/ui/onboarding/questions.cljs:232
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"