Fix the root cause in profile.cljs: remove the optimistic conj from
access-token-created and instead chain a fetch-access-tokens after the
create-access-token API call succeeds. This ensures all callers get a
fresh, server-consistent token list automatically.
Suggested-by: niwinz
Signed-off-by: kapilvus <kapil69265@gmail.com>
Co-authored-by: kapilvus <kapilvus@gmail.com>
Read PENPOT_TENANT env var (defaulting to "default") and embed it in
Redis Pub/Sub channel names as penpot.mcp.<tenant>.task.{req,res}.<id>.
This prevents cross-tenant interference when multiple environments share
a Redis instance, matching the backend convention
(e.g. penpot.rlimit.<tenant>.window.<name> in app.rpc.rlimit).
Co-authored-by: deepseek-v4-flash <deepseek-v4-flash@penpot.app>
- Convert .eleventy.js to eleventy.config.mjs (ESM) since
@11ty/eleventy-plugin-rss@3.0.0 is ESM-only
- Replace search-index.json.njk with search-index.json.11ty.js
to avoid async templateContent access in Nunjucks filters
- Update feed.njk to use new RSS plugin v3 filter names:
rssLastUpdatedDate -> getNewestCollectionItemDate | dateToRfc3339
rssDate -> dateToRfc3339
- Add 11ty.js to templateFormats for search index generation
* 🎉 Add background blur
* 🎉 Add test
* 🎉 Add background blur info to plugins API
* 🎉 Suport in wasm for both layer and background blur
* 🐛 Fix failing test
* ♻️ Fix comments
---------
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
When an organization invitation token is verified by a logged-out recipient
(e.g. an unregistered invitee opening the emailed link), profile-id is nil.
The team-invitation branch still evaluated get-org-membership eagerly, calling
nitrate with that nil profile-id. That request fails and surfaces as a generic
error, masking the clean :invalid-token response and dropping the user on the
login screen instead of the dedicated "Invite invalid" page.
Only query membership when a logged-in profile is present, so a canceled or
otherwise invalid org invite reaches the :invalid-token path as intended.
Use direct backbuffer tile compositing for render_sync_shape (viewer/thumbnails)
instead of the tile texture atlas cache, which left 512×512 transparent holes.
* ✨ Remove guides from svg overlay
* 🎉 Draw guides in wasm
* 🎉 Serialize guides to wasm
* ✨ Store separate and sorted horizontal and vertical guides
* 🎉 Implement collision detection with guides
* 🎉 Right click on guides to change color or remove
* ✨ Implement dragging guides
* 🎉 Edit wasm guides by double clicking them
* 🎉 Implement changing mouse cursor on hovering a guide
* ✨ Show guide pill on hover
* 🎉 Implement removing guide on hovering + Del
* 🔧 Fix lint + fmt errors
* 🎉 Clip out outer board guide lines
* ♻️ Extract common code into guide-pill* component
* 🎉 Draw dotted lines on hovering board guides
* 🐛 Fix board rotation when it has guides
* 🎉 Make foreign guides not visible in focus mode
The multi-input component did not handle paste events for
comma-separated values. When users pasted emails like
'qa@example.com, test@example.com', the entire string was
inserted as-is, triggering validation errors.
The on-key-down handler already split text on commas/spaces
when typing, but paste events bypassed this logic.
Added an on-paste handler that:
- Detects if pasted text contains commas or whitespace
- Splits the text by commas and/or whitespace
- Validates each part individually
- Adds valid items to the items list
- Prevents default paste behavior
- Resets input state after processing
Signed-off-by: Andrey Antukh <niwi@niwi.nz>