## User-facing features and how to test them
- Project Settings → Emails → Reply to has an info tooltip explaining
how its display name is used in visitor confirmation subjects and
messages, and when “Site Owner” is shown. Test it by hovering or
focusing the info icon.
- When a Form has no resources available for its Action, clicking the
Action + button explains that a resource must first be created in
Variables. Test it with a Form that has no action-capable resources,
then create a resource and verify it can be added to the Action.
- Success redirect is shown inside the Action control only when Resource
actions are connected. Test by switching between navigation mode and a
Form with a Resource action; the redirect field should appear only for
Resource actions, and its saved value should return when a Resource
action is added again.
- The Action control no longer offers Disable/Enable. Connected Resource
actions run in their configured order. The Form Action model has no
`enabled` field; older saved JSON with that extra key is read as an
ordinary connected action.
## Verification
- Focused UI test for the Reply to tooltip.
- Focused UI test for the empty Action resource tooltip.
- Manually verify Success redirect visibility and value retention while
switching modes.
- Manually verify all connected Actions execute in order, including
older saved Actions carrying an ignored `enabled` key.
## Review follow-up
- Address all current open code review comments on this PR, verify the
fixes, and reply to each addressed thread before resolving it.
## CI repair follow-up
- Inspect the latest failing checks on this PR, fix the causes on the
existing branch, and verify the affected checks locally and in CI.
## Follow-up audit (2026-10-14)
- Audited head `8fb0b44`, all inline review threads and the PR
conversation. The earlier Reply to tooltip comment was answered and
resolved. Two P1 comments remained: required boolean `enabled`
validation in CLI evaluations, and execution of saved disabled actions.
- `builder-e2e (shard-6)` failed because Preview returned `Disabled`
between `First` and `Last` in the configured failure results test. The
failure matches the security review finding. `builder-e2e (shard-2)` was
still in progress at audit start; the staging deployment workflow was
cancelled.
- The follow-up filters saved disabled actions from execution and
restores boolean `enabled` validation in both CLI evaluations. Builder
labels saved disabled actions. Focused SDK (55), CLI (222), and Builder
(45) tests, plus all three affected package typechecks, passed locally.
- Pushed `7c2b90e082`; replied to both P1 review threads, then resolved
them. Its main CI run passed all 25 test/check jobs, including all six
Builder E2E shards and the previously failing shard 6.
- A later P2 review identified stale CLI/MCP guidance. Commit
`160a9d1707` corrects the source and generated docs; focused docs tests
(12) and CLI typecheck pass locally. Replied to and resolved that
thread. On this latest head, the main CI run completed successfully: 27
check jobs passed, including all six Builder E2E shards; one
visual-regression job was skipped. All three required checks passed. The
automatically triggered staging deployment workflow was cancelled under
the no-deployment instruction.
## Input type default follow-up
- Show `text` as selected in the Props panel for both the HTML `input`
element and the Input component when their `type` prop is unset,
matching their rendered default. Verify both variants in the Builder and
retain explicit type choices.
## Current review-thread follow-up (2026-10-14)
- Recheck every unresolved review thread against the current PR head,
make and validate any required fixes, and reply with the resolution
before closing each thread. Keep this work on the existing PR branch; do
not deploy.
## Input type metadata follow-up (2026-10-14)
- Move the unset input `type` display default into component/element
property metadata for both the Input component and native HTML `input`
element. Remove the Props-panel special case, keep the implicit default
out of saved props, and cover both variants with regression tests.
- Run focused checks, push the fix to this PR, and cancel any
automatically triggered staging deployment workflow. Do not deploy
manually.
## Props metadata selector simplification follow-up (2026-10-15)
- Refactor `$selectedInstancePropsMetas` after the input default
metadata change. Preserve the current metadata, ordering, and attribute
override behavior while simplifying the selector's structure and
abstraction boundaries.
- Run focused checks, commit and push to this PR branch. Cancel any
automatically triggered staging deployment; do not deploy manually.
## Latest review follow-up (2026-10-15)
- Audit the latest PR head, all unresolved inline review threads, and
general PR comments. Address actionable feedback on this branch, run
focused validation, then reply and resolve each addressed thread. Cancel
any automatically triggered staging deployment; do not deploy manually.
## Form Action model decision (2026-10-15)
- Remove the Form Action `enabled` field completely from the type,
serialization, validation, execution, fixtures, and current docs. Accept
older saved JSON containing that extra key by ignoring it, including
`enabled: false`; action presence and valid IDs determine execution.
- Update the CLI evaluation to assert intended action IDs and order
without using `enabled`. Address the latest P2 review finding against
this model. Run focused checks, push on this PR branch, and cancel any
automatic staging deployment. No manual deployment.
## Action control visual follow-up (2026-10-15)
- Match the Form Action plus button to the established Variables section
plus button style and implementation where appropriate. Keep the
existing icon.
- Give the Action resource dropdown a stable width comparable to the
Variables resource dropdown, including when available resource names are
short.
- Add focused UI coverage, validate locally, commit and push to this PR
branch, and cancel any automatic staging deployment. Do not deploy
manually.
## Action plus hover follow-up (2026-10-15)
- Match the Action `+` button's hover and focus styling exactly to the
plus buttons in panels such as Variables. Compare their actual
implementations, preserve the existing icon, and add focused UI coverage
where appropriate.
- Run focused checks, commit and push to this PR branch. Cancel and
confirm any automatically triggered staging workflow; do not deploy
manually.
## Current CI fix (2026-10-15)
- Inspect the latest check rollup and failing job logs on the current PR
head. Fix all current failures on this branch, run focused local
validation, push the changes, and monitor the new head until checks
complete.
- Cancel and confirm any automatically triggered staging deployment. Do
not deploy manually.
Closes#5924Closes#5925Closes#5926Closes#5927Closes#5928Closes#5929
## Outcome
Makes MCP and CLI authoring predictable across project-wide CSS
variables, font uploads, retried asset uploads, destructive asset
selection, design-token collisions, and SVG HtmlEmbed edits.
## Delivered
### Project-global CSS variables
- [x] `define-css-variable` writes to `ROOT_INSTANCE_ID` / `:root`
instead of the home-page Body.
- [x] Breakpoint and overwrite behavior is preserved, and compact
results identify the root scope.
- [x] Existing body-local declarations remain untouched.
- [x] Runtime and Builder integration tests cover root selection and
generated project behavior.
### Font metadata and upload overrides
- [x] Static fonts prefer authoritative `OS/2.usWeightClass`.
- [x] Fallback matching normalizes spaces, hyphens, and underscores and
checks specific aliases before shorter ones.
- [x] Explicit format and partial metadata overrides travel through
HTTP, filesystem, and S3 upload paths and are validated after merging
with detected metadata.
- [x] Regression tests cover ExtraBold, Extra-Bold, Semi Bold Italic,
Ultra Light, valid weight classes, invalid weight classes, partial
overrides, and invalid overrides.
### Idempotent asset uploads
- [x] API uploads compute a project-scoped SHA-256 content hash.
- [x] Sequential and concurrent duplicate uploads reuse the existing
asset and return `deduplicated: true`.
- [x] `force: true` bypasses deduplication for intentional duplicates.
- [x] A partial unique index enforces one non-null content hash per
uploader project.
- [x] Stale reservations are cleaned up and active concurrent uploads
are bounded by polling and an actionable retry error.
- [x] HTTP, protocol, uploader, and CLI tests cover hash reuse,
uniqueness races, force propagation, and result markers.
The migration does not backfill historical files. Existing assets begin
participating in deduplication when uploaded through the new path;
matching content keeps the existing asset's metadata rather than
silently rewriting it.
### Consistent asset inputs and permissions output
- [x] `delete-asset` exposes exact `assetIds` and explicit
`assetIdPrefixes`.
- [x] The legacy `assetIdsOrPrefixes` input remains accepted and is
marked deprecated.
- [x] Exact ids no longer accidentally select longer prefixed ids.
- [x] `webstudio permissions` prints a readable role/capability summary
by default while `--json` remains unchanged for machine callers.
- [x] Help and discovery describe JSON output as optional.
- [x] Runtime, CLI, metadata, and generated-contract tests cover
canonical and compatibility behavior.
### Deterministic fragment design tokens
- [x] Fragment insertion reconciles incoming tokens against project
tokens and earlier tokens in the same fragment.
- [x] Equal name/style tokens are reused instead of creating suffixed
twins.
- [x] Same-name/different-style fragments require an explicit `ours`,
`theirs`, or `merge` policy at the public runtime boundary.
- [x] Builder's established internal paste behavior retains its explicit
incoming-value default.
- [x] `create-design-token` accepts documented CSS strings through the
property-aware CSS parser as well as typed style values.
- [x] Tests cover same-fragment reuse/conflicts, persisted tokens,
explicit policies, and CSS string parsing.
### Editable SVG HtmlEmbed content
- [x] HtmlEmbed validation uses parse5 parser errors and source
structure instead of serialization-string equality.
- [x] Valid inline SVG is accepted without silently normalizing authored
markup.
- [x] Fragment insertion now uses the same validator as prop update and
text replacement paths.
- [x] Malformed markup is rejected before mutation.
- [x] Regression tests cover realistic SVG, parser failures, and
no-partial-mutation behavior.
## Verification
- [x] `pnpm checks`: all workspace tests, typechecks, lint, package
boundaries, generated API/docs checks, and fixtures passed on the final
committed tree.
- [x] `pnpm --filter webstudio test:release-smoke`: packaged install,
compact comparison, preview, agent workflow, stdio MCP, and structured
commands passed.
- [x] Prisma schema validation passed with test connection variables.
- [x] Two minimally prompted weak-model subagents independently
exercised the changed CLI/MCP discovery and focused workflows.
- [x] The subagent-found stale `permissions --help` requirement was
fixed, regression-tested, and retested.
- [x] Final diff and worktree are clean.
## Summary
This update adds new MCP and CLI capabilities for project auditing,
structured data, project-specific agent instructions, focused project
search, safer bulk editing, image descriptions, font discovery, visual
verification, and external registry inspection.
## New Capabilities
### Audit projects
- Run a single `audit` command across accessibility, SEO, security,
assets, styles, and performance.
- Limit an audit to selected scopes, pages, or severity levels.
- Receive stable findings with locations and suggested fixes.
- Run rendered audits across desktop, mobile, and Builder breakpoint
widths.
- Detect horizontal overflow, broken images, oversized images, eager
below-fold images, render-blocking resources, and legacy font formats.
- Identify unused assets, tokens, CSS variables, local styles, and
breakpoints.
- Identify duplicate token declarations.
- Detect accessibility issues involving names, labels, headings,
landmarks, IDs, keyboard focus, ARIA, iframes, and autoplaying media.
- Detect SEO issues involving titles, descriptions, language, social
images, and structured data.
- Detect unsafe new-tab links and write resources exposed during page
rendering.
### Search an entire project
- Search project text, labels, props, resources, assets, and styles
through `search-project`.
- Find relevant records without downloading and reparsing the full
project snapshot.
- Scope searches to the relevant project-data areas.
### Add validated JSON-LD
- Add structured data with a dedicated JSON-LD component.
- Place JSON-LD inside the page Head Slot.
- Edit JSON in a purpose-built code editor.
- Prevent structurally invalid JSON-LD from being saved.
- Validate Schema.org types, properties, and values.
- Find invalid, missing, unknown, deprecated, or incompatible structured
data through the SEO audit.
- Let agents discover the correct JSON-LD workflow without using page
custom metadata or a generic HTML embed.
### Configure project-specific agent instructions
- Add AI-agent instructions from the new **Agents** section in Project
Settings.
- Synchronize those instructions into a managed root `AGENTS.md`.
- Update or remove the managed file automatically during project sync.
- Protect existing user-owned `AGENTS.md` files from being overwritten.
- Share the instructions with authenticated CLI and MCP agents.
- Keep agent instructions out of publicly readable production bundles.
### Generate and manage image descriptions
- Audit image assets for missing descriptions.
- Let a vision-capable agent inspect each image in its rendered context.
- Save generated descriptions to multiple image assets in one operation.
- Mark images as intentionally decorative.
- Reuse the saved asset description wherever the image is used.
- Re-run the audit to verify that missing-description findings are
resolved.
### Perform bounded bulk replacements
- Replace matching literal text across selected pages with
`replace-text`.
- Replace matching fixed prop text with `replace-prop-text`.
- Replace matching resource names or URLs with `replace-resource-text`.
- Restrict replacements by page, instance, prop, resource, field, match
mode, and maximum change count.
- Leave dynamic expressions unchanged.
### Inspect element ancestry
- Return an element’s direct parent in instance listings.
- Request the complete ancestor chain when inspecting an element.
- Understand tree placement without rebuilding the instance hierarchy
from raw project data.
### Discover available fonts
- List uploaded font families through `list-fonts`.
- Discover available system font stacks.
- Inspect font family, style, weight, format, and associated asset
information before applying typography.
### Inspect external component registries
- Inspect a local or remote shadcn-style registry item.
- Read its description, files, dependencies, targets, and documentation.
- Receive an explicit Webstudio compatibility report.
- Inspect registry metadata without installing or executing external
code.
### Capture generated project routes directly
- Run `webstudio screenshot --path /route` against the configured
project.
- Generate a temporary production-style preview automatically.
- Capture the requested route.
- Stop the temporary preview after capture.
- Avoid manually building and starting a preview for a single
screenshot.
### Assert visual changes
- Add expected text to screenshot comparisons.
- Set maximum pixel mismatch limits.
- Set minimum or maximum changed-region counts.
- Assert whether overall brightness or a color channel moved in the
expected direction.
- Use these assertions as pass/fail evidence for visual changes.
### Require compatible CLI versions
- Send the project-bundle contract version with CLI synchronization
requests.
- Stop incompatible CLI versions before they receive incomplete project
data.
- Tell users exactly how to update the CLI or run the latest version
once.
- Prevent older clients from silently dropping project settings.
## Upgrade Note
This branch introduces a new synchronized project-bundle contract. Older
CLI versions must update before synchronizing against the new API.
```sh
npm install -g webstudio@latest
```
Or run the latest version once:
```sh
npx webstudio@latest <command>
```
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Ref https://github.com/webstudio-is/webstudio/issues/3632
Here unflagged element component in components panel and html paste.
Additionally
- migrate link template to html element
- added :local-link state to links which is replaced with
[aria-current=page] when css is generated, sadly not yet supported in
any browser
- migrated many templates from legacy components to html elements
- put tailwind paste behind flag
Ref https://github.com/webstudio-is/webstudio/issues/3632
This is big one. So I switched to html elements whole forms section in
components. Though here I introduced some deviation from specification
**Textarea**
Initial value is represented as text content
```html
<textarea>content</textarea>
````
Though it is trickier to manage text content as state and all frameworks
rely on value property of textarea dom interface.
**Select**
Similar story. There is no value attribute and state is represented by
selected boolean attribute on options
```html
<select>
<option value="value1" selected></option>
<option value="value2"></option>
</select>
```
We replace selected attribute on option with value attribute on selected
when paste.
So basically all form elements are using "value" and "checked"
attributes which can be easily mapped to html and all frameworks.
Html elements can completely replace legacy typography components. Here
replace component templates with element templates as part of sdk.
- moved content block to general section
- moved separator into typography section
- moved code text into typography section and used regular `<code>`
element for it
- made "Text Content" setting expandable
- fixed dragging templates onto canvas.
<img width="475" alt="Screenshot 2025-05-21 at 11 27 27"
src="https://github.com/user-attachments/assets/ab53c5ec-e51f-498d-b01b-cc7f2eb20c2d"
/>
<img width="515" alt="Screenshot 2025-05-21 at 11 27 20"
src="https://github.com/user-attachments/assets/0f560c26-7e51-4025-a487-6f7e4e3f43e3"
/>
Here dropped legacy descriptions generated with AI. All attributes are
using descriptions scraped from html spec. Though many component
properties redefine these attributes without descriptions. So to
workaround just always fall back to attributes descriptions. Covers most
cases.
Ref https://github.com/webstudio-is/webstudio/issues/3632
Here enabled converting class -> className for all components with tags.
Now it does not affect anything though later will unlock using html
attributes instead of component props.
Also got rid from huge map with react properties and replaced it with a
set of proper aliases.
Here added lists of attributes from html and aria specifications for
future Element component.
Html provides an easy to navigate table with all types with relations to
specific tags and descriptions.
Aria list with types is extracted from aria-query library. Though
descriptions are parsed from specification. In the future we will use
more aria-query data to navigate specific roles.
All attributes types are tested with react types
You can see generated data in
- packages/html-data/src/__generated__/attributes.ts
- packages/html-data/src/__generated__/aria.ts
Succeeds https://github.com/webstudio-is/webstudio/pull/2341
Here replaced "embed" and "control" components with content model. Many
components now detect no content based on html content model like with
img or input tags. In other cases component meta can explicitly specify
empty array to not accept anything.
```
meta = {
contentModel: {
category: 'instance',
children: []
}
}
```
Ref https://github.com/webstudio-is/webstudio/issues/3632
This is a big step into native html elements support. I scraped content
model from html spec and now enforcing all html tags structure so we no
longer need to write custom restrictions.
Now paragraph cannot be nested into heading. Box cannot be nested into
span Text though still can in div Text. Any interactive elements cannot
be nested automatically. List item should have a list as direct parent
(collection and slot are exception because they don't have elements
inside).
Most rules are defined in this table
https://html.spec.whatwg.org/multipage/indices.html#elements-3
## Description
1. What is this PR about (link the issue and add a short description)
**Important** The PR adds tooltips only for HTML attributes.
Fixes https://github.com/webstudio-is/webstudio-builder/issues/2027
## Steps for reproduction
1. Add a few components to the canvas
3. Select one
4. Go to the Settings tab in the right sidebar
5. Hover over the labels
HTML attributes should show a tooltip with a description
## Code Review
- [ ] @taylornowotny please review the descriptions in the
props-descriptions.ts file
- test it on preview
- [ ] @istarkov check the first commit that is where the implementation
and integration are done. The idea behind this is that we have a central
file with HTML attributes descriptions and when generating components
props we pick the descriptions from there if the property doesn't have a
custom description. Essentially we use props-descriptions as a fallback.
Do we need tests for this feature?
## Before requesting a review
- [ ] made a self-review
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
---------
Co-authored-by: Giuseppe Gurgone <ggurgone@users.noreply.github.com>
Co-authored-by: istarkov <istarkov@gmail.com>