open-design/assets/frames
Sid 8bcd96f5e5
fix(frames): resolve relative screen= against embedder URL (#2316)
Shared device frames serve at /frames/<name>.html and previously
assigned the raw ?screen= value to the inner iframe.src. A
project-relative value like screen=screens/foo.html resolved against
/frames/, producing /frames/screens/foo.html (404), instead of the
embedding project's /api/projects/:id/raw/screens/foo.html.

The five frame HTML files now resolve relative ?screen= values
against document.referrer when present (the embedding project
preview), falling back to location.href so standalone /frames/*
loads keep working. Absolute and root-relative paths are passed
through unchanged.

Adds an e2e Vitest spec that evaluates each frame's inline <script>
in a Node vm and asserts iframe.src under five scenarios per file
(25 cases total): project-relative against referrer, root-relative
pass-through, absolute pass-through, empty referrer fallback, and
missing ?screen= no-op.

Fixes #2234
2026-05-20 10:03:01 +08:00
..
android-pixel.html fix(frames): resolve relative screen= against embedder URL (#2316) 2026-05-20 10:03:01 +08:00
browser-chrome.html fix(frames): resolve relative screen= against embedder URL (#2316) 2026-05-20 10:03:01 +08:00
ipad-pro.html fix(frames): resolve relative screen= against embedder URL (#2316) 2026-05-20 10:03:01 +08:00
iphone-15-pro.html fix(frames): resolve relative screen= against embedder URL (#2316) 2026-05-20 10:03:01 +08:00
macbook.html fix(frames): resolve relative screen= against embedder URL (#2316) 2026-05-20 10:03:01 +08:00
README.md Refactor project name from "Open Claude Design" to "Open Design" (#1) 2026-04-28 16:03:35 +08:00

Shared device frames

Reusable, pixel-accurate device chrome that any skill can compose into a multi-device or multi-screen layout. Each frame is a self-contained HTML snippet that renders a device shell and embeds its inner screen via an ` \`\`\`

In an OD-managed project, the recommended pattern is:

``` my-project/ ├── index.html ← gallery view: composes 3+ frames in a row ├── screens/ │ ├── home.html ← inner content rendered inside iphone-15-pro.html │ ├── search.html │ └── detail.html └── (no copy of frames — point at the shared assets folder) ```

Design tokens

Each frame reads its inner screen's tokens via `postMessage` if you want the bezel to tint with the active palette. The default state is "phone in hand" — neutral metallic — which works against any background.

Authoring rules

When extending this library:

  1. No external assets. Inline all SVG. No font imports. No image URLs.
  2. One frame per file. Don't bundle iPhone + Android in one HTML.
  3. `?screen=` query is the only contract. Don't introduce other query params; the harness has to be predictable for skills to use.
  4. The frame is decorative chrome only. All content lives in the inner screen file. The frame must work with ?screen=about:blank (showing just the device shell).
  5. Match real device dimensions. iPhone 15 Pro is 390×844 logical pixels. iPad Pro 11" is 834×1194. Don't ship a "looks like" frame — the seed has to match.