Skip to content

sydpz/EyeToSpec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

👁 EyeToSpec

From your eye to a spec.
Drag UI elements where they look right, export the exact coordinates, and hand them to your AI coding agent.

Quickstart · How it works · Author a pack · MIT

EyeToSpec demo — drag, rotate, flip, export


The problem

AI coding agents write your UI, but they can't see it. Aligning a layout turns into round after round of typing positions in words:

"move the logo up a bit — no, too far — now center the button — smaller — undo that…"

You have the visual judgment. The agent has the hands. There's no clean channel between them for position.

EyeToSpec is that channel. Drag each element on a canvas until it looks right, hit export, and you get a compact coordinate JSON your agent can build against — precisely, in one pass.

Quickstart

No install, no build step. Just Python 3 (already on macOS and most Linux):

git clone https://github.com/sydpz/EyeToSpec.git
cd EyeToSpec
python3 serve.py

Your browser opens to the pack list. Click Search Home, drag the logo, search bar, and button into place, then hit 💾 Save. The coordinates land in output/search-home.json.

That file is the whole point — feed it to your agent:

"Lay out these elements using the normalized coordinates in output/search-home.json (cx/cy are the element center as a fraction of the canvas; w/h are size as a fraction of the canvas)."

How it works

An asset pack is a folder in config/ describing a canvas and the elements to place on it. EyeToSpec renders them, you arrange them, and it exports where they ended up — as normalized coordinates.

Why normalized (0–1) coordinates? Because they're resolution- and device-independent. cx: 0.5 means "horizontally centered" whether the target is a 720px phone screen or a 4K display. The agent multiplies by the real canvas size at build time.

{
  "logo":      { "cx": 0.5,  "cy": 0.18, "w": 0.45, "h": 0.13 },
  "searchbar": { "cx": 0.5,  "cy": 0.34, "w": 0.72, "h": 0.06 },
  "btn_search":{ "cx": 0.38, "cy": 0.46, "w": 0.24, "h": 0.05 }
}
  • cx / cy — element center, as a fraction of canvas width / height.
  • w / h — display size, as a fraction of canvas width / height.

Flat and literal: what you drag is exactly what lands in the JSON. No grouping, no folding, nothing to decode.

Rotation and flip

Beyond position and size, each element can be rotated (drag the top handle) and flipped horizontally or vertically (the ↔ / ↕ toggles in the inspector). These only appear in the export when they're set, so simple layouts stay clean:

{
  "btn_search": { "cx": 0.3, "cy": 0.52, "w": 0.3, "rotation": 60, "flipH": true, "flipV": true }
}
  • rotation — degrees clockwise (drag snaps to 15°; hold Shift for free rotation).
  • flipH / flipV — mirror left↔right / top↔bottom. Only emitted when true.

Flip matters when art has a direction: a sprite drawn facing right can't be rotated to face left without turning upside down — it has to be mirrored.

Three kinds of element

Kind In pack.json In the editor
Image "file": "logo.svg" scales by width, height locked to aspect
Text "file": null, "text": "Sign in" renders the real copy (WYSIWYG) at its font size/color
Box "file": null, no text a labeled placeholder you size freely (for code-drawn elements)

Scope

EyeToSpec does one thing: turn your visual judgment into a coordinate spec.

It deliberately does not cut your assets (that's your job — screenshot, export, or draw them) and does not wire the JSON into your code (that's your agent's job). One folder in, one JSON out. That narrowness is the point: it stays small, predictable, and easy to trust.

Author your own pack

  1. Make a folder under config/, e.g. config/login-screen/.
  2. Drop your cut assets in config/login-screen/assets/.
  3. Write a pack.json describing the canvas and elements.
  4. Restart serve.py — your pack appears in the list.

Want to align a real page? Screenshot any site, slice out the pieces you care about, drop them in a pack, and rebuild the layout by eye. The exported coordinates are yours to hand off.

See docs/pack-format.md for the full manifest format.

Use it from your phone

serve.py binds to your LAN by default, so you can drag a layout from a phone on the same wifi:

python3 serve.py            # note the "phone" URL it prints

Open that URL on your phone — drag and resize work with touch.

Note: the default --host 0.0.0.0 exposes the server to everyone on your local network (there's no auth — it's a personal dev tool). That's fine on a home/office wifi; on an untrusted network use --host 127.0.0.1 for local-only access, or an SSH tunnel.

Options

python3 serve.py --port 8771    # use a different port
python3 serve.py --no-open      # don't auto-open the browser
python3 serve.py --host 127.0.0.1   # local only (no phone access)

Reproducing the demo

The GIF above is scripted, not hand-recorded — see docs/media/record-demo.js (Playwright + ffmpeg). It's dev-only tooling; the tool itself has zero runtime dependencies.

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors