Design and build Canvely's responsive design editor from the frozen prompt, rules, document data, and requirements, including zoom around the pointer, shape-accurate selection, snapping, rotated resize, groups, and undo history without a canvas, drag-and-drop, or geometry library.
Difficulty: Hardweb-app · 3 outputs · 3 runs · 3 revisions · frozen 2026-09-25 14:50 UTC
One archived screenshot per published Run against version 1.0.0, of the Run’s representative Revision. Ordered by setup and then by repetition, not by quality.
Frozen with this version. Requirement IDs are stable across versions and are cited unchanged by evaluation records.
Automated checks are not an accessibility certification. Recorded axe findings describe what the tooling observed at capture time, on a pinned browser and viewport. A check that reports no violation is not proof that the interface is accessible, and a selector problem is inconclusive rather than an implementation failure.
| # | Model | Tool | Revision | Status | Actions |
|---|---|---|---|---|---|
| Fig. 01 | Claude Opus 5.5 (high) | Claude Code | 0 · initial | live | |
| Fig. 02 | GPT-6-Luna (max) | Codex CLI | 0 · initial | live | |
| Fig. 03 | GPT-6-Sol (high) | Codex CLI | 0 · initial | live |
Fig. 01Claude Opus 5.5 (high)
Fig. 02GPT-6-Luna (max)
Operator-attested: the Configuration, tool version, displayed model, and elapsed time were recorded by the operator from what the tool showed at Run time. They are not independently verified. An exact model ID appears only when the tool exposed one; it is never inferred.
Published sites are independent, AI-generated demos served from separate preview origins with local mock data. They are not products, and no UIBenchmark session data crosses to them.
Exact model ID, tool version, elapsed time, run state, stop reason, discarded attempts and every published Revision, repairs included, in run log order. Each Run and each Revision links to its own page.
01Run 1 · Claude Opus 5.5 (high) · Claude Code
Every Run here received exactly the frozen inputs of this version, so they form one cohort. Runs against another frozen version are listed on that version’s own page.
All published Runs of Canvely — Spring MenuDesign and build Canvely's responsive design editor from the frozen prompt, rules, document data, and requirements, including zoom around the pointer, shape-accurate selection, snapping, rotated resize, groups, and undo history without a canvas, drag-and-drop, or geometry library.
The workflow designs the interface itself from the frozen brief.
Read PROMPT.md and BENCHMARK_RULES.mdThis is the immutable Challenge Version: the exact inputs every Run against it received. Frozen inputs never change, so an older Run stays readable against precisely the brief it was given.
Both are shown as the stored source text, unrendered and unedited, so what you read is byte-for-byte what the frozen version contains.
Launch prompt
The prompt submitted at the start of every Run against this version.
# Canvely — Spring Menu Build the editor of **Canvely**, a fictional browser-based design tool for layouts and marketing graphics. The open file is **Hazel & Rye — Spring Menu** in the workspace **Orchard Studio**. ## Product - **Name:** Canvely. - **Feel:** precise, quiet, professional. Designers keep it open all day, so the canvas is the focus and the interface around it stays calm and dense. Every direct manipulation must feel exact: things land where the pointer says they land. - **You own the visual identity.** Design the Canvely wordmark/logo, color palette, type scale, icons, selection handles, guides, and layout yourself; nothing is prescribed. Any graphics you need must be created in this workspace (inline SVG or CSS). There is no supplied photography. - **Microcopy is part of the task.** Write all interface copy yourself: tooltips, empty states, validation messages, confirmations, and the explanations shown when an action is not possible. ## Data `public/data/document.json` holds the product, workspace, and file names and the layer tree of the file. Use it as the initial document. Do not add, remove, or rename supplied layers in the initial state. The layer model: - **Layer types:** `frame`, `group`, `rect`, `ellipse`, and `text`. Every layer has an `id`, a `name`, `visible`, and `locked`. - **Stacking:** every `children` array is ordered back to front. The last child is drawn on top. - **Frames** never appear inside other layers. Their `x` and `y` are canvas coordinates. A frame has a fill, clips its children to its bounds, and shows its name on the canvas. The supplied top level holds only frames. - **Coordinates:** `x` and `y` of every layer inside a frame are relative to that frame's top-left corner. Groups do not create their own coordinate space. Layers at the top level use canvas coordinates. - **Geometry:** `x`, `y`, `width`, and `height` describe the unrotated box. `rotation` is in degrees, clockwise, around the box center. - **Groups** store no geometry of their own. A group's bounds are the axis-aligned bounds of its children after rotation. - **Rectangles** have `fill`, `opacity`, `corner_radius`, and an optional `stroke` (`color` and `width`, drawn inside the bounds). **Ellipses** have `fill` and `opacity`. - **Text** has `text`, `font_size`, `font_weight`, `line_height` (a multiplier), `align`, `fill` (the text color), and `opacity`. Text wraps within its width and starts at the top of its box. Text that does not fit the box height overflows below it and is not clipped, except by its frame. Use the system font stack. - **Hidden and locked:** `visible: false` layers are not drawn. `locked: true` layers are drawn but cannot be selected, moved, resized, or rotated on the canvas, or moved with arrow keys. They can still be selected through their row, then edited in the properties panel, duplicated, or deleted. Hiding or locking a frame or group applies to everything inside it. ## Editor One application screen with: 1. **App frame:** the Canvely wordmark you design, the workspace name, and the file name. 2. **Toolbar:** the Move, Rectangle, Ellipse, and Text tools, undo and redo, the zoom level, and a “reset demo” action. 3. **Layers panel:** the layer tree. 4. **Canvas:** the frames and their layers. 5. **Properties panel:** the properties of the current selection. 6. **Fictional notice:** the note “Canvely is a fictional product created for UIBenchmark.” (verbatim, must be visible). ## Canvas and view - On first load the view fits all three frames. - **Zoom** ranges from 10% to 800%. Ctrl/Cmd + wheel zooms around the pointer: the document point under the pointer stays under the pointer. Browsers report trackpad pinch the same way. This must never zoom the browser page itself. Visible controls zoom in, zoom out, fit all content, and reset to 100%. The current zoom is shown as a percentage. - **Pan** with the wheel or trackpad scroll, and by dragging while holding Space. ## Selection - A click selects the topmost visible, unlocked layer under the pointer. Hit-testing follows each layer's real shape: the rotated box for rectangles and text (rounded corners may count as inside), the ellipse for ellipses. A click inside a rotated layer's bounding box but outside its rotated outline does not select it. - A click on a frame's empty area does not select the frame. A frame is selected by clicking its name on the canvas or its row in the layers panel. - A click on a layer inside a group selects the outermost group inside the frame, or at the top level. A double-click selects one level deeper toward the layer under the pointer. While a layer inside a group is selected, whether by double-click or through its row, a click on a layer inside that layer's parent group selects at the same depth; a click outside it starts again at the outermost level. - Escape selects the parent group. When a frame, a direct child of a frame, or a top-level layer is selected, Escape clears the selection. - Shift+click adds a layer to the selection or removes it. - Dragging on an empty spot starts a marquee. Hidden and locked layers count as empty. A marquee started inside a frame selects the visible, unlocked direct children of that frame it intersects (a group counts as one layer). A marquee started outside all frames selects the frames and top-level layers it intersects. ## Editing - **Move:** dragging a selection moves it exactly with the pointer at every zoom level, apart from snapping. A frame moves by dragging its name. Moving a group or frame moves everything inside it. While focus is not in the layers panel or a text field, Arrow keys move the selection by 1 px and Shift+Arrow by 10 px, in document units. - **Snapping:** while dragging, the selection's edges and center snap to the edges and centers of its sibling layers and of its parent frame when they are within about 5 screen pixels. A guide line shows each active snap and disappears when the drag ends. - **Resize:** a single selected layer shows eight resize handles. Dragging a handle keeps the opposite edge or corner fixed. Shift keeps the aspect ratio. Alt/Option resizes symmetrically around the center. Width and height stop at 1 px; layers never flip. The current width and height are shown while resizing. Resizing text changes its box, and the text rewraps at the same font size. Resizing a frame changes only the frame; its children keep their positions relative to its top-left corner. - **Rotated layers:** handles follow the rotated outline. Resizing works along the layer's own axes, keeps the opposite corner or edge fixed on screen, and leaves the rotation unchanged. - **Multiple layers and groups:** a multi-selection shows one bounding box. Resizing it, or resizing a group, scales the position and size of each contained layer proportionally within that box. - **Rotate:** a single selected rectangle, ellipse, or text layer rotates around its center by dragging just outside a corner handle or a dedicated rotation handle. Shift snaps to 15° steps. The angle is shown while rotating. Frames and groups do not need rotation. - **Properties panel:** for one selected layer it shows and edits X, Y, W, H, rotation, opacity, and fill color, plus corner radius for rectangles and font size for text. Frames show X, Y, W, H, and fill. Groups show X, Y, W, and H of their bounds; changing them moves or scales the children. X and Y are relative to the parent frame (canvas coordinates for top-level layers). A value applies on Enter or when the field loses focus. Invalid input is rejected and the previous value is restored: non-numeric input, W or H below 1, opacity outside 0–100%, a negative corner radius, a font size below 1, or an invalid hex color. The fields update live while the layer is changed on the canvas. - **Mixed values:** for a multi-selection, each shared property shows the common value, or a clear “Mixed” state when the values differ. Entering a value applies it to every selected layer. ## Structure - **Layers panel:** shows the full tree with the topmost layer of each parent listed first. Every row shows the layer type and name. Frames and groups expand and collapse. Arrow keys move between rows while focus is in the panel. Selection is synchronized in both directions: a canvas selection highlights and reveals its row. Rows can be renamed in place; an empty name keeps the previous name. Every row can toggle visibility and lock. - **Layer order:** dragging a row reorders the layer among its siblings, and the canvas stacking follows. Bring forward and send backward move the selection one step, through a visible control and with the shortcuts below. - **Create:** the Rectangle, Ellipse, and Text tools create a layer by dragging on the canvas, or at a default size by clicking. Shift constrains rectangles and ellipses to a square or circle. A layer drawn over a frame becomes that frame's topmost child; a layer drawn outside all frames becomes a top-level layer. After creating, the tool returns to Move and the new layer is selected. Name new layers by type with an increasing number, for example “Rectangle 1”. - **Text editing:** a double-click on a text layer edits it when the text layer itself is selected or sits directly in a frame; inside a group, the double-clicks first select one level deeper as described above. Enter with a text layer selected also edits it. Editing happens in place on the canvas, at the layer's position, size, zoom level, and rotation. Escape or a click outside commits. A new text layer starts in text editing. Committing empty text removes the text layer. - **Groups:** grouping two or more selected siblings creates a selected group at the stacking position of the topmost selected layer. Ungrouping keeps the children selected, in place, and in stacking order. Frames, and layers with different parents, cannot be grouped, and the interface explains why. - **Duplicate and delete:** duplicate copies the selection, including all children of groups and frames. Each copy lands 10 px right and 10 px down, directly above its original, and the copies become the selection. Delete removes the selection. Both are also available through a visible control. ## History and persistence - **Undo and redo** cover at least 50 steps, through visible controls and the shortcuts below. Every completed change is exactly one step, however many pointer events it took: move, resize, rotation, property edit, reorder, group, ungroup, rename, visibility or lock change, creation, deletion, duplication, and one text-editing session. Each Arrow key press is one step. Creating a text layer and its first text-editing session together are one step; a new text layer committed empty leaves no step. Selection and view changes are not steps. A new change after an undo clears the redo history. - **Persistence:** the document survives a page reload using local storage. A “reset demo” action restores the supplied document and clears the history after a confirmation step. ## Keyboard shortcuts Shortcuts refer to a US-English keyboard layout. | Action | Shortcut | |---|---| | Move, Rectangle, Ellipse, Text tool | V, R, O, T | | Undo / redo | Ctrl/Cmd+Z / Ctrl/Cmd+Shift+Z | | Duplicate | Ctrl/Cmd+D | | Delete | Delete or Backspace | | Group / ungroup | Ctrl/Cmd+G / Ctrl/Cmd+Shift+G | | Bring forward / send backward | Ctrl/Cmd+] / Ctrl/Cmd+[ | | Move by 1 px / 10 px | Arrow keys / Shift+Arrow keys | | Zoom to fit all content / zoom to 100% | Shift+1 / Shift+0 | | Edit text | Enter or double-click | | Select parent / clear selection | Escape | | Pan | Space+drag | Shortcuts must not fire while the user types in a text field or edits text on the canvas. Where a shortcut matches a browser shortcut, the editor action wins. ## Constraints - Responsive at 1440×900 (desktop) and 390×844 (mobile). At mobile width the document must not overflow horizontally. The canvas stays visible. With touch input, a one-finger drag on empty canvas pans instead of drawing a marquee, and the visible controls zoom. Layers can be selected by tapping the canvas or through the layers panel, the properties of the selection can be edited, and undo and redo stay reachable. Resize and rotation handles are not required at mobile width. - Every control is reachable by keyboard, has a visible focus indicator and an accessible name. - No canvas, drawing, drag-and-drop, or geometry library is installed and none may be added: build everything with React and browser APIs. The rendering technique (DOM, SVG, or `<canvas>`) is your choice. - Respect reduced-motion preferences for any animation you add. - No external network requests, fonts, or images. System font stack only. See `BENCHMARK_RULES.md` for binding rules and `REQUIREMENTS.json` for the behaviors that will be evaluated.
Shared rules
The rules every Configuration worked under for this version.
# Benchmark rules (shared, v4)
These rules are binding and identical for every Configuration.
## Allowed
- The supplied starter, images, data files, and installed dependencies.
- Additional graphics you create yourself inside this workspace (inline SVG,
CSS art, or authored SVG files).
- Local development preview while working.
- The provided local test browser (headless Chromium with Playwright) at
`/opt/uibench/browser`: `import { chromium, launch } from
"/opt/uibench/browser/launch.mjs"` in a Node script, or run
`/opt/uibench/browser/bin/uibench-screenshot <url> <file.png>`. Use it only
against your own local preview on `localhost` or `127.0.0.1`.
- Building, testing, and correcting your implementation before completion.
## Required
- Browser-compatible production output under `dist/` via the starter's build
script, deployable at a hostname root.
- Implement required interactions as working behavior.
- Responsive behavior at 1440×900 and 390×844.
- Keep demo state in memory or origin-scoped local storage; no cookies.
- Required forms, if any, simulate behavior locally and never transmit data.
- All navigation stays within the demo.
## Prohibited
- Modifying `BENCHMARK_RULES.md`, `PROMPT.md`, `REQUIREMENTS.json`,
`AGENTS.md`, `CLAUDE.md`, or the dependency lockfile.
- Delegating any part of the work to subagents, sub-sessions, or spawned
agent tasks; complete the task in this single session.
- Adding, removing, or updating dependencies.
- External network resources of any kind: requests, fonts, images, embeds,
analytics, service workers, or background requests, including external
navigations or requests made through the provided test browser.
- Researching on the web while you work: searching the web or fetching web
pages or online documentation.
- Generating images with an image-generation tool or model.
- Backend services, databases, credentials, payments, or personal data.
- Deploying the result or accessing deployment credentials.
## Completion
Remove generated self-test artifacts (screenshots and test scripts) from
`dist/` before completion.
Before declaring completion, run the production build. In your final response,
state whether it succeeded and identify any incomplete requirements.
The declared rules and viewports this version was executed and captured under.
Fig. 03GPT-6-Sol (high)
02Run 1 · GPT-6-Luna (max) · Codex CLI
03Run 1 · GPT-6-Sol (high) · Codex CLI
Discarded attempts failed for a technical reason — a crashed session, a tool outage, a broken upload — and were discarded and retried from the same frozen inputs. The count is not a quality signal.
Generation cost: Not separately metered. Runs were executed on the operator’s personal tool subscriptions, which do not itemize a per-Run charge. No amount is attributed, and no zero-cost claim is made.
Starter SHA-256
aa2276a44780653d1147ac1eb10925e101c37b45fe6406afc268fc2d15db4a73
Asset pack SHA-256
4794e27a536d59f148e0ab852c3621dd269495ace6fe92b47a826013140cb278